1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instcombine -S | FileCheck %s
3
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.
6
7; There are many variants to this pattern:
8;   a)  (x & ((1 << maskNbits) - 1)) << shiftNbits
9; simplify to:
10;   (x << shiftNbits) & (~(-1 << (maskNbits+shiftNbits)))
11
12; Simple tests.
13
14declare void @use32(i32)
15
16define i32 @t0_basic(i32 %x, i32 %nbits) {
17; CHECK-LABEL: @t0_basic(
18; CHECK-NEXT:    [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
19; CHECK-NEXT:    [[T1:%.*]] = shl i32 1, [[T0]]
20; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], -1
21; CHECK-NEXT:    [[T4:%.*]] = sub i32 32, [[NBITS]]
22; CHECK-NEXT:    call void @use32(i32 [[T0]])
23; CHECK-NEXT:    call void @use32(i32 [[T1]])
24; CHECK-NEXT:    call void @use32(i32 [[T2]])
25; CHECK-NEXT:    call void @use32(i32 [[T4]])
26; CHECK-NEXT:    [[TMP1:%.*]] = shl i32 [[X:%.*]], [[T4]]
27; CHECK-NEXT:    [[T5:%.*]] = and i32 [[TMP1]], 2147483647
28; CHECK-NEXT:    ret i32 [[T5]]
29;
30  %t0 = add i32 %nbits, -1
31  %t1 = shl i32 1, %t0 ; shifting by nbits-1
32  %t2 = add i32 %t1, -1
33  %t3 = and i32 %t2, %x
34  %t4 = sub i32 32, %nbits
35  call void @use32(i32 %t0)
36  call void @use32(i32 %t1)
37  call void @use32(i32 %t2)
38  call void @use32(i32 %t4)
39  %t5 = shl i32 %t3, %t4
40  ret i32 %t5
41}
42
43; Vectors
44
45declare void @use8xi32(<8 x i32>)
46
47define <8 x i32> @t1_vec_splat(<8 x i32> %x, <8 x i32> %nbits) {
48; CHECK-LABEL: @t1_vec_splat(
49; CHECK-NEXT:    [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
50; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, [[T0]]
51; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
52; CHECK-NEXT:    [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, [[NBITS]]
53; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
54; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T1]])
55; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
56; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T4]])
57; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]
58; CHECK-NEXT:    [[T5:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
59; CHECK-NEXT:    ret <8 x i32> [[T5]]
60;
61  %t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
62  %t1 = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %t0
63  %t2 = add <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
64  %t3 = and <8 x i32> %t2, %x
65  %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits
66  call void @use8xi32(<8 x i32> %t0)
67  call void @use8xi32(<8 x i32> %t1)
68  call void @use8xi32(<8 x i32> %t2)
69  call void @use8xi32(<8 x i32> %t4)
70  %t5 = shl <8 x i32> %t3, %t4
71  ret <8 x i32> %t5
72}
73
74define <8 x i32> @t1_vec_splat_undef(<8 x i32> %x, <8 x i32> %nbits) {
75; CHECK-LABEL: @t1_vec_splat_undef(
76; CHECK-NEXT:    [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
77; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 undef, i32 1>, [[T0]]
78; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
79; CHECK-NEXT:    [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 undef, i32 32>, [[NBITS]]
80; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
81; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T1]])
82; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
83; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T4]])
84; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]
85; CHECK-NEXT:    [[T5:%.*]] = and <8 x i32> [[TMP1]], <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647, i32 poison, i32 2147483647>
86; CHECK-NEXT:    ret <8 x i32> [[T5]]
87;
88  %t0 = add <8 x i32> %nbits, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
89  %t1 = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 undef, i32 1>, %t0
90  %t2 = add <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 undef, i32 -1>
91  %t3 = and <8 x i32> %t2, %x
92  %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 undef, i32 32>, %nbits
93  call void @use8xi32(<8 x i32> %t0)
94  call void @use8xi32(<8 x i32> %t1)
95  call void @use8xi32(<8 x i32> %t2)
96  call void @use8xi32(<8 x i32> %t4)
97  %t5 = shl <8 x i32> %t3, %t4
98  ret <8 x i32> %t5
99}
100
101define <8 x i32> @t2_vec_nonsplat(<8 x i32> %x, <8 x i32> %nbits) {
102; CHECK-LABEL: @t2_vec_nonsplat(
103; CHECK-NEXT:    [[T0:%.*]] = add <8 x i32> [[NBITS:%.*]], <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>
104; CHECK-NEXT:    [[T1:%.*]] = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, [[T0]]
105; CHECK-NEXT:    [[T2:%.*]] = add <8 x i32> [[T1]], <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
106; CHECK-NEXT:    [[T4:%.*]] = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, [[NBITS]]
107; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T0]])
108; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T1]])
109; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T2]])
110; CHECK-NEXT:    call void @use8xi32(<8 x i32> [[T4]])
111; CHECK-NEXT:    [[TMP1:%.*]] = shl <8 x i32> [[X:%.*]], [[T4]]
112; CHECK-NEXT:    [[T5:%.*]] = and <8 x i32> [[TMP1]], <i32 poison, i32 0, i32 1, i32 2147483647, i32 -1, i32 -1, i32 -1, i32 poison>
113; CHECK-NEXT:    ret <8 x i32> [[T5]]
114;
115  %t0 = add <8 x i32> %nbits, <i32 -33, i32 -32, i32 -31, i32 -1, i32 0, i32 1, i32 31, i32 32>
116  %t1 = shl <8 x i32> <i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1, i32 1>, %t0
117  %t2 = add <8 x i32> %t1, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
118  %t3 = and <8 x i32> %t2, %x
119  %t4 = sub <8 x i32> <i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32, i32 32>, %nbits
120  call void @use8xi32(<8 x i32> %t0)
121  call void @use8xi32(<8 x i32> %t1)
122  call void @use8xi32(<8 x i32> %t2)
123  call void @use8xi32(<8 x i32> %t4)
124  %t5 = shl <8 x i32> %t3, %t4
125  ret <8 x i32> %t5
126}
127
128; Extra uses.
129
130define i32 @n3_extrause(i32 %x, i32 %nbits) {
131; CHECK-LABEL: @n3_extrause(
132; CHECK-NEXT:    [[T0:%.*]] = add i32 [[NBITS:%.*]], -1
133; CHECK-NEXT:    [[T1:%.*]] = shl i32 1, [[T0]]
134; CHECK-NEXT:    [[T2:%.*]] = add i32 [[T1]], -1
135; CHECK-NEXT:    [[T3:%.*]] = and i32 [[T2]], [[X:%.*]]
136; CHECK-NEXT:    [[T4:%.*]] = sub i32 32, [[NBITS]]
137; CHECK-NEXT:    call void @use32(i32 [[T0]])
138; CHECK-NEXT:    call void @use32(i32 [[T1]])
139; CHECK-NEXT:    call void @use32(i32 [[T2]])
140; CHECK-NEXT:    call void @use32(i32 [[T3]])
141; CHECK-NEXT:    call void @use32(i32 [[T4]])
142; CHECK-NEXT:    [[T5:%.*]] = shl i32 [[T3]], [[T4]]
143; CHECK-NEXT:    ret i32 [[T5]]
144;
145  %t0 = add i32 %nbits, -1
146  %t1 = shl i32 1, %t0 ; shifting by nbits-1
147  %t2 = add i32 %t1, -1
148  %t3 = and i32 %t2, %x ; this mask must be one-use.
149  %t4 = sub i32 32, %nbits
150  call void @use32(i32 %t0)
151  call void @use32(i32 %t1)
152  call void @use32(i32 %t2)
153  call void @use32(i32 %t3) ; BAD
154  call void @use32(i32 %t4)
155  %t5 = shl i32 %t3, %t4
156  ret i32 %t5
157}
158