1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=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 nsw i32 -1, [[NBITS:%.*]]
19 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 -1, [[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 nsw <8 x i32> splat (i32 -1), [[NBITS:%.*]]
46 ; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]
47 ; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], splat (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]], splat (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_splat_poison(<8 x i32> %x, <8 x i32> %nbits) {
67 ; CHECK-LABEL: @t2_vec_splat_poison(
68 ; CHECK-NEXT: [[T0:%.*]] = shl nsw <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>, [[NBITS:%.*]]
69 ; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]
70 ; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>
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 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>
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 poison, 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 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison, i32 -1>
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
89 define <8 x i32> @t2_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {
90 ; CHECK-LABEL: @t2_vec_nonsplat(
91 ; CHECK-NEXT: [[T0:%.*]] = shl nsw <8 x i32> splat (i32 -1), [[NBITS:%.*]]
92 ; CHECK-NEXT: [[T1:%.*]] = lshr <8 x i32> splat (i32 -1), [[NBITS]]
93 ; CHECK-NEXT: [[T3:%.*]] = add <8 x i32> [[NBITS]], <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
94 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T0]])
95 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T1]])
96 ; CHECK-NEXT: call void @use8xi32(<8 x i32> [[T3]])
97 ; CHECK-NEXT: [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T3]]
98 ; CHECK-NEXT: [[T4:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 -1, i32 poison>
99 ; CHECK-NEXT: ret <8 x i32> [[T4]]
101 %t0 = shl <8 x i32> <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>, %nbits
102 %t1 = lshr <8 x i32> %t0, %nbits
103 %t2 = and <8 x i32> %t1, %x
104 %t3 = add <8 x i32> %nbits, <i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32, i32 33>
105 call void @use8xi32(<8 x i32> %t0)
106 call void @use8xi32(<8 x i32> %t1)
107 call void @use8xi32(<8 x i32> %t3)
108 %t4 = shl <8 x i32> %t2, %t3 ; shift is smaller than mask
114 define i32 @n3_extrause(i32 %x, i32 %nbits) {
115 ; CHECK-LABEL: @n3_extrause(
116 ; CHECK-NEXT: [[T0:%.*]] = shl nsw i32 -1, [[NBITS:%.*]]
117 ; CHECK-NEXT: [[T1:%.*]] = lshr i32 -1, [[NBITS]]
118 ; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[X:%.*]]
119 ; CHECK-NEXT: [[T3:%.*]] = add i32 [[NBITS]], -1
120 ; CHECK-NEXT: call void @use32(i32 [[T0]])
121 ; CHECK-NEXT: call void @use32(i32 [[T1]])
122 ; CHECK-NEXT: call void @use32(i32 [[T2]])
123 ; CHECK-NEXT: call void @use32(i32 [[T3]])
124 ; CHECK-NEXT: [[T4:%.*]] = shl i32 [[T2]], [[T3]]
125 ; CHECK-NEXT: ret i32 [[T4]]
127 %t0 = shl i32 -1, %nbits
128 %t1 = lshr i32 %t0, %nbits
129 %t2 = and i32 %t1, %x
130 %t3 = add i32 %nbits, -1
131 call void @use32(i32 %t0)
132 call void @use32(i32 %t1)
133 call void @use32(i32 %t2) ; BAD
134 call void @use32(i32 %t3)
135 %t4 = shl i32 %t2, %t3 ; shift is smaller than mask