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.
9 define i8 @t0(i8 %x, i8 %y, i8 %z) {
11 ; CHECK-NEXT: [[TMP1:%.*]] = add i8 [[Y:%.*]], [[Z:%.*]]
12 ; CHECK-NEXT: [[R:%.*]] = sub i8 [[X:%.*]], [[TMP1]]
13 ; CHECK-NEXT: 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
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
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
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
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]]
74 %r = sub nuw i8 %o0, %z
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
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]]
96 %r = sub nuw nsw i8 %o0, %z
100 ; The inner sub must have single use.
101 define i8 @n2(i8 %x, i8 %y, i8 %z) {
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)
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]]
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]]
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]]
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]]
159 call void @use8(i8 %i0)
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]]
172 call void @use8(i8 %i0)
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]]
185 call void @use8(i8 %i0)
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]]
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]]
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]]
222 call void @use8(i8 %i0)
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]]
235 call void @use8(i8 %i0)
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)
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]]
260 %r = sub i32 ptrtoint (ptr @g1 to i32), %i0
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
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]]
281 %r = add i64 %i0, ptrtoint (ptr @g0 to i64)