1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
8 ; iff both x and y are free to invert.
10 declare void @use1(i1)
12 ; Most basic positive test
13 define i1 @t0(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
15 ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
16 ; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
17 ; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
18 ; CHECK-NEXT: ret i1 [[I3_NOT]]
20 %i1 = icmp eq i32 %v0, %v1
21 %i2 = icmp eq i32 %v2, %v3
27 ; All operands must be invertible
28 define i1 @n1(i1 %i1, i32 %v2, i32 %v3) {
30 ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
31 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1:%.*]]
32 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
33 ; CHECK-NEXT: ret i1 [[I4]]
35 %i2 = icmp eq i32 %v2, %v3
40 define i1 @n2(i32 %v0, i32 %v1, i1 %i2) {
42 ; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
43 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I1]], [[I2:%.*]]
44 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
45 ; CHECK-NEXT: ret i1 [[I4]]
47 %i1 = icmp eq i32 %v0, %v1
52 define i1 @n3(i1 %i1, i1 %i2) {
54 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2:%.*]], [[I1:%.*]]
55 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
56 ; CHECK-NEXT: ret i1 [[I4]]
63 ; All other uses of operands must be invertible
64 define i1 @n4(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
66 ; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
67 ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
68 ; CHECK-NEXT: call void @use1(i1 [[I1]])
69 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1]]
70 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
71 ; CHECK-NEXT: ret i1 [[I4]]
73 %i1 = icmp eq i32 %v0, %v1
74 %i2 = icmp eq i32 %v2, %v3
75 call void @use1(i1 %i1)
80 define i1 @n5(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
82 ; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
83 ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
84 ; CHECK-NEXT: call void @use1(i1 [[I2]])
85 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1]]
86 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
87 ; CHECK-NEXT: ret i1 [[I4]]
89 %i1 = icmp eq i32 %v0, %v1
90 %i2 = icmp eq i32 %v2, %v3
91 call void @use1(i1 %i2)
96 define i1 @n6(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
98 ; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
99 ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
100 ; CHECK-NEXT: call void @use1(i1 [[I1]])
101 ; CHECK-NEXT: call void @use1(i1 [[I2]])
102 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1]]
103 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
104 ; CHECK-NEXT: ret i1 [[I4]]
106 %i1 = icmp eq i32 %v0, %v1
107 %i2 = icmp eq i32 %v2, %v3
108 call void @use1(i1 %i1)
109 call void @use1(i1 %i2)
110 %i3 = and i1 %i2, %i1
115 ; Hands have invertible uses
116 define i1 @t7(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
118 ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
119 ; CHECK-NEXT: call void @use1(i1 [[I1]])
120 ; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
121 ; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
122 ; CHECK-NEXT: ret i1 [[I3_NOT]]
124 %i1 = icmp eq i32 %v0, %v1
125 %i1.not = xor i1 %i1, -1
126 call void @use1(i1 %i1.not)
127 %i2 = icmp eq i32 %v2, %v3
128 %i3 = and i1 %i2, %i1
132 define i1 @t8(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
134 ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
135 ; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
136 ; CHECK-NEXT: call void @use1(i1 [[I2]])
137 ; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
138 ; CHECK-NEXT: ret i1 [[I3_NOT]]
140 %i1 = icmp eq i32 %v0, %v1
141 %i2 = icmp eq i32 %v2, %v3
142 %i2.not = xor i1 %i2, -1
143 call void @use1(i1 %i2.not)
144 %i3 = and i1 %i2, %i1
148 define i1 @t9(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
150 ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
151 ; CHECK-NEXT: call void @use1(i1 [[I1]])
152 ; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
153 ; CHECK-NEXT: call void @use1(i1 [[I2]])
154 ; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
155 ; CHECK-NEXT: ret i1 [[I3_NOT]]
157 %i1 = icmp eq i32 %v0, %v1
158 %i1.not = xor i1 %i1, -1
159 call void @use1(i1 %i1.not)
160 %i2 = icmp eq i32 %v2, %v3
161 %i2.not = xor i1 %i2, -1
162 call void @use1(i1 %i2.not)
163 %i3 = and i1 %i2, %i1
168 ; Select can have other uses
170 ; Not all uses can be adapted
171 define i1 @n10(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {
173 ; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]
174 ; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]
175 ; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1]]
176 ; CHECK-NEXT: call void @use1(i1 [[I3]])
177 ; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true
178 ; CHECK-NEXT: ret i1 [[I4]]
180 %i1 = icmp eq i32 %v0, %v1
181 %i2 = icmp eq i32 %v2, %v3
182 %i3 = and i1 %i2, %i1
183 call void @use1(i1 %i3)
188 ; All other uses can be adapted.
189 define i1 @t11(i32 %v0, i32 %v1, i32 %v2, i32 %v3, i1 %v4, i1 %v5) {
191 ; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]]
192 ; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]]
193 ; CHECK-NEXT: [[I3_NOT:%.*]] = or i1 [[I2]], [[I1]]
194 ; CHECK-NEXT: [[I5:%.*]] = select i1 [[I3_NOT]], i1 [[V5:%.*]], i1 [[V4:%.*]]
195 ; CHECK-NEXT: call void @use1(i1 [[I5]])
196 ; CHECK-NEXT: ret i1 [[I3_NOT]]
198 %i1 = icmp eq i32 %v0, %v1
199 %i2 = icmp eq i32 %v2, %v3
200 %i3 = and i1 %i2, %i1
202 %i5 = select i1 %i3, i1 %v4, i1 %v5
203 call void @use1(i1 %i5)