[Transforms] Silence a warning in SROA.cpp (NFC)
[llvm-project.git] / llvm / test / Transforms / InstCombine / sub-from-sub.ll
blob7b9e2fe4e6cdf2d562d5367b6efb64a723992831
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -passes=instcombine %s -S -o - | FileCheck %s
4 ; ((X - Y) - Z)  -->  X - (Y + Z)  because we prefer add's.
6 declare void @use8(i8)
8 ; Basic test
9 define 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]]
15   %i0 = sub i8 %x, %y
16   %r = sub i8 %i0, %z
17   ret i8 %r
20 ; NSW/NUW flags are propagated
21 define 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]]
27   %o0 = sub nuw nsw i8 %x, %y
28   %r = sub nuw nsw i8 %o0, %z
29   ret i8 %r
32 ; NUW flags are propagated
33 define 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]]
39   %o0 = sub nuw i8 %x, %y
40   %r = sub nuw i8 %o0, %z
41   ret i8 %r
44 ; Negative tests
45 define 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]]
51   %o0 = sub nsw i8 %x, %y
52   %r = sub i8 %o0, %z
53   ret i8 %r
56 define 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]]
62   %o0 = sub nuw i8 %x, %y
63   %r = sub i8 %o0, %z
64   ret i8 %r
67 define 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]]
73   %o0 = sub i8 %x, %y
74   %r = sub nuw i8 %o0, %z
75   ret i8 %r
78 define 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]]
84   %o0 = sub nuw nsw i8 %x, %y
85   %r = sub i8 %o0, %z
86   ret i8 %r
89 define 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]]
95   %o0 = sub i8 %x, %y
96   %r = sub nuw nsw i8 %o0, %z
97   ret i8 %r
100 ; The inner sub must have single use.
101 define 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]]
108   %i0 = sub i8 %x, %y ; extra use
109   call void @use8(i8 %i0)
110   %r = sub i8 %i0, %z
111   ret i8 %r
114 ; What if some operand is constant?
116 define 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]]
122   %i0 = sub i8 42, %y
123   %r = sub i8 %i0, %z
124   ret i8 %r
127 define 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]]
133   %i0 = sub i8 %x, 42
134   %r = sub i8 %i0, %z
135   ret i8 %r
138 define 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]]
144   %i0 = sub i8 %x, %y
145   %r = sub i8 %i0, 42
146   ret i8 %r
149 ; What if some operand is constant and there was extra use?
151 define 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]]
158   %i0 = sub i8 42, %y
159   call void @use8(i8 %i0)
160   %r = sub i8 %i0, %z
161   ret i8 %r
164 define 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]]
171   %i0 = sub i8 %x, 42
172   call void @use8(i8 %i0)
173   %r = sub i8 %i0, %z
174   ret i8 %r
177 define 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]]
184   %i0 = sub i8 %x, %y
185   call void @use8(i8 %i0)
186   %r = sub i8 %i0, 42
187   ret i8 %r
190 ; What if two operands are constants?
192 define 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]]
197   %i0 = sub i8 42, %y
198   %r = sub i8 %i0, 24
199   ret i8 %r
202 define 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]]
207   %i0 = sub i8 %x, 42
208   %r = sub i8 %i0, 24
209   ret i8 %r
212 ; What if two operands are constants and there was extra use?
214 define 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]]
221   %i0 = sub i8 42, %y
222   call void @use8(i8 %i0)
223   %r = sub i8 %i0, 24
224   ret i8 %r
227 define 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]]
234   %i0 = sub i8 %x, 42
235   call void @use8(i8 %i0)
236   %r = sub i8 %i0, 24
237   ret i8 %r
240 ; PR49870
241 @g0 = external global i8, align 1
242 @g1 = external global i8, align 1
243 define 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]]
249   %i0 = add i32 %x, ptrtoint (ptr @g0 to i32)
250   %r = sub i32 0, %i0
251   ret i32 %r
253 define 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]]
259   %i0 = add i32 %x, 42
260   %r = sub i32 ptrtoint (ptr @g1 to i32), %i0
261   ret i32 %r
263 define 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]]
269   %i0 = add i32 %x, ptrtoint (ptr @g0 to i32)
270   %r = sub i32 ptrtoint (ptr @g1 to i32), %i0
271   ret i32 %r
274 define 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]]
280   %i0 = xor i64 %x, -1
281   %r = add i64 %i0, ptrtoint (ptr @g0 to i64)
282   ret i64 %r