2016-08-16 01:19:07 +08:00
|
|
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
2012-04-19 00:44:44 +08:00
|
|
|
; This test makes sure that shift instructions are properly eliminated
|
2007-03-24 05:57:47 +08:00
|
|
|
; even with arbitrary precision integers.
|
2012-04-19 01:01:26 +08:00
|
|
|
; RUN: opt < %s -instcombine -S | FileCheck %s
|
2007-03-24 05:57:47 +08:00
|
|
|
|
|
|
|
define i55 @test6(i55 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test6(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = mul i55 %A, 6
|
|
|
|
; CHECK-NEXT: ret i55 [[C]]
|
|
|
|
;
|
|
|
|
%B = shl i55 %A, 1
|
|
|
|
%C = mul i55 %B, 3
|
|
|
|
ret i55 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2017-02-10 07:13:04 +08:00
|
|
|
; (X * C2) << C1 --> X * (C2 << C1)
|
|
|
|
|
Reapply r155136 after fixing PR12599.
Original commit message:
Defer some shl transforms to DAGCombine.
The shl instruction is used to represent multiplication by a constant
power of two as well as bitwise left shifts. Some InstCombine
transformations would turn an shl instruction into a bit mask operation,
making it difficult for later analysis passes to recognize the
constsnt multiplication.
Disable those shl transformations, deferring them to DAGCombine time.
An 'shl X, C' instruction is now treated mostly the same was as 'mul X, C'.
These transformations are deferred:
(X >>? C) << C --> X & (-1 << C) (When X >> C has multiple uses)
(X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2) (When C2 > C1)
(X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2) (When C1 > C2)
The corresponding exact transformations are preserved, just like
div-exact + mul:
(X >>?,exact C) << C --> X
(X >>?,exact C1) << C2 --> X << (C2-C1)
(X >>?,exact C1) << C2 --> X >>?,exact (C1-C2)
The disabled transformations could also prevent the instruction selector
from recognizing rotate patterns in hash functions and cryptographic
primitives. I have a test case for that, but it is too fragile.
llvm-svn: 155362
2012-04-24 01:39:52 +08:00
|
|
|
define i55 @test6a(i55 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test6a(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = mul i55 %A, 6
|
|
|
|
; CHECK-NEXT: ret i55 [[C]]
|
|
|
|
;
|
|
|
|
%B = mul i55 %A, 3
|
|
|
|
%C = shl i55 %B, 1
|
|
|
|
ret i55 %C
|
Reapply r155136 after fixing PR12599.
Original commit message:
Defer some shl transforms to DAGCombine.
The shl instruction is used to represent multiplication by a constant
power of two as well as bitwise left shifts. Some InstCombine
transformations would turn an shl instruction into a bit mask operation,
making it difficult for later analysis passes to recognize the
constsnt multiplication.
Disable those shl transformations, deferring them to DAGCombine time.
An 'shl X, C' instruction is now treated mostly the same was as 'mul X, C'.
These transformations are deferred:
(X >>? C) << C --> X & (-1 << C) (When X >> C has multiple uses)
(X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2) (When C2 > C1)
(X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2) (When C1 > C2)
The corresponding exact transformations are preserved, just like
div-exact + mul:
(X >>?,exact C) << C --> X
(X >>?,exact C1) << C2 --> X << (C2-C1)
(X >>?,exact C1) << C2 --> X >>?,exact (C1-C2)
The disabled transformations could also prevent the instruction selector
from recognizing rotate patterns in hash functions and cryptographic
primitives. I have a test case for that, but it is too fragile.
llvm-svn: 155362
2012-04-24 01:39:52 +08:00
|
|
|
}
|
|
|
|
|
2017-02-10 07:13:04 +08:00
|
|
|
; (X * C2) << C1 --> X * (C2 << C1)
|
|
|
|
|
|
|
|
define <2 x i55> @test6a_vec(<2 x i55> %A) {
|
|
|
|
; CHECK-LABEL: @test6a_vec(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = mul <2 x i55> %A, <i55 6, i55 48>
|
|
|
|
; CHECK-NEXT: ret <2 x i55> [[C]]
|
|
|
|
;
|
|
|
|
%B = mul <2 x i55> %A, <i55 3, i55 12>
|
|
|
|
%C = shl <2 x i55> %B, <i55 1, i55 2>
|
|
|
|
ret <2 x i55> %C
|
|
|
|
}
|
|
|
|
|
2007-03-24 05:57:47 +08:00
|
|
|
define i29 @test7(i8 %X) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test7(
|
|
|
|
; CHECK-NEXT: ret i29 -1
|
|
|
|
;
|
|
|
|
%A = zext i8 %X to i29
|
|
|
|
%B = ashr i29 -1, %A
|
|
|
|
ret i29 %B
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i7 @test8(i7 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test8(
|
|
|
|
; CHECK-NEXT: ret i7 0
|
|
|
|
;
|
|
|
|
%B = shl i7 %A, 4
|
|
|
|
%C = shl i7 %B, 3
|
|
|
|
ret i7 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i17 @test9(i17 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test9(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i17 %A, 1
|
|
|
|
; CHECK-NEXT: ret i17 [[B]]
|
|
|
|
;
|
|
|
|
%B = shl i17 %A, 16
|
|
|
|
%C = lshr i17 %B, 16
|
|
|
|
ret i17 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2017-01-16 07:45:03 +08:00
|
|
|
; shl (lshr X, C), C --> and X, C'
|
|
|
|
|
|
|
|
define i19 @test10(i19 %X) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test10(
|
2017-01-16 07:45:03 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = and i19 %X, -262144
|
|
|
|
; CHECK-NEXT: ret i19 [[SH1]]
|
|
|
|
;
|
|
|
|
%sh1 = lshr i19 %X, 18
|
|
|
|
%sh2 = shl i19 %sh1, 18
|
|
|
|
ret i19 %sh2
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; Two right shifts in the same direction:
|
2017-01-17 03:23:34 +08:00
|
|
|
; lshr (lshr X, C1), C2 --> lshr X, C1 + C2
|
2017-01-16 07:45:03 +08:00
|
|
|
|
2017-01-17 03:23:34 +08:00
|
|
|
define <2 x i19> @lshr_lshr_splat_vec(<2 x i19> %X) {
|
|
|
|
; CHECK-LABEL: @lshr_lshr_splat_vec(
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = lshr <2 x i19> %X, <i19 5, i19 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i19> [[SH1]]
|
2016-08-16 01:19:07 +08:00
|
|
|
;
|
2017-01-17 03:23:34 +08:00
|
|
|
%sh1 = lshr <2 x i19> %X, <i19 3, i19 3>
|
|
|
|
%sh2 = lshr <2 x i19> %sh1, <i19 2, i19 2>
|
2017-01-16 07:45:03 +08:00
|
|
|
ret <2 x i19> %sh2
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2017-02-02 05:38:32 +08:00
|
|
|
define i9 @multiuse_lshr_lshr(i9 %x) {
|
|
|
|
; CHECK-LABEL: @multiuse_lshr_lshr(
|
2017-02-02 05:31:34 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = lshr i9 %x, 2
|
|
|
|
; CHECK-NEXT: [[SH2:%.*]] = lshr i9 %x, 5
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul i9 [[SH1]], [[SH2]]
|
|
|
|
; CHECK-NEXT: ret i9 [[MUL]]
|
|
|
|
;
|
|
|
|
%sh1 = lshr i9 %x, 2
|
|
|
|
%sh2 = lshr i9 %sh1, 3
|
|
|
|
%mul = mul i9 %sh1, %sh2
|
|
|
|
ret i9 %mul
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i9> @multiuse_lshr_lshr_splat(<2 x i9> %x) {
|
|
|
|
; CHECK-LABEL: @multiuse_lshr_lshr_splat(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = lshr <2 x i9> %x, <i9 2, i9 2>
|
|
|
|
; CHECK-NEXT: [[SH2:%.*]] = lshr <2 x i9> %x, <i9 5, i9 5>
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i9> [[SH1]], [[SH2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i9> [[MUL]]
|
|
|
|
;
|
|
|
|
%sh1 = lshr <2 x i9> %x, <i9 2, i9 2>
|
|
|
|
%sh2 = lshr <2 x i9> %sh1, <i9 3, i9 3>
|
|
|
|
%mul = mul <2 x i9> %sh1, %sh2
|
|
|
|
ret <2 x i9> %mul
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; Two left shifts in the same direction:
|
2017-01-17 03:23:34 +08:00
|
|
|
; shl (shl X, C1), C2 --> shl X, C1 + C2
|
|
|
|
|
|
|
|
define <2 x i19> @shl_shl_splat_vec(<2 x i19> %X) {
|
|
|
|
; CHECK-LABEL: @shl_shl_splat_vec(
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl <2 x i19> %X, <i19 5, i19 5>
|
|
|
|
; CHECK-NEXT: ret <2 x i19> [[SH1]]
|
2017-01-17 03:23:34 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl <2 x i19> %X, <i19 3, i19 3>
|
|
|
|
%sh2 = shl <2 x i19> %sh1, <i19 2, i19 2>
|
|
|
|
ret <2 x i19> %sh2
|
|
|
|
}
|
|
|
|
|
2017-02-02 05:31:34 +08:00
|
|
|
define i42 @multiuse_shl_shl(i42 %x) {
|
|
|
|
; CHECK-LABEL: @multiuse_shl_shl(
|
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl i42 %x, 8
|
|
|
|
; CHECK-NEXT: [[SH2:%.*]] = shl i42 %x, 17
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul i42 [[SH1]], [[SH2]]
|
|
|
|
; CHECK-NEXT: ret i42 [[MUL]]
|
|
|
|
;
|
|
|
|
%sh1 = shl i42 %x, 8
|
|
|
|
%sh2 = shl i42 %sh1, 9
|
|
|
|
%mul = mul i42 %sh1, %sh2
|
|
|
|
ret i42 %mul
|
|
|
|
}
|
|
|
|
|
2017-02-02 05:38:32 +08:00
|
|
|
define <2 x i42> @multiuse_shl_shl_splat(<2 x i42> %x) {
|
|
|
|
; CHECK-LABEL: @multiuse_shl_shl_splat(
|
2017-02-02 05:31:34 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl <2 x i42> %x, <i42 8, i42 8>
|
|
|
|
; CHECK-NEXT: [[SH2:%.*]] = shl <2 x i42> %x, <i42 17, i42 17>
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i42> [[SH1]], [[SH2]]
|
|
|
|
; CHECK-NEXT: ret <2 x i42> [[MUL]]
|
|
|
|
;
|
|
|
|
%sh1 = shl <2 x i42> %x, <i42 8, i42 8>
|
|
|
|
%sh2 = shl <2 x i42> %sh1, <i42 9, i42 9>
|
|
|
|
%mul = mul <2 x i42> %sh1, %sh2
|
|
|
|
ret <2 x i42> %mul
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; Equal shift amounts in opposite directions become bitwise 'and':
|
2017-01-17 03:23:34 +08:00
|
|
|
; lshr (shl X, C), C --> and X, C'
|
|
|
|
|
|
|
|
define <2 x i19> @eq_shl_lshr_splat_vec(<2 x i19> %X) {
|
|
|
|
; CHECK-LABEL: @eq_shl_lshr_splat_vec(
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = and <2 x i19> %X, <i19 65535, i19 65535>
|
|
|
|
; CHECK-NEXT: ret <2 x i19> [[SH1]]
|
2017-01-17 03:23:34 +08:00
|
|
|
;
|
|
|
|
%sh1 = shl <2 x i19> %X, <i19 3, i19 3>
|
|
|
|
%sh2 = lshr <2 x i19> %sh1, <i19 3, i19 3>
|
|
|
|
ret <2 x i19> %sh2
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; Equal shift amounts in opposite directions become bitwise 'and':
|
2017-01-17 03:23:34 +08:00
|
|
|
; shl (lshr X, C), C --> and X, C'
|
|
|
|
|
|
|
|
define <2 x i19> @eq_lshr_shl_splat_vec(<2 x i19> %X) {
|
|
|
|
; CHECK-LABEL: @eq_lshr_shl_splat_vec(
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = and <2 x i19> %X, <i19 -8, i19 -8>
|
|
|
|
; CHECK-NEXT: ret <2 x i19> [[SH1]]
|
2017-01-17 03:23:34 +08:00
|
|
|
;
|
|
|
|
%sh1 = lshr <2 x i19> %X, <i19 3, i19 3>
|
|
|
|
%sh2 = shl <2 x i19> %sh1, <i19 3, i19 3>
|
|
|
|
ret <2 x i19> %sh2
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; In general, we would need an 'and' for this transform, but the masked-off bits are known zero.
|
2017-01-17 03:23:34 +08:00
|
|
|
; shl (lshr X, C1), C2 --> lshr X, C1 - C2
|
|
|
|
|
|
|
|
define <2 x i7> @lshr_shl_splat_vec(<2 x i7> %X) {
|
|
|
|
; CHECK-LABEL: @lshr_shl_splat_vec(
|
|
|
|
; CHECK-NEXT: [[MUL:%.*]] = mul <2 x i7> %X, <i7 -8, i7 -8>
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = lshr exact <2 x i7> [[MUL]], <i7 1, i7 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i7> [[SH1]]
|
2017-01-17 03:23:34 +08:00
|
|
|
;
|
|
|
|
%mul = mul <2 x i7> %X, <i7 -8, i7 -8>
|
|
|
|
%sh1 = lshr exact <2 x i7> %mul, <i7 3, i7 3>
|
|
|
|
%sh2 = shl nuw nsw <2 x i7> %sh1, <i7 2, i7 2>
|
|
|
|
ret <2 x i7> %sh2
|
|
|
|
}
|
|
|
|
|
2017-01-17 03:35:45 +08:00
|
|
|
; In general, we would need an 'and' for this transform, but the masked-off bits are known zero.
|
2017-01-17 03:23:34 +08:00
|
|
|
; lshr (shl X, C1), C2 --> shl X, C1 - C2
|
|
|
|
|
|
|
|
define <2 x i7> @shl_lshr_splat_vec(<2 x i7> %X) {
|
|
|
|
; CHECK-LABEL: @shl_lshr_splat_vec(
|
|
|
|
; CHECK-NEXT: [[DIV:%.*]] = udiv <2 x i7> %X, <i7 9, i7 9>
|
2017-01-17 03:35:45 +08:00
|
|
|
; CHECK-NEXT: [[SH1:%.*]] = shl nuw nsw <2 x i7> [[DIV]], <i7 1, i7 1>
|
|
|
|
; CHECK-NEXT: ret <2 x i7> [[SH1]]
|
2017-01-17 03:23:34 +08:00
|
|
|
;
|
|
|
|
%div = udiv <2 x i7> %X, <i7 9, i7 9>
|
|
|
|
%sh1 = shl nuw <2 x i7> %div, <i7 3, i7 3>
|
|
|
|
%sh2 = lshr exact <2 x i7> %sh1, <i7 2, i7 2>
|
|
|
|
ret <2 x i7> %sh2
|
|
|
|
}
|
|
|
|
|
Reapply r155136 after fixing PR12599.
Original commit message:
Defer some shl transforms to DAGCombine.
The shl instruction is used to represent multiplication by a constant
power of two as well as bitwise left shifts. Some InstCombine
transformations would turn an shl instruction into a bit mask operation,
making it difficult for later analysis passes to recognize the
constsnt multiplication.
Disable those shl transformations, deferring them to DAGCombine time.
An 'shl X, C' instruction is now treated mostly the same was as 'mul X, C'.
These transformations are deferred:
(X >>? C) << C --> X & (-1 << C) (When X >> C has multiple uses)
(X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2) (When C2 > C1)
(X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2) (When C1 > C2)
The corresponding exact transformations are preserved, just like
div-exact + mul:
(X >>?,exact C) << C --> X
(X >>?,exact C1) << C2 --> X << (C2-C1)
(X >>?,exact C1) << C2 --> X >>?,exact (C1-C2)
The disabled transformations could also prevent the instruction selector
from recognizing rotate patterns in hash functions and cryptographic
primitives. I have a test case for that, but it is too fragile.
llvm-svn: 155362
2012-04-24 01:39:52 +08:00
|
|
|
; Don't hide the shl from scalar evolution. DAGCombine will get it.
|
2007-03-24 05:57:47 +08:00
|
|
|
define i23 @test11(i23 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test11(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = mul i23 %A, 3
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = lshr i23 [[A]], 11
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = shl i23 [[B]], 12
|
|
|
|
; CHECK-NEXT: ret i23 [[C]]
|
|
|
|
;
|
|
|
|
%a = mul i23 %A, 3
|
|
|
|
%B = lshr i23 %a, 11
|
|
|
|
%C = shl i23 %B, 12
|
|
|
|
ret i23 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2017-01-16 07:45:03 +08:00
|
|
|
; shl (ashr X, C), C --> and X, C'
|
|
|
|
|
|
|
|
define i47 @test12(i47 %X) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test12(
|
2017-01-16 07:45:03 +08:00
|
|
|
; CHECK-NEXT: [[SH11:%.*]] = and i47 %X, -256
|
|
|
|
; CHECK-NEXT: ret i47 [[SH11]]
|
|
|
|
;
|
|
|
|
%sh1 = ashr i47 %X, 8
|
|
|
|
%sh2 = shl i47 %sh1, 8
|
|
|
|
ret i47 %sh2
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i47> @test12_splat_vec(<2 x i47> %X) {
|
|
|
|
; CHECK-LABEL: @test12_splat_vec(
|
2017-04-21 05:33:02 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i47> %X, <i47 -256, i47 -256>
|
|
|
|
; CHECK-NEXT: ret <2 x i47> [[TMP1]]
|
2016-08-16 01:19:07 +08:00
|
|
|
;
|
2017-01-16 07:45:03 +08:00
|
|
|
%sh1 = ashr <2 x i47> %X, <i47 8, i47 8>
|
|
|
|
%sh2 = shl <2 x i47> %sh1, <i47 8, i47 8>
|
|
|
|
ret <2 x i47> %sh2
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
Reapply r155136 after fixing PR12599.
Original commit message:
Defer some shl transforms to DAGCombine.
The shl instruction is used to represent multiplication by a constant
power of two as well as bitwise left shifts. Some InstCombine
transformations would turn an shl instruction into a bit mask operation,
making it difficult for later analysis passes to recognize the
constsnt multiplication.
Disable those shl transformations, deferring them to DAGCombine time.
An 'shl X, C' instruction is now treated mostly the same was as 'mul X, C'.
These transformations are deferred:
(X >>? C) << C --> X & (-1 << C) (When X >> C has multiple uses)
(X >>? C1) << C2 --> X << (C2-C1) & (-1 << C2) (When C2 > C1)
(X >>? C1) << C2 --> X >>? (C1-C2) & (-1 << C2) (When C1 > C2)
The corresponding exact transformations are preserved, just like
div-exact + mul:
(X >>?,exact C) << C --> X
(X >>?,exact C1) << C2 --> X << (C2-C1)
(X >>?,exact C1) << C2 --> X >>?,exact (C1-C2)
The disabled transformations could also prevent the instruction selector
from recognizing rotate patterns in hash functions and cryptographic
primitives. I have a test case for that, but it is too fragile.
llvm-svn: 155362
2012-04-24 01:39:52 +08:00
|
|
|
; Don't hide the shl from scalar evolution. DAGCombine will get it.
|
2007-03-24 05:57:47 +08:00
|
|
|
define i18 @test13(i18 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test13(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = mul i18 %A, 3
|
|
|
|
; CHECK-NEXT: [[B1:%.*]] = lshr i18 [[A]], 8
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = shl i18 [[B1]], 9
|
|
|
|
; CHECK-NEXT: ret i18 [[C]]
|
|
|
|
;
|
|
|
|
%a = mul i18 %A, 3
|
|
|
|
%B = ashr i18 %a, 8
|
|
|
|
%C = shl i18 %B, 9
|
|
|
|
ret i18 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i35 @test14(i35 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test14(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i35 %A, -19760
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = or i35 [[B]], 19744
|
|
|
|
; CHECK-NEXT: ret i35 [[C]]
|
|
|
|
;
|
|
|
|
%B = lshr i35 %A, 4
|
|
|
|
%C = or i35 %B, 1234
|
|
|
|
%D = shl i35 %C, 4
|
|
|
|
ret i35 %D
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i79 @test14a(i79 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test14a(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i79 %A, 77
|
|
|
|
; CHECK-NEXT: ret i79 [[C]]
|
|
|
|
;
|
|
|
|
%B = shl i79 %A, 4
|
|
|
|
%C = and i79 %B, 1234
|
|
|
|
%D = lshr i79 %C, 4
|
|
|
|
ret i79 %D
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i45 @test15(i1 %C) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test15(
|
|
|
|
; CHECK-NEXT: [[A:%.*]] = select i1 %C, i45 12, i45 4
|
|
|
|
; CHECK-NEXT: ret i45 [[A]]
|
|
|
|
;
|
|
|
|
%A = select i1 %C, i45 3, i45 1
|
|
|
|
%V = shl i45 %A, 2
|
|
|
|
ret i45 %V
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i53 @test15a(i1 %X) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test15a(
|
|
|
|
; CHECK-NEXT: [[V:%.*]] = select i1 %X, i53 512, i53 128
|
|
|
|
; CHECK-NEXT: ret i53 [[V]]
|
|
|
|
;
|
|
|
|
%A = select i1 %X, i8 3, i8 1
|
|
|
|
%B = zext i8 %A to i53
|
|
|
|
%V = shl i53 64, %B
|
|
|
|
ret i53 %V
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test16(i84 %X) {
|
2016-08-15 06:56:46 +08:00
|
|
|
; CHECK-LABEL: @test16(
|
|
|
|
; CHECK-NEXT: [[AND:%.*]] = and i84 %X, 16
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i84 [[AND]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[CMP]]
|
|
|
|
;
|
|
|
|
%shr = ashr i84 %X, 4
|
|
|
|
%and = and i84 %shr, 1
|
|
|
|
%cmp = icmp ne i84 %and, 0
|
|
|
|
ret i1 %cmp
|
|
|
|
}
|
|
|
|
|
|
|
|
define <2 x i1> @test16vec(<2 x i84> %X) {
|
|
|
|
; CHECK-LABEL: @test16vec(
|
[InstCombine] reverse 'trunc X to <N x i1>' canonicalization; 2nd try
Re-trying r344082 because it unintentionally included extra diffs.
Original commit message:
icmp ne (and X, 1), 0 --> trunc X to N x i1
Ideally, we'd do the same for scalars, but there will likely be
regressions unless we add more trunc folds as we're doing here
for vectors.
The motivating vector case is from PR37549:
https://bugs.llvm.org/show_bug.cgi?id=37549
define <4 x float> @bitwise_select(<4 x float> %x, <4 x float> %y, <4 x float> %z, <4 x float> %w) {
%c = fcmp ole <4 x float> %x, %y
%s = sext <4 x i1> %c to <4 x i32>
%s1 = shufflevector <4 x i32> %s, <4 x i32> undef, <4 x i32> <i32 0, i32 0, i32 1, i32 1>
%s2 = shufflevector <4 x i32> %s, <4 x i32> undef, <4 x i32> <i32 2, i32 2, i32 3, i32 3>
%cond = or <4 x i32> %s1, %s2
%condtr = trunc <4 x i32> %cond to <4 x i1>
%r = select <4 x i1> %condtr, <4 x float> %z, <4 x float> %w
ret <4 x float> %r
}
Here's a sampling of the vector codegen for that case using
mask+icmp (current behavior) vs. trunc (with this patch):
AVX before:
vcmpleps %xmm1, %xmm0, %xmm0
vpermilps $80, %xmm0, %xmm1 ## xmm1 = xmm0[0,0,1,1]
vpermilps $250, %xmm0, %xmm0 ## xmm0 = xmm0[2,2,3,3]
vorps %xmm0, %xmm1, %xmm0
vandps LCPI0_0(%rip), %xmm0, %xmm0
vxorps %xmm1, %xmm1, %xmm1
vpcmpeqd %xmm1, %xmm0, %xmm0
vblendvps %xmm0, %xmm3, %xmm2, %xmm0
AVX after:
vcmpleps %xmm1, %xmm0, %xmm0
vpermilps $80, %xmm0, %xmm1 ## xmm1 = xmm0[0,0,1,1]
vpermilps $250, %xmm0, %xmm0 ## xmm0 = xmm0[2,2,3,3]
vorps %xmm0, %xmm1, %xmm0
vblendvps %xmm0, %xmm2, %xmm3, %xmm0
AVX512f before:
vcmpleps %xmm1, %xmm0, %xmm0
vpermilps $80, %xmm0, %xmm1 ## xmm1 = xmm0[0,0,1,1]
vpermilps $250, %xmm0, %xmm0 ## xmm0 = xmm0[2,2,3,3]
vorps %xmm0, %xmm1, %xmm0
vpbroadcastd LCPI0_0(%rip), %xmm1 ## xmm1 = [1,1,1,1]
vptestnmd %zmm1, %zmm0, %k1
vblendmps %zmm3, %zmm2, %zmm0 {%k1}
AVX512f after:
vcmpleps %xmm1, %xmm0, %xmm0
vpermilps $80, %xmm0, %xmm1 ## xmm1 = xmm0[0,0,1,1]
vpermilps $250, %xmm0, %xmm0 ## xmm0 = xmm0[2,2,3,3]
vorps %xmm0, %xmm1, %xmm0
vpslld $31, %xmm0, %xmm0
vptestmd %zmm0, %zmm0, %k1
vblendmps %zmm2, %zmm3, %zmm0 {%k1}
AArch64 before:
fcmge v0.4s, v1.4s, v0.4s
zip1 v1.4s, v0.4s, v0.4s
zip2 v0.4s, v0.4s, v0.4s
orr v0.16b, v1.16b, v0.16b
movi v1.4s, #1
and v0.16b, v0.16b, v1.16b
cmeq v0.4s, v0.4s, #0
bsl v0.16b, v3.16b, v2.16b
AArch64 after:
fcmge v0.4s, v1.4s, v0.4s
zip1 v1.4s, v0.4s, v0.4s
zip2 v0.4s, v0.4s, v0.4s
orr v0.16b, v1.16b, v0.16b
bsl v0.16b, v2.16b, v3.16b
PowerPC-le before:
xvcmpgesp 34, 35, 34
vspltisw 0, 1
vmrglw 3, 2, 2
vmrghw 2, 2, 2
xxlor 0, 35, 34
xxlxor 35, 35, 35
xxland 34, 0, 32
vcmpequw 2, 2, 3
xxsel 34, 36, 37, 34
PowerPC-le after:
xvcmpgesp 34, 35, 34
vmrglw 3, 2, 2
vmrghw 2, 2, 2
xxlor 0, 35, 34
xxsel 34, 37, 36, 0
Differential Revision: https://reviews.llvm.org/D52747
llvm-svn: 344181
2018-10-11 04:47:46 +08:00
|
|
|
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i84> [[X:%.*]], <i84 16, i84 16>
|
|
|
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i84> [[TMP1]], zeroinitializer
|
2016-08-15 06:56:46 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[CMP]]
|
|
|
|
;
|
|
|
|
%shr = ashr <2 x i84> %X, <i84 4, i84 4>
|
|
|
|
%and = and <2 x i84> %shr, <i84 1, i84 1>
|
|
|
|
%cmp = icmp ne <2 x i84> %and, zeroinitializer
|
|
|
|
ret <2 x i1> %cmp
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test17(i106 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test17(
|
|
|
|
; CHECK-NEXT: [[B_MASK:%.*]] = and i106 %A, -8
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i106 [[B_MASK]], 9872
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = lshr i106 %A, 3
|
|
|
|
%C = icmp eq i106 %B, 1234
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2016-08-16 01:55:39 +08:00
|
|
|
define <2 x i1> @test17vec(<2 x i106> %A) {
|
|
|
|
; CHECK-LABEL: @test17vec(
|
2016-08-25 06:22:06 +08:00
|
|
|
; CHECK-NEXT: [[B_MASK:%.*]] = and <2 x i106> %A, <i106 -8, i106 -8>
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i106> [[B_MASK]], <i106 9872, i106 9872>
|
2016-08-16 01:55:39 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%B = lshr <2 x i106> %A, <i106 3, i106 3>
|
|
|
|
%C = icmp eq <2 x i106> %B, <i106 1234, i106 1234>
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
2007-03-24 05:57:47 +08:00
|
|
|
define i1 @test18(i11 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test18(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%B = lshr i11 %A, 10
|
|
|
|
%C = icmp eq i11 %B, 123
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test19(i37 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test19(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult i37 %A, 4
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = ashr i37 %A, 2
|
|
|
|
%C = icmp eq i37 %B, 0
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2016-08-16 01:55:39 +08:00
|
|
|
define <2 x i1> @test19vec(<2 x i37> %A) {
|
|
|
|
; CHECK-LABEL: @test19vec(
|
2016-08-25 06:22:06 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ult <2 x i37> %A, <i37 4, i37 4>
|
2016-08-16 01:55:39 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%B = ashr <2 x i37> %A, <i37 2, i37 2>
|
|
|
|
%C = icmp eq <2 x i37> %B, zeroinitializer
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
2007-03-24 05:57:47 +08:00
|
|
|
define i1 @test19a(i39 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test19a(
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt i39 %A, -5
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = ashr i39 %A, 2
|
|
|
|
%C = icmp eq i39 %B, -1
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2016-08-16 01:55:39 +08:00
|
|
|
define <2 x i1> @test19a_vec(<2 x i39> %A) {
|
|
|
|
; CHECK-LABEL: @test19a_vec(
|
2016-08-29 02:18:00 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp ugt <2 x i39> %A, <i39 -5, i39 -5>
|
2016-08-16 01:55:39 +08:00
|
|
|
; CHECK-NEXT: ret <2 x i1> [[C]]
|
|
|
|
;
|
|
|
|
%B = ashr <2 x i39> %A, <i39 2, i39 2>
|
|
|
|
%C = icmp eq <2 x i39> %B, <i39 -1, i39 -1>
|
|
|
|
ret <2 x i1> %C
|
|
|
|
}
|
|
|
|
|
2007-03-24 05:57:47 +08:00
|
|
|
define i1 @test20(i13 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test20(
|
|
|
|
; CHECK-NEXT: ret i1 false
|
|
|
|
;
|
|
|
|
%B = ashr i13 %A, 12
|
|
|
|
%C = icmp eq i13 %B, 123
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test21(i12 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test21(
|
|
|
|
; CHECK-NEXT: [[B_MASK:%.*]] = and i12 %A, 63
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i12 [[B_MASK]], 62
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = shl i12 %A, 6
|
|
|
|
%C = icmp eq i12 %B, -128
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i1 @test22(i14 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test22(
|
|
|
|
; CHECK-NEXT: [[B_MASK:%.*]] = and i14 %A, 127
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = icmp eq i14 [[B_MASK]], 0
|
|
|
|
; CHECK-NEXT: ret i1 [[C]]
|
|
|
|
;
|
|
|
|
%B = shl i14 %A, 7
|
|
|
|
%C = icmp eq i14 %B, 0
|
|
|
|
ret i1 %C
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i11 @test23(i44 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test23(
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = trunc i44 %A to i11
|
|
|
|
; CHECK-NEXT: ret i11 [[D]]
|
|
|
|
;
|
|
|
|
%B = shl i44 %A, 33
|
|
|
|
%C = ashr i44 %B, 33
|
|
|
|
%D = trunc i44 %C to i11
|
|
|
|
ret i11 %D
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
2017-01-27 04:10:55 +08:00
|
|
|
; Fold lshr (shl X, C), C -> and X, C' regardless of the number of uses of the shl.
|
|
|
|
|
|
|
|
define i44 @shl_lshr_eq_amt_multi_use(i44 %A) {
|
|
|
|
; CHECK-LABEL: @shl_lshr_eq_amt_multi_use(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl i44 %A, 33
|
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i44 %A, 2047
|
|
|
|
; CHECK-NEXT: [[D:%.*]] = or i44 [[B]], [[C]]
|
|
|
|
; CHECK-NEXT: ret i44 [[D]]
|
|
|
|
;
|
|
|
|
%B = shl i44 %A, 33
|
|
|
|
%C = lshr i44 %B, 33
|
|
|
|
%D = add i44 %B, %C
|
|
|
|
ret i44 %D
|
|
|
|
}
|
|
|
|
|
2017-01-27 04:52:27 +08:00
|
|
|
; Fold vector lshr (shl X, C), C -> and X, C' regardless of the number of uses of the shl.
|
2017-01-27 04:10:55 +08:00
|
|
|
|
|
|
|
define <2 x i44> @shl_lshr_eq_amt_multi_use_splat_vec(<2 x i44> %A) {
|
|
|
|
; CHECK-LABEL: @shl_lshr_eq_amt_multi_use_splat_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = shl <2 x i44> %A, <i44 33, i44 33>
|
2017-01-27 04:52:27 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = and <2 x i44> %A, <i44 2047, i44 2047>
|
2017-01-27 04:10:55 +08:00
|
|
|
; CHECK-NEXT: [[D:%.*]] = or <2 x i44> [[B]], [[C]]
|
|
|
|
; CHECK-NEXT: ret <2 x i44> [[D]]
|
|
|
|
;
|
|
|
|
%B = shl <2 x i44> %A, <i44 33, i44 33>
|
|
|
|
%C = lshr <2 x i44> %B, <i44 33, i44 33>
|
|
|
|
%D = add <2 x i44> %B, %C
|
|
|
|
ret <2 x i44> %D
|
|
|
|
}
|
|
|
|
|
2017-01-27 06:08:10 +08:00
|
|
|
; Fold shl (lshr X, C), C -> and X, C' regardless of the number of uses of the lshr.
|
2017-01-27 04:10:55 +08:00
|
|
|
|
|
|
|
define i43 @lshr_shl_eq_amt_multi_use(i43 %A) {
|
|
|
|
; CHECK-LABEL: @lshr_shl_eq_amt_multi_use(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = lshr i43 %A, 23
|
2017-01-27 06:08:10 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = and i43 %A, -8388608
|
2017-01-27 04:10:55 +08:00
|
|
|
; CHECK-NEXT: [[D:%.*]] = mul i43 [[B]], [[C]]
|
|
|
|
; CHECK-NEXT: ret i43 [[D]]
|
|
|
|
;
|
|
|
|
%B = lshr i43 %A, 23
|
|
|
|
%C = shl i43 %B, 23
|
|
|
|
%D = mul i43 %B, %C
|
|
|
|
ret i43 %D
|
|
|
|
}
|
|
|
|
|
2017-01-27 06:08:10 +08:00
|
|
|
; Fold vector shl (lshr X, C), C -> and X, C' regardless of the number of uses of the lshr.
|
2017-01-27 04:10:55 +08:00
|
|
|
|
|
|
|
define <2 x i43> @lshr_shl_eq_amt_multi_use_splat_vec(<2 x i43> %A) {
|
|
|
|
; CHECK-LABEL: @lshr_shl_eq_amt_multi_use_splat_vec(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = lshr <2 x i43> %A, <i43 23, i43 23>
|
2017-01-27 06:08:10 +08:00
|
|
|
; CHECK-NEXT: [[C:%.*]] = and <2 x i43> %A, <i43 -8388608, i43 -8388608>
|
2017-01-27 04:10:55 +08:00
|
|
|
; CHECK-NEXT: [[D:%.*]] = mul <2 x i43> [[B]], [[C]]
|
|
|
|
; CHECK-NEXT: ret <2 x i43> [[D]]
|
|
|
|
;
|
|
|
|
%B = lshr <2 x i43> %A, <i43 23, i43 23>
|
|
|
|
%C = shl <2 x i43> %B, <i43 23, i43 23>
|
|
|
|
%D = mul <2 x i43> %B, %C
|
|
|
|
ret <2 x i43> %D
|
|
|
|
}
|
|
|
|
|
2007-03-24 05:57:47 +08:00
|
|
|
define i37 @test25(i37 %tmp.2, i37 %AA) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test25(
|
|
|
|
; CHECK-NEXT: [[TMP_3:%.*]] = and i37 %tmp.2, -131072
|
|
|
|
; CHECK-NEXT: [[X2:%.*]] = add i37 [[TMP_3]], %AA
|
|
|
|
; CHECK-NEXT: [[TMP_6:%.*]] = and i37 [[X2]], -131072
|
|
|
|
; CHECK-NEXT: ret i37 [[TMP_6]]
|
|
|
|
;
|
|
|
|
%x = lshr i37 %AA, 17
|
|
|
|
%tmp.3 = lshr i37 %tmp.2, 17
|
|
|
|
%tmp.5 = add i37 %tmp.3, %x
|
|
|
|
%tmp.6 = shl i37 %tmp.5, 17
|
|
|
|
ret i37 %tmp.6
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
define i40 @test26(i40 %A) {
|
2016-08-16 01:19:07 +08:00
|
|
|
; CHECK-LABEL: @test26(
|
|
|
|
; CHECK-NEXT: [[B:%.*]] = and i40 %A, -2
|
|
|
|
; CHECK-NEXT: ret i40 [[B]]
|
|
|
|
;
|
|
|
|
%B = lshr i40 %A, 1
|
|
|
|
%C = bitcast i40 %B to i40
|
|
|
|
%D = shl i40 %C, 1
|
|
|
|
ret i40 %D
|
2007-03-24 05:57:47 +08:00
|
|
|
}
|