xref: /llvm-project/llvm/test/Transforms/InstCombine/sub-from-sub.ll (revision dfe1d35c629f2948c0e8cf29d926729b1dbc1709)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -passes=instcombine %s -S -o - | FileCheck %s
3
4; ((X - Y) - Z)  -->  X - (Y + Z)  because we prefer add's.
5
6declare void @use8(i8)
7
8; Basic test
9define i8 @t0(i8 %x, i8 %y, i8 %z) {
10; CHECK-LABEL: @t0(
11; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
12; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
13; CHECK-NEXT:    ret i8 [[R]]
14;
15  %i0 = sub i8 %x, %y
16  %r = sub i8 %i0, %z
17  ret i8 %r
18}
19
20; NSW/NUW flags are propagated
21define i8 @t1_flags(i8 %x, i8 %y, i8 %z) {
22; CHECK-LABEL: @t1_flags(
23; CHECK-NEXT:    [[TMP1:%.*]] = add nuw nsw i8 [[Y:%.*]], [[Z:%.*]]
24; CHECK-NEXT:    [[R:%.*]] = sub nuw nsw i8 [[X:%.*]], [[TMP1]]
25; CHECK-NEXT:    ret i8 [[R]]
26;
27  %o0 = sub nuw nsw i8 %x, %y
28  %r = sub nuw nsw i8 %o0, %z
29  ret i8 %r
30}
31
32; NUW flags are propagated
33define i8 @t1_flags_nuw_only(i8 %x, i8 %y, i8 %z) {
34; CHECK-LABEL: @t1_flags_nuw_only(
35; CHECK-NEXT:    [[TMP1:%.*]] = add nuw i8 [[Y:%.*]], [[Z:%.*]]
36; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[X:%.*]], [[TMP1]]
37; CHECK-NEXT:    ret i8 [[R]]
38;
39  %o0 = sub nuw i8 %x, %y
40  %r = sub nuw i8 %o0, %z
41  ret i8 %r
42}
43
44; Negative tests
45define i8 @t1_flags_sub_nsw_sub(i8 %x, i8 %y, i8 %z) {
46; CHECK-LABEL: @t1_flags_sub_nsw_sub(
47; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
48; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
49; CHECK-NEXT:    ret i8 [[R]]
50;
51  %o0 = sub nsw i8 %x, %y
52  %r = sub i8 %o0, %z
53  ret i8 %r
54}
55
56define i8 @t1_flags_nuw_first(i8 %x, i8 %y, i8 %z) {
57; CHECK-LABEL: @t1_flags_nuw_first(
58; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
59; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
60; CHECK-NEXT:    ret i8 [[R]]
61;
62  %o0 = sub nuw i8 %x, %y
63  %r = sub i8 %o0, %z
64  ret i8 %r
65}
66
67define i8 @t1_flags_nuw_second(i8 %x, i8 %y, i8 %z) {
68; CHECK-LABEL: @t1_flags_nuw_second(
69; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
70; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
71; CHECK-NEXT:    ret i8 [[R]]
72;
73  %o0 = sub i8 %x, %y
74  %r = sub nuw i8 %o0, %z
75  ret i8 %r
76}
77
78define i8 @t1_flags_nuw_nsw_first(i8 %x, i8 %y, i8 %z) {
79; CHECK-LABEL: @t1_flags_nuw_nsw_first(
80; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
81; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
82; CHECK-NEXT:    ret i8 [[R]]
83;
84  %o0 = sub nuw nsw i8 %x, %y
85  %r = sub i8 %o0, %z
86  ret i8 %r
87}
88
89define i8 @t1_flags_nuw_nsw_second(i8 %x, i8 %y, i8 %z) {
90; CHECK-LABEL: @t1_flags_nuw_nsw_second(
91; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
92; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
93; CHECK-NEXT:    ret i8 [[R]]
94;
95  %o0 = sub i8 %x, %y
96  %r = sub nuw nsw i8 %o0, %z
97  ret i8 %r
98}
99
100; The inner sub must have single use.
101define i8 @n2(i8 %x, i8 %y, i8 %z) {
102; CHECK-LABEL: @n2(
103; CHECK-NEXT:    [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
104; CHECK-NEXT:    call void @use8(i8 [[I0]])
105; CHECK-NEXT:    [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]]
106; CHECK-NEXT:    ret i8 [[R]]
107;
108  %i0 = sub i8 %x, %y ; extra use
109  call void @use8(i8 %i0)
110  %r = sub i8 %i0, %z
111  ret i8 %r
112}
113
114; What if some operand is constant?
115
116define i8 @t3_c0(i8 %y, i8 %z) {
117; CHECK-LABEL: @t3_c0(
118; CHECK-NEXT:    [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
119; CHECK-NEXT:    [[R:%.*]] = sub i8 42, [[TMP1]]
120; CHECK-NEXT:    ret i8 [[R]]
121;
122  %i0 = sub i8 42, %y
123  %r = sub i8 %i0, %z
124  ret i8 %r
125}
126
127define i8 @t4_c1(i8 %x, i8 %z) {
128; CHECK-LABEL: @t4_c1(
129; CHECK-NEXT:    [[I0:%.*]] = add i8 [[X:%.*]], -42
130; CHECK-NEXT:    [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]]
131; CHECK-NEXT:    ret i8 [[R]]
132;
133  %i0 = sub i8 %x, 42
134  %r = sub i8 %i0, %z
135  ret i8 %r
136}
137
138define i8 @t5_c2(i8 %x, i8 %y) {
139; CHECK-LABEL: @t5_c2(
140; CHECK-NEXT:    [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
141; CHECK-NEXT:    [[R:%.*]] = add i8 [[I0]], -42
142; CHECK-NEXT:    ret i8 [[R]]
143;
144  %i0 = sub i8 %x, %y
145  %r = sub i8 %i0, 42
146  ret i8 %r
147}
148
149; What if some operand is constant and there was extra use?
150
151define i8 @t6_c0_extrause(i8 %y, i8 %z) {
152; CHECK-LABEL: @t6_c0_extrause(
153; CHECK-NEXT:    [[I0:%.*]] = sub i8 42, [[Y:%.*]]
154; CHECK-NEXT:    call void @use8(i8 [[I0]])
155; CHECK-NEXT:    [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]]
156; CHECK-NEXT:    ret i8 [[R]]
157;
158  %i0 = sub i8 42, %y
159  call void @use8(i8 %i0)
160  %r = sub i8 %i0, %z
161  ret i8 %r
162}
163
164define i8 @t7_c1_extrause(i8 %x, i8 %z) {
165; CHECK-LABEL: @t7_c1_extrause(
166; CHECK-NEXT:    [[I0:%.*]] = add i8 [[X:%.*]], -42
167; CHECK-NEXT:    call void @use8(i8 [[I0]])
168; CHECK-NEXT:    [[R:%.*]] = sub i8 [[I0]], [[Z:%.*]]
169; CHECK-NEXT:    ret i8 [[R]]
170;
171  %i0 = sub i8 %x, 42
172  call void @use8(i8 %i0)
173  %r = sub i8 %i0, %z
174  ret i8 %r
175}
176
177define i8 @t8_c2_extrause(i8 %x, i8 %y) {
178; CHECK-LABEL: @t8_c2_extrause(
179; CHECK-NEXT:    [[I0:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
180; CHECK-NEXT:    call void @use8(i8 [[I0]])
181; CHECK-NEXT:    [[R:%.*]] = add i8 [[I0]], -42
182; CHECK-NEXT:    ret i8 [[R]]
183;
184  %i0 = sub i8 %x, %y
185  call void @use8(i8 %i0)
186  %r = sub i8 %i0, 42
187  ret i8 %r
188}
189
190; What if two operands are constants?
191
192define i8 @t9_c0_c2(i8 %y, i8 %z) {
193; CHECK-LABEL: @t9_c0_c2(
194; CHECK-NEXT:    [[R:%.*]] = sub i8 18, [[Y:%.*]]
195; CHECK-NEXT:    ret i8 [[R]]
196;
197  %i0 = sub i8 42, %y
198  %r = sub i8 %i0, 24
199  ret i8 %r
200}
201
202define i8 @t10_c1_c2(i8 %x, i8 %z) {
203; CHECK-LABEL: @t10_c1_c2(
204; CHECK-NEXT:    [[R:%.*]] = add i8 [[X:%.*]], -66
205; CHECK-NEXT:    ret i8 [[R]]
206;
207  %i0 = sub i8 %x, 42
208  %r = sub i8 %i0, 24
209  ret i8 %r
210}
211
212; What if two operands are constants and there was extra use?
213
214define i8 @t11_c0_c2_extrause(i8 %y, i8 %z) {
215; CHECK-LABEL: @t11_c0_c2_extrause(
216; CHECK-NEXT:    [[I0:%.*]] = sub i8 42, [[Y:%.*]]
217; CHECK-NEXT:    call void @use8(i8 [[I0]])
218; CHECK-NEXT:    [[R:%.*]] = sub i8 18, [[Y]]
219; CHECK-NEXT:    ret i8 [[R]]
220;
221  %i0 = sub i8 42, %y
222  call void @use8(i8 %i0)
223  %r = sub i8 %i0, 24
224  ret i8 %r
225}
226
227define i8 @t12_c1_c2_exrause(i8 %x, i8 %z) {
228; CHECK-LABEL: @t12_c1_c2_exrause(
229; CHECK-NEXT:    [[I0:%.*]] = add i8 [[X:%.*]], -42
230; CHECK-NEXT:    call void @use8(i8 [[I0]])
231; CHECK-NEXT:    [[R:%.*]] = add i8 [[X]], -66
232; CHECK-NEXT:    ret i8 [[R]]
233;
234  %i0 = sub i8 %x, 42
235  call void @use8(i8 %i0)
236  %r = sub i8 %i0, 24
237  ret i8 %r
238}
239
240; PR49870
241@g0 = external global i8, align 1
242@g1 = external global i8, align 1
243define i32 @constantexpr0(i32 %x, ptr %y) unnamed_addr {
244; CHECK-LABEL: @constantexpr0(
245; CHECK-NEXT:    [[I0:%.*]] = add i32 [[X:%.*]], ptrtoint (ptr @g0 to i32)
246; CHECK-NEXT:    [[R:%.*]] = sub i32 0, [[I0]]
247; CHECK-NEXT:    ret i32 [[R]]
248;
249  %i0 = add i32 %x, ptrtoint (ptr @g0 to i32)
250  %r = sub i32 0, %i0
251  ret i32 %r
252}
253define i32 @constantexpr1(i32 %x, ptr %y) unnamed_addr {
254; CHECK-LABEL: @constantexpr1(
255; CHECK-NEXT:    [[I0:%.*]] = add i32 [[X:%.*]], 42
256; CHECK-NEXT:    [[R:%.*]] = sub i32 ptrtoint (ptr @g1 to i32), [[I0]]
257; CHECK-NEXT:    ret i32 [[R]]
258;
259  %i0 = add i32 %x, 42
260  %r = sub i32 ptrtoint (ptr @g1 to i32), %i0
261  ret i32 %r
262}
263define i32 @constantexpr2(i32 %x, ptr %y) unnamed_addr {
264; CHECK-LABEL: @constantexpr2(
265; CHECK-NEXT:    [[I0:%.*]] = add i32 [[X:%.*]], ptrtoint (ptr @g0 to i32)
266; CHECK-NEXT:    [[R:%.*]] = sub i32 ptrtoint (ptr @g1 to i32), [[I0]]
267; CHECK-NEXT:    ret i32 [[R]]
268;
269  %i0 = add i32 %x, ptrtoint (ptr @g0 to i32)
270  %r = sub i32 ptrtoint (ptr @g1 to i32), %i0
271  ret i32 %r
272}
273
274define i64 @pr49870(i64 %x) {
275; CHECK-LABEL: @pr49870(
276; CHECK-NEXT:    [[I0:%.*]] = xor i64 [[X:%.*]], -1
277; CHECK-NEXT:    [[R:%.*]] = add i64 [[I0]], ptrtoint (ptr @g0 to i64)
278; CHECK-NEXT:    ret i64 [[R]]
279;
280  %i0 = xor i64 %x, -1
281  %r = add i64 %i0, ptrtoint (ptr @g0 to i64)
282  ret i64 %r
283}
284