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 & (-1 >> y) != x
8; Should be transformed into:
9;   x u> (-1 >> y)
10
11; ============================================================================ ;
12; Basic positive tests
13; ============================================================================ ;
14
15define i1 @p0(i8 %x, i8 %y) {
16; CHECK-LABEL: @p0(
17; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
18; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP0]], [[X:%.*]]
19; CHECK-NEXT:    ret i1 [[TMP1]]
20;
21  %tmp0 = lshr i8 -1, %y
22  %tmp1 = and i8 %tmp0, %x
23  %ret = icmp ne i8 %tmp1, %x
24  ret i1 %ret
25}
26
27; ============================================================================ ;
28; Vector tests
29; ============================================================================ ;
30
31define <2 x i1> @p1_vec(<2 x i8> %x, <2 x i8> %y) {
32; CHECK-LABEL: @p1_vec(
33; CHECK-NEXT:    [[TMP0:%.*]] = lshr <2 x i8> <i8 -1, i8 -1>, [[Y:%.*]]
34; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <2 x i8> [[TMP0]], [[X:%.*]]
35; CHECK-NEXT:    ret <2 x i1> [[TMP1]]
36;
37  %tmp0 = lshr <2 x i8> <i8 -1, i8 -1>, %y
38  %tmp1 = and <2 x i8> %tmp0, %x
39  %ret = icmp ne <2 x i8> %tmp1, %x
40  ret <2 x i1> %ret
41}
42
43define <3 x i1> @p2_vec_undef(<3 x i8> %x, <3 x i8> %y) {
44; CHECK-LABEL: @p2_vec_undef(
45; CHECK-NEXT:    [[TMP0:%.*]] = lshr <3 x i8> <i8 -1, i8 undef, i8 -1>, [[Y:%.*]]
46; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult <3 x i8> [[TMP0]], [[X:%.*]]
47; CHECK-NEXT:    ret <3 x i1> [[TMP1]]
48;
49  %tmp0 = lshr <3 x i8> <i8 -1, i8 undef, i8 -1>, %y
50  %tmp1 = and <3 x i8> %tmp0, %x
51  %ret = icmp ne <3 x i8> %tmp1, %x
52  ret <3 x i1> %ret
53}
54
55; ============================================================================ ;
56; Commutativity tests.
57; ============================================================================ ;
58
59declare i8 @gen8()
60
61define i1 @c0(i8 %y) {
62; CHECK-LABEL: @c0(
63; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
64; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
65; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
66; CHECK-NEXT:    ret i1 [[TMP1]]
67;
68  %tmp0 = lshr i8 -1, %y
69  %x = call i8 @gen8()
70  %tmp1 = and i8 %x, %tmp0 ; swapped order
71  %ret = icmp ne i8 %tmp1, %x
72  ret i1 %ret
73}
74
75define i1 @c1(i8 %y) {
76; CHECK-LABEL: @c1(
77; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
78; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
79; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
80; CHECK-NEXT:    ret i1 [[TMP1]]
81;
82  %tmp0 = lshr i8 -1, %y
83  %x = call i8 @gen8()
84  %tmp1 = and i8 %tmp0, %x
85  %ret = icmp ne i8 %x, %tmp1 ; swapped order
86  ret i1 %ret
87}
88
89define i1 @c2(i8 %y) {
90; CHECK-LABEL: @c2(
91; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
92; CHECK-NEXT:    [[X:%.*]] = call i8 @gen8()
93; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[X]], [[TMP0]]
94; CHECK-NEXT:    ret i1 [[TMP1]]
95;
96  %tmp0 = lshr i8 -1, %y
97  %x = call i8 @gen8()
98  %tmp1 = and i8 %x, %tmp0 ; swapped order
99  %ret = icmp ne i8 %x, %tmp1 ; swapped order
100  ret i1 %ret
101}
102
103; ============================================================================ ;
104; One-use tests. We don't care about multi-uses here.
105; ============================================================================ ;
106
107declare void @use8(i8)
108
109define i1 @oneuse0(i8 %x, i8 %y) {
110; CHECK-LABEL: @oneuse0(
111; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
112; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
113; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP0]], [[X:%.*]]
114; CHECK-NEXT:    ret i1 [[TMP1]]
115;
116  %tmp0 = lshr i8 -1, %y
117  call void @use8(i8 %tmp0)
118  %tmp1 = and i8 %tmp0, %x
119  %ret = icmp ne i8 %tmp1, %x
120  ret i1 %ret
121}
122
123define i1 @oneuse1(i8 %x, i8 %y) {
124; CHECK-LABEL: @oneuse1(
125; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
126; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]
127; CHECK-NEXT:    call void @use8(i8 [[TMP1]])
128; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP0]], [[X]]
129; CHECK-NEXT:    ret i1 [[TMP1]]
130;
131  %tmp0 = lshr i8 -1, %y
132  %tmp1 = and i8 %tmp0, %x
133  call void @use8(i8 %tmp1)
134  %ret = icmp ne i8 %tmp1, %x
135  ret i1 %ret
136}
137
138define i1 @oneuse2(i8 %x, i8 %y) {
139; CHECK-LABEL: @oneuse2(
140; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
141; CHECK-NEXT:    call void @use8(i8 [[TMP0]])
142; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]
143; CHECK-NEXT:    call void @use8(i8 [[TMP1]])
144; CHECK-NEXT:    [[TMP1:%.*]] = icmp ult i8 [[TMP0]], [[X]]
145; CHECK-NEXT:    ret i1 [[TMP1]]
146;
147  %tmp0 = lshr i8 -1, %y
148  call void @use8(i8 %tmp0)
149  %tmp1 = and i8 %tmp0, %x
150  call void @use8(i8 %tmp1)
151  %ret = icmp ne i8 %tmp1, %x
152  ret i1 %ret
153}
154
155; ============================================================================ ;
156; Negative tests
157; ============================================================================ ;
158
159define i1 @n0(i8 %x, i8 %y, i8 %notx) {
160; CHECK-LABEL: @n0(
161; CHECK-NEXT:    [[TMP0:%.*]] = lshr i8 -1, [[Y:%.*]]
162; CHECK-NEXT:    [[TMP1:%.*]] = and i8 [[TMP0]], [[X:%.*]]
163; CHECK-NEXT:    [[RET:%.*]] = icmp ne i8 [[TMP1]], [[NOTX:%.*]]
164; CHECK-NEXT:    ret i1 [[RET]]
165;
166  %tmp0 = lshr i8 -1, %y
167  %tmp1 = and i8 %tmp0, %x
168  %ret = icmp ne i8 %tmp1, %notx ; not %x
169  ret i1 %ret
170}
171