1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt %s -instcombine -S | FileCheck %s
4 ; If we have some pattern that leaves only some low bits set, and then performs
5 ; left-shift of those bits, we can combine those two shifts into a shift+mask.
7 ; There are many variants to this pattern:
8 ; d) (x & ((-1 << maskNbits) >> maskNbits)) << shiftNbits
10 ; (x << shiftNbits) & (-1 >> ((-(maskNbits+shiftNbits))+32))
14 declare void @use32(i32)
16 define i32 @t0_basic(i32 %x, i32 %nbits) {
17 ; CHECK-LABEL: @t0_basic(
18 ; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]]
19 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
20 ; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -1
21 ; CHECK-NEXT: call void @use32(i32 [[T0]])
22 ; CHECK-NEXT: call void @use32(i32 [[T1]])
23 ; CHECK-NEXT: call void @use32(i32 [[T3]])
24 ; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], [[T3]]
25 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[TMP1]], 2147483647
26 ; CHECK-NEXT: ret i32 [[T4]]
28 %t0 = shl i32 -1, %nbits
29 %t1 = lshr i32 %t0, %nbits
31 %t3 = add i32 %nbits, -1
32 call void @use32(i32 %t0)
33 call void @use32(i32 %t1)
34 call void @use32(i32 %t3)
35 %t4 = shl i32 %t2, %t3 ; shift is smaller than mask
41 declare void @use8xi32(<8 x i32>)
43 define <8 x i32> @t2_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {
44 ; CHECK-LABEL: @t2_vec_splat(
45 ; CHECK-NEXT: [[T0:%.*]] = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, [[NBITS:%.*]]
46 ; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> [[T0]], [[NBITS]]
47 ; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
48 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
49 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])
50 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])
51 ; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]
52 ; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
53 ; CHECK-NEXT: ret <8 x i32> [[T4]]
55 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits
56 %t1 = lshr <8 x i32> %t0, %nbits
57 %t2 = and <8 x i32> %t1, %x
58 %t3 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
59 call void @use8xi32(<8 x i32> %t0)
60 call void @use8xi32(<8 x i32> %t1)
61 call void @use8xi32(<8 x i32> %t3)
62 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask
66 define <8 x i32> @t2_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {
67 ; CHECK-LABEL: @t2_vec_nonsplat(
68 ; CHECK-NEXT: [[T0:%.*]] = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, [[NBITS:%.*]]
69 ; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> [[T0]], [[NBITS]]
70 ; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
71 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
72 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])
73 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])
74 ; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]
75 ; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], <i32 undef, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef>
76 ; CHECK-NEXT: ret <8 x i32> [[T4]]
78 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits
79 %t1 = lshr <8 x i32> %t0, %nbits
80 %t2 = and <8 x i32> %t1, %x
81 %t3 = add <8 x i32> %nbits, <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
82 call void @use8xi32(<8 x i32> %t0)
83 call void @use8xi32(<8 x i32> %t1)
84 call void @use8xi32(<8 x i32> %t3)
85 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask
91 define i32 @n3_extrause(i32 %x, i32 %nbits) {
92 ; CHECK-LABEL: @n3_extrause(
93 ; CHECK-NEXT: [[T0:%.*]] = shl i32 -1, [[NBITS:%.*]]
94 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[T0]], [[NBITS]]
95 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[X:%.*]]
96 ; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -1
97 ; CHECK-NEXT: call void @use32(i32 [[T0]])
98 ; CHECK-NEXT: call void @use32(i32 [[T1]])
99 ; CHECK-NEXT: call void @use32(i32 [[T2]])
100 ; CHECK-NEXT: call void @use32(i32 [[T3]])
101 ; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[T3]]
102 ; CHECK-NEXT: ret i32 [[T4]]
104 %t0 = shl i32 -1, %nbits
105 %t1 = lshr i32 %t0, %nbits
106 %t2 = and i32 %t1, %x
107 %t3 = add i32 %nbits, -1
108 call void @use32(i32 %t0)
109 call void @use32(i32 %t1)
110 call void @use32(i32 %t2) ; BAD
111 call void @use32(i32 %t3)
112 %t4 = shl i32 %t2, %t3 ; shift is smaller than mask