• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 u>= x
8; Should be transformed into:
9;   x u<= C
10; Iff: isPowerOf2(C + 1)
11; C can be 0 and -1.
12
13; ============================================================================ ;
14; Basic positive tests
15; ============================================================================ ;
16
17define i1 @p0(i8 %x) {
18; CHECK-LABEL: @p0(
19; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X:%.*]], 4
20; CHECK-NEXT:    ret i1 [[TMP1]]
21;
22  %tmp0 = and i8 %x, 3
23  %ret = icmp uge i8 %tmp0, %x
24  ret i1 %ret
25}
26
27define i1 @pv(i8 %x, i8 %y) {
28; CHECK-LABEL: @pv(
29; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
30; CHECK-NEXT:    [[TMP1:%.*]] = icmp uge i8 [[TMP0]], [[X:%.*]]
31; CHECK-NEXT:    ret i1 [[TMP1]]
32;
33  %tmp0 = lshr i8 -1, %y
34  %tmp1 = and i8 %tmp0, %x
35  %ret = icmp uge i8 %tmp1, %x
36  ret i1 %ret
37}
38
39; ============================================================================ ;
40; Vector tests
41; ============================================================================ ;
42
43define <2 x i1> @p1_vec_splat(<2 x i8> %x) {
44; CHECK-LABEL: @p1_vec_splat(
45; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 4, i8 4>
46; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
47;
48  %tmp0 = and <2 x i8> %x, <i8 3, i8 3>
49  %ret = icmp uge <2 x i8> %tmp0, %x
50  ret <2 x i1> %ret
51}
52
53define <2 x i1> @p2_vec_nonsplat(<2 x i8> %x) {
54; CHECK-LABEL: @p2_vec_nonsplat(
55; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[X:%.*]], <i8 4, i8 16>
56; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
57;
58  %tmp0 = and <2 x i8> %x, <i8 3, i8 15> ; doesn't have to be splat.
59  %ret = icmp uge <2 x i8> %tmp0, %x
60  ret <2 x i1> %ret
61}
62
63define <2 x i1> @p2_vec_nonsplat_edgecase0(<2 x i8> %x) {
64; CHECK-LABEL: @p2_vec_nonsplat_edgecase0(
65; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 0>
66; CHECK-NEXT:    [[RET:%.*]] = icmp uge <2 x i8> [[TMP0]], [[X]]
67; CHECK-NEXT:    ret <2 x i1> [[RET]]
68;
69  %tmp0 = and <2 x i8> %x, <i8 3, i8 0>
70  %ret = icmp uge <2 x i8> %tmp0, %x
71  ret <2 x i1> %ret
72}
73define <2 x i1> @p2_vec_nonsplat_edgecase1(<2 x i8> %x) {
74; CHECK-LABEL: @p2_vec_nonsplat_edgecase1(
75; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule <2 x i8> [[X:%.*]], <i8 3, i8 -1>
76; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
77;
78  %tmp0 = and <2 x i8> %x, <i8 3, i8 -1>
79  %ret = icmp uge <2 x i8> %tmp0, %x
80  ret <2 x i1> %ret
81}
82
83define <3 x i1> @p3_vec_splat_undef(<3 x i8> %x) {
84; CHECK-LABEL: @p3_vec_splat_undef(
85; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <3 x i8> [[X:%.*]], <i8 4, i8 4, i8 4>
86; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
87;
88  %tmp0 = and <3 x i8> %x, <i8 3, i8 undef, i8 3>
89  %ret = icmp uge <3 x i8> %tmp0, %x
90  ret <3 x i1> %ret
91}
92
93; ============================================================================ ;
94; Commutativity tests.
95; ============================================================================ ;
96
97declare i8 @gen8()
98
99; The pattern is not commutative. instsimplify will already take care of it.
100define i1 @c0() {
101; CHECK-LABEL: @c0(
102; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
103; CHECK-NEXT:    ret i1 true
104;
105  %x = call i8 @gen8()
106  %tmp0 = and i8 %x, 3
107  %ret = icmp uge i8 %x, %tmp0 ; swapped order
108  ret i1 %ret
109}
110
111; ============================================================================ ;
112; Commutativity tests with variable
113; ============================================================================ ;
114
115define i1 @cv0(i8 %y) {
116; CHECK-LABEL: @cv0(
117; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
118; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
119; CHECK-NEXT:    [[TMP1:%.*]] = icmp ule i8 [[X]], [[TMP0]]
120; CHECK-NEXT:    ret i1 [[TMP1]]
121;
122  %x = call i8 @gen8()
123  %tmp0 = lshr i8 -1, %y
124  %tmp1 = and i8 %x, %tmp0 ; swapped order
125  %ret = icmp uge i8 %tmp1, %x
126  ret i1 %ret
127}
128
129define i1 @cv1(i8 %y) {
130; CHECK-LABEL: @cv1(
131; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
132; CHECK-NEXT:    ret i1 true
133;
134  %x = call i8 @gen8()
135  %tmp0 = lshr i8 -1, %y
136  %tmp1 = and i8 %tmp0, %x
137  %ret = icmp uge i8 %x, %tmp1 ; swapped order
138  ret i1 %ret
139}
140
141define i1 @cv2(i8 %y) {
142; CHECK-LABEL: @cv2(
143; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
144; CHECK-NEXT:    ret i1 true
145;
146  %x = call i8 @gen8()
147  %tmp0 = lshr i8 -1, %y
148  %tmp1 = and i8 %x, %tmp0 ; swapped order
149  %ret = icmp uge i8 %x, %tmp1 ; swapped order
150  ret i1 %ret
151}
152
153; ============================================================================ ;
154; One-use tests. We don't care about multi-uses here.
155; ============================================================================ ;
156
157declare void @use8(i8)
158
159define i1 @oneuse0(i8 %x) {
160; CHECK-LABEL: @oneuse0(
161; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X:%.*]], 3
162; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
163; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[X]], 4
164; CHECK-NEXT:    ret i1 [[TMP1]]
165;
166  %tmp0 = and i8 %x, 3
167  call void @use8(i8 %tmp0)
168  %ret = icmp uge i8 %tmp0, %x
169  ret i1 %ret
170}
171
172; ============================================================================ ;
173; Negative tests
174; ============================================================================ ;
175
176define i1 @n0(i8 %x) {
177; CHECK-LABEL: @n0(
178; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X:%.*]], 4
179; CHECK-NEXT:    [[RET:%.*]] = icmp uge i8 [[TMP0]], [[X]]
180; CHECK-NEXT:    ret i1 [[RET]]
181;
182  %tmp0 = and i8 %x, 4 ; power-of-two, but invalid.
183  %ret = icmp uge i8 %tmp0, %x
184  ret i1 %ret
185}
186
187define i1 @n1(i8 %x, i8 %y, i8 %notx) {
188; CHECK-LABEL: @n1(
189; CHECK-NEXT:    [[TMP0:%.*]] = and i8 [[X:%.*]], 3
190; CHECK-NEXT:    [[RET:%.*]] = icmp uge i8 [[TMP0]], [[NOTX:%.*]]
191; CHECK-NEXT:    ret i1 [[RET]]
192;
193  %tmp0 = and i8 %x, 3
194  %ret = icmp uge i8 %tmp0, %notx ; not %x
195  ret i1 %ret
196}
197
198define <2 x i1> @n2(<2 x i8> %x) {
199; CHECK-LABEL: @n2(
200; CHECK-NEXT:    [[TMP0:%.*]] = and <2 x i8> [[X:%.*]], <i8 3, i8 16>
201; CHECK-NEXT:    [[RET:%.*]] = icmp uge <2 x i8> [[TMP0]], [[X]]
202; CHECK-NEXT:    ret <2 x i1> [[RET]]
203;
204  %tmp0 = and <2 x i8> %x, <i8 3, i8 16> ; only the first one is valid.
205  %ret = icmp uge <2 x i8> %tmp0, %x
206  ret <2 x i1> %ret
207}
208