xref: /llvm-project/llvm/test/Transforms/InstCombine/conditional-negation.ll (revision a105877646d68e48cdeeeadd9d1e075dc3c5d68d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; Basic pattern
5define i8 @t0(i8 %x, i1 %cond) {
6; CHECK-LABEL: @t0(
7; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
8; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]]
9; CHECK-NEXT:    ret i8 [[XOR]]
10;
11  %cond.splat = sext i1 %cond to i8
12  %sub = add i8 %cond.splat, %x
13  %xor = xor i8 %sub, %cond.splat
14  ret i8 %xor
15}
16define <2 x i8> @t0_vec(<2 x i8> %x, <2 x i1> %cond) {
17; CHECK-LABEL: @t0_vec(
18; CHECK-NEXT:    [[X_NEG:%.*]] = sub <2 x i8> zeroinitializer, [[X:%.*]]
19; CHECK-NEXT:    [[XOR:%.*]] = select <2 x i1> [[COND:%.*]], <2 x i8> [[X_NEG]], <2 x i8> [[X]]
20; CHECK-NEXT:    ret <2 x i8> [[XOR]]
21;
22  %cond.splat = sext <2 x i1> %cond to <2 x i8>
23  %sub = add <2 x i8> %cond.splat, %x
24  %xor = xor <2 x i8> %sub, %cond.splat
25  ret <2 x i8> %xor
26}
27
28; Two different extensions are fine
29define i8 @t1(i8 %x, i1 %cond) {
30; CHECK-LABEL: @t1(
31; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
32; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]]
33; CHECK-NEXT:    ret i8 [[XOR]]
34;
35  %cond.splat0 = sext i1 %cond to i8
36  %cond.splat1 = sext i1 %cond to i8
37  %sub = add i8 %cond.splat0, %x
38  %xor = xor i8 %sub, %cond.splat1
39  ret i8 %xor
40}
41
42; Two different extensions of different conditions are not fine
43define i8 @t2(i8 %x, i1 %cond0, i1 %cond1) {
44; CHECK-LABEL: @t2(
45; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND0:%.*]] to i8
46; CHECK-NEXT:    [[COND_SPLAT1:%.*]] = sext i1 [[COND1:%.*]] to i8
47; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]]
48; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]]
49; CHECK-NEXT:    ret i8 [[XOR]]
50;
51  %cond.splat0 = sext i1 %cond0 to i8
52  %cond.splat1 = sext i1 %cond1 to i8
53  %sub = add i8 %cond.splat0, %x
54  %xor = xor i8 %sub, %cond.splat1
55  ret i8 %xor
56}
57
58; Condition must be boolean.
59define i8 @t3(i8 %x, i2 %cond) {
60; CHECK-LABEL: @t3(
61; CHECK-NEXT:    [[COND_SPLAT:%.*]] = sext i2 [[COND:%.*]] to i8
62; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]]
63; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]]
64; CHECK-NEXT:    ret i8 [[XOR]]
65;
66  %cond.splat = sext i2 %cond to i8
67  %sub = add i8 %cond.splat, %x
68  %xor = xor i8 %sub, %cond.splat
69  ret i8 %xor
70}
71define <2 x i8> @t3_vec(<2 x i8> %x, <2 x i2> %cond) {
72; CHECK-LABEL: @t3_vec(
73; CHECK-NEXT:    [[COND_SPLAT:%.*]] = sext <2 x i2> [[COND:%.*]] to <2 x i8>
74; CHECK-NEXT:    [[SUB:%.*]] = add <2 x i8> [[X:%.*]], [[COND_SPLAT]]
75; CHECK-NEXT:    [[XOR:%.*]] = xor <2 x i8> [[SUB]], [[COND_SPLAT]]
76; CHECK-NEXT:    ret <2 x i8> [[XOR]]
77;
78  %cond.splat = sext <2 x i2> %cond to <2 x i8>
79  %sub = add <2 x i8> %cond.splat, %x
80  %xor = xor <2 x i8> %sub, %cond.splat
81  ret <2 x i8> %xor
82}
83
84; add is commutative
85; xor is not commutative here because of complexity ordering
86define i8 @xor.commuted(i1 %cond) {
87; CHECK-LABEL: @xor.commuted(
88; CHECK-NEXT:    [[X:%.*]] = call i8 @gen.i8()
89; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X]]
90; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND:%.*]], i8 [[X_NEG]], i8 [[X]]
91; CHECK-NEXT:    ret i8 [[XOR]]
92;
93  %cond.splat = sext i1 %cond to i8
94  %x = call i8 @gen.i8()
95  %sub = add i8 %x, %cond.splat
96  %xor = xor i8 %sub, %cond.splat
97  ret i8 %xor
98}
99
100; Extra use tests
101define i8 @extrause01_v1(i8 %x, i1 %cond) {
102; CHECK-LABEL: @extrause01_v1(
103; CHECK-NEXT:    [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8
104; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT]])
105; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
106; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
107; CHECK-NEXT:    ret i8 [[XOR]]
108;
109  %cond.splat = sext i1 %cond to i8
110  call void @use.i8(i8 %cond.splat)
111  %sub = add i8 %cond.splat, %x
112  %xor = xor i8 %sub, %cond.splat
113  ret i8 %xor
114}
115define i8 @extrause10_v1(i8 %x, i1 %cond) {
116; CHECK-LABEL: @extrause10_v1(
117; CHECK-NEXT:    [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8
118; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]]
119; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
120; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]]
121; CHECK-NEXT:    ret i8 [[XOR]]
122;
123  %cond.splat = sext i1 %cond to i8
124  %sub = add i8 %cond.splat, %x
125  call void @use.i8(i8 %sub)
126  %xor = xor i8 %sub, %cond.splat
127  ret i8 %xor
128}
129define i8 @extrause11_v1(i8 %x, i1 %cond) {
130; CHECK-LABEL: @extrause11_v1(
131; CHECK-NEXT:    [[COND_SPLAT:%.*]] = sext i1 [[COND:%.*]] to i8
132; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT]])
133; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT]]
134; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
135; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT]]
136; CHECK-NEXT:    ret i8 [[XOR]]
137;
138  %cond.splat = sext i1 %cond to i8
139  call void @use.i8(i8 %cond.splat)
140  %sub = add i8 %cond.splat, %x
141  call void @use.i8(i8 %sub)
142  %xor = xor i8 %sub, %cond.splat
143  ret i8 %xor
144}
145
146; Extra use tests with two extensions
147define i8 @extrause001_v2(i8 %x, i1 %cond) {
148; CHECK-LABEL: @extrause001_v2(
149; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
150; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT0]])
151; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
152; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
153; CHECK-NEXT:    ret i8 [[XOR]]
154;
155  %cond.splat0 = sext i1 %cond to i8
156  call void @use.i8(i8 %cond.splat0)
157  %cond.splat1 = sext i1 %cond to i8
158  %sub = add i8 %cond.splat0, %x
159  %xor = xor i8 %sub, %cond.splat1
160  ret i8 %xor
161}
162define i8 @extrause010_v2(i8 %x, i1 %cond) {
163; CHECK-LABEL: @extrause010_v2(
164; CHECK-NEXT:    [[COND_SPLAT1:%.*]] = sext i1 [[COND:%.*]] to i8
165; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT1]])
166; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
167; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
168; CHECK-NEXT:    ret i8 [[XOR]]
169;
170  %cond.splat0 = sext i1 %cond to i8
171  %cond.splat1 = sext i1 %cond to i8
172  call void @use.i8(i8 %cond.splat1)
173  %sub = add i8 %cond.splat0, %x
174  %xor = xor i8 %sub, %cond.splat1
175  ret i8 %xor
176}
177define i8 @extrause011_v2(i8 %x, i1 %cond) {
178; CHECK-LABEL: @extrause011_v2(
179; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
180; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT0]])
181; CHECK-NEXT:    [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8
182; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT1]])
183; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X:%.*]]
184; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
185; CHECK-NEXT:    ret i8 [[XOR]]
186;
187  %cond.splat0 = sext i1 %cond to i8
188  call void @use.i8(i8 %cond.splat0)
189  %cond.splat1 = sext i1 %cond to i8
190  call void @use.i8(i8 %cond.splat1)
191  %sub = add i8 %cond.splat0, %x
192  %xor = xor i8 %sub, %cond.splat1
193  ret i8 %xor
194}
195define i8 @extrause100_v2(i8 %x, i1 %cond) {
196; CHECK-LABEL: @extrause100_v2(
197; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
198; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]]
199; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
200; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X]]
201; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
202; CHECK-NEXT:    ret i8 [[XOR]]
203;
204  %cond.splat0 = sext i1 %cond to i8
205  %cond.splat1 = sext i1 %cond to i8
206  %sub = add i8 %cond.splat0, %x
207  call void @use.i8(i8 %sub)
208  %xor = xor i8 %sub, %cond.splat1
209  ret i8 %xor
210}
211define i8 @extrause101_v2(i8 %x, i1 %cond) {
212; CHECK-LABEL: @extrause101_v2(
213; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
214; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT0]])
215; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]]
216; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
217; CHECK-NEXT:    [[X_NEG:%.*]] = sub i8 0, [[X]]
218; CHECK-NEXT:    [[XOR:%.*]] = select i1 [[COND]], i8 [[X_NEG]], i8 [[X]]
219; CHECK-NEXT:    ret i8 [[XOR]]
220;
221  %cond.splat0 = sext i1 %cond to i8
222  call void @use.i8(i8 %cond.splat0)
223  %cond.splat1 = sext i1 %cond to i8
224  %sub = add i8 %cond.splat0, %x
225  call void @use.i8(i8 %sub)
226  %xor = xor i8 %sub, %cond.splat1
227  ret i8 %xor
228}
229define i8 @extrause110_v2(i8 %x, i1 %cond) {
230; CHECK-LABEL: @extrause110_v2(
231; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
232; CHECK-NEXT:    [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8
233; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT1]])
234; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]]
235; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
236; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]]
237; CHECK-NEXT:    ret i8 [[XOR]]
238;
239  %cond.splat0 = sext i1 %cond to i8
240  %cond.splat1 = sext i1 %cond to i8
241  call void @use.i8(i8 %cond.splat1)
242  %sub = add i8 %cond.splat0, %x
243  call void @use.i8(i8 %sub)
244  %xor = xor i8 %sub, %cond.splat1
245  ret i8 %xor
246}
247define i8 @extrause111_v2(i8 %x, i1 %cond) {
248; CHECK-LABEL: @extrause111_v2(
249; CHECK-NEXT:    [[COND_SPLAT0:%.*]] = sext i1 [[COND:%.*]] to i8
250; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT0]])
251; CHECK-NEXT:    [[COND_SPLAT1:%.*]] = sext i1 [[COND]] to i8
252; CHECK-NEXT:    call void @use.i8(i8 [[COND_SPLAT1]])
253; CHECK-NEXT:    [[SUB:%.*]] = add i8 [[X:%.*]], [[COND_SPLAT0]]
254; CHECK-NEXT:    call void @use.i8(i8 [[SUB]])
255; CHECK-NEXT:    [[XOR:%.*]] = xor i8 [[SUB]], [[COND_SPLAT1]]
256; CHECK-NEXT:    ret i8 [[XOR]]
257;
258  %cond.splat0 = sext i1 %cond to i8
259  call void @use.i8(i8 %cond.splat0)
260  %cond.splat1 = sext i1 %cond to i8
261  call void @use.i8(i8 %cond.splat1)
262  %sub = add i8 %cond.splat0, %x
263  call void @use.i8(i8 %sub)
264  %xor = xor i8 %sub, %cond.splat1
265  ret i8 %xor
266}
267
268declare void @use.i8(i8)
269declare i8 @gen.i8()
270