147
|
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
|
2 ; RUN: opt < %s -instcombine -S | FileCheck %s
|
|
3
|
|
4 ; https://bugs.llvm.org/show_bug.cgi?id=38123
|
|
5
|
|
6 ; Pattern:
|
|
7 ; x & C s< x
|
|
8 ; Should be transformed into:
|
|
9 ; x s> C
|
|
10 ; Iff: isPowerOf2(C + 1)
|
|
11 ; C must not be -1, but may be 0.
|
|
12
|
|
13 ; ============================================================================ ;
|
|
14 ; Basic positive tests
|
|
15 ; ============================================================================ ;
|
|
16
|
|
17 define i1 @p0(i8 %x) {
|
|
18 ; CHECK-LABEL: @p0(
|
|
19 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X:%.*]], 3
|
|
20 ; CHECK-NEXT: ret i1 [[TMP1]]
|
|
21 ;
|
|
22 %tmp0 = and i8 %x, 3
|
|
23 %ret = icmp slt i8 %tmp0, %x
|
|
24 ret i1 %ret
|
|
25 }
|
|
26
|
|
27 ; ============================================================================ ;
|
|
28 ; Vector tests
|
|
29 ; ============================================================================ ;
|
|
30
|
|
31 define <2 x i1> @p1_vec_splat(<2 x i8> %x) {
|
|
32 ; CHECK-LABEL: @p1_vec_splat(
|
|
33 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 3, i8 3>
|
|
34 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
|
|
35 ;
|
|
36 %tmp0 = and <2 x i8> %x, <i8 3, i8 3>
|
|
37 %ret = icmp slt <2 x i8> %tmp0, %x
|
|
38 ret <2 x i1> %ret
|
|
39 }
|
|
40
|
|
41 define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {
|
|
42 ; CHECK-LABEL: @p2_vec_nonsplat(
|
|
43 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 3, i8 15>
|
|
44 ; CHECK-NEXT: ret <2 x i1> [[TMP1]]
|
|
45 ;
|
|
46 %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat.
|
|
47 %ret = icmp slt <2 x i8> %tmp0, %x
|
|
48 ret <2 x i1> %ret
|
|
49 }
|
|
50
|
|
51 define <2 x i1> @p2_vec_nonsplat_edgecase(<2 x i8> %x) {
|
|
52 ; CHECK-LABEL: @p2_vec_nonsplat_edgecase(
|
|
53 ; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 0>
|
|
54 ; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]]
|
|
55 ; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
56 ;
|
|
57 %tmp0 = and <2 x i8> %x, <i8 3, i8 0>
|
|
58 %ret = icmp slt <2 x i8> %tmp0, %x
|
|
59 ret <2 x i1> %ret
|
|
60 }
|
|
61
|
|
62 define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) {
|
|
63 ; CHECK-LABEL: @p3_vec_splat_undef(
|
|
64 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt <3 x i8> [[X:%.*]], <i8 3, i8 undef, i8 3>
|
|
65 ; CHECK-NEXT: ret <3 x i1> [[TMP1]]
|
|
66 ;
|
|
67 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3>
|
|
68 %ret = icmp slt <3 x i8> %tmp0, %x
|
|
69 ret <3 x i1> %ret
|
|
70 }
|
|
71
|
|
72 ; ============================================================================ ;
|
|
73 ; One-use tests. We don't care about multi-uses here.
|
|
74 ; ============================================================================ ;
|
|
75
|
|
76 declare void @use8(i8)
|
|
77
|
|
78 define i1 @oneuse0(i8 %x) {
|
|
79 ; CHECK-LABEL: @oneuse0(
|
|
80 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3
|
|
81 ; CHECK-NEXT: call void @use8(i8 [[TMP0]])
|
|
82 ; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i8 [[X]], 3
|
|
83 ; CHECK-NEXT: ret i1 [[TMP1]]
|
|
84 ;
|
|
85 %tmp0 = and i8 %x, 3
|
|
86 call void @use8(i8 %tmp0)
|
|
87 %ret = icmp slt i8 %tmp0, %x
|
|
88 ret i1 %ret
|
|
89 }
|
|
90
|
|
91 ; ============================================================================ ;
|
|
92 ; Negative tests
|
|
93 ; ============================================================================ ;
|
|
94
|
|
95 ; Commutativity tests.
|
|
96
|
|
97 declare i8 @gen8()
|
|
98
|
|
99 define i1 @c0() {
|
|
100 ; CHECK-LABEL: @c0(
|
|
101 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
|
|
102 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 3
|
|
103 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP0]]
|
|
104 ; CHECK-NEXT: ret i1 [[RET]]
|
|
105 ;
|
|
106 %x = call i8 @gen8()
|
|
107 %tmp0 = and i8 %x, 3
|
|
108 %ret = icmp slt i8 %x, %tmp0 ; swapped order
|
|
109 ret i1 %ret
|
|
110 }
|
|
111
|
|
112 ; ============================================================================ ;
|
|
113 ; Rest of negative tests
|
|
114 ; ============================================================================ ;
|
|
115
|
|
116 define i1 @n0(i8 %x) {
|
|
117 ; CHECK-LABEL: @n0(
|
|
118 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 4
|
|
119 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[X]]
|
|
120 ; CHECK-NEXT: ret i1 [[RET]]
|
|
121 ;
|
|
122 %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
|
|
123 %ret = icmp slt i8 %tmp0, %x
|
|
124 ret i1 %ret
|
|
125 }
|
|
126
|
|
127 define i1 @n1(i8 %x, i8 %y, i8 %notx) {
|
|
128 ; CHECK-LABEL: @n1(
|
|
129 ; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3
|
|
130 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP0]], [[NOTX:%.*]]
|
|
131 ; CHECK-NEXT: ret i1 [[RET]]
|
|
132 ;
|
|
133 %tmp0 = and i8 %x, 3
|
|
134 %ret = icmp slt i8 %tmp0, %notx ; not %x
|
|
135 ret i1 %ret
|
|
136 }
|
|
137
|
|
138 define <2 x i1> @n2(<2 x i8> %x) {
|
|
139 ; CHECK-LABEL: @n2(
|
|
140 ; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>
|
|
141 ; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]]
|
|
142 ; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
143 ;
|
|
144 %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.
|
|
145 %ret = icmp slt <2 x i8> %tmp0, %x
|
|
146 ret <2 x i1> %ret
|
|
147 }
|
|
148
|
|
149 ; ============================================================================ ;
|
|
150 ; Potential miscompiles.
|
|
151 ; ============================================================================ ;
|
|
152
|
|
153 define i1 @nv(i8 %x, i8 %y) {
|
|
154 ; CHECK-LABEL: @nv(
|
|
155 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
|
|
156 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]
|
|
157 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]]
|
|
158 ; CHECK-NEXT: ret i1 [[RET]]
|
|
159 ;
|
|
160 %tmp0 = lshr i8 -1, %y
|
|
161 %tmp1 = and i8 %tmp0, %x
|
|
162 %ret = icmp slt i8 %tmp1, %x
|
|
163 ret i1 %ret
|
|
164 }
|
|
165
|
|
166 define <2 x i1> @n3(<2 x i8> %x) {
|
|
167 ; CHECK-LABEL: @n3(
|
|
168 ; CHECK-NEXT: [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 -1>
|
|
169 ; CHECK-NEXT: [[RET:%.*]] = icmp slt <2 x i8> [[TMP0]], [[X]]
|
|
170 ; CHECK-NEXT: ret <2 x i1> [[RET]]
|
|
171 ;
|
|
172 %tmp0 = and <2 x i8> %x, <i8 3, i8 -1>
|
|
173 %ret = icmp slt <2 x i8> %tmp0, %x
|
|
174 ret <2 x i1> %ret
|
|
175 }
|
|
176
|
|
177 define <3 x i1> @n4(<3 x i8> %x) {
|
|
178 ; CHECK-LABEL: @n4(
|
|
179 ; CHECK-NEXT: [[TMP0:%.*]] = and <3 x i8> [[X:%.*]], <i8 3, i8 undef, i8 -1>
|
|
180 ; CHECK-NEXT: [[RET:%.*]] = icmp slt <3 x i8> [[TMP0]], [[X]]
|
|
181 ; CHECK-NEXT: ret <3 x i1> [[RET]]
|
|
182 ;
|
|
183 %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 -1>
|
|
184 %ret = icmp slt <3 x i8> %tmp0, %x
|
|
185 ret <3 x i1> %ret
|
|
186 }
|
|
187
|
|
188 ; Commutativity tests with variable
|
|
189
|
|
190 define i1 @cv0(i8 %y) {
|
|
191 ; CHECK-LABEL: @cv0(
|
|
192 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
|
|
193 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
|
|
194 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]
|
|
195 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[TMP1]], [[X]]
|
|
196 ; CHECK-NEXT: ret i1 [[RET]]
|
|
197 ;
|
|
198 %x = call i8 @gen8()
|
|
199 %tmp0 = lshr i8 -1, %y
|
|
200 %tmp1 = and i8 %x, %tmp0 ; swapped order
|
|
201 %ret = icmp slt i8 %tmp1, %x
|
|
202 ret i1 %ret
|
|
203 }
|
|
204
|
|
205 define i1 @cv1(i8 %y) {
|
|
206 ; CHECK-LABEL: @cv1(
|
|
207 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
|
|
208 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
|
|
209 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[TMP0]], [[X]]
|
|
210 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]]
|
|
211 ; CHECK-NEXT: ret i1 [[RET]]
|
|
212 ;
|
|
213 %x = call i8 @gen8()
|
|
214 %tmp0 = lshr i8 -1, %y
|
|
215 %tmp1 = and i8 %tmp0, %x
|
|
216 %ret = icmp slt i8 %x, %tmp1 ; swapped order
|
|
217 ret i1 %ret
|
|
218 }
|
|
219
|
|
220 define i1 @cv2(i8 %y) {
|
|
221 ; CHECK-LABEL: @cv2(
|
|
222 ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8()
|
|
223 ; CHECK-NEXT: [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
|
|
224 ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[X]], [[TMP0]]
|
|
225 ; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP1]]
|
|
226 ; CHECK-NEXT: ret i1 [[RET]]
|
|
227 ;
|
|
228 %x = call i8 @gen8()
|
|
229 %tmp0 = lshr i8 -1, %y
|
|
230 %tmp1 = and i8 %x, %tmp0 ; swapped order
|
|
231 %ret = icmp slt i8 %x, %tmp1 ; swapped order
|
|
232 ret i1 %ret
|
|
233 }
|