Skip to content

Commit 12816fe

Browse files
committed
Added tests for multiple uses.
1 parent 43c9db9 commit 12816fe

File tree

2 files changed

+194
-4
lines changed

2 files changed

+194
-4
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2830,10 +2830,17 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
28302830
NumOfNewInstrs += !isa<Constant>(Z) ? 1 : 0;
28312831
// Check if we can trade some of the old instructions for the new ones.
28322832
unsigned NumOfDeadInstrs = 0;
2833-
NumOfDeadInstrs += Op0->hasOneUse() ? 1 : 0;
2834-
NumOfDeadInstrs += Op1->hasOneUse() ? 1 : 0;
2835-
NumOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2836-
NumOfDeadInstrs += Add1->hasOneUse() ? 1 : 0;
2833+
if (Op0->hasOneUse()) {
2834+
// If Op0 (sext) has multiple uses, then we keep it
2835+
// and the add that it uses, otherwise, we can remove
2836+
// the sext and probably the add (depending on the number of its uses).
2837+
++NumOfDeadInstrs;
2838+
NumOfDeadInstrs += Add0->hasOneUse() ? 1 : 0;
2839+
}
2840+
if (Op1->hasOneUse()) {
2841+
++NumOfDeadInstrs;
2842+
NumOfDeadInstrs += Add1->hasOneUse() ? 1 : 0;
2843+
}
28372844
if (NumOfDeadInstrs >= NumOfNewInstrs) {
28382845
Value *SExtY = Builder.CreateSExt(Y, I.getType());
28392846
Value *SExtZ = Builder.CreateSExt(Z, I.getType());

llvm/test/Transforms/InstCombine/sub-sext-add.ll

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,189 @@ define i64 @src_2add_2sext_sub_nuw(i32 %x, i32 %y, i32 %z) {
106106
ret i64 %sub
107107
}
108108

109+
declare void @use_i32(i32, i32)
110+
declare void @use_i64(i64, i64)
111+
112+
define i64 @src_2add_2sext_sub_multiple_uses_1(i32 %x, i32 %y, i32 %z) {
113+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_1(
114+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
115+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
116+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y]] to i64
117+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
118+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
119+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT1]])
120+
; CHECK-NEXT: ret i64 [[SUB]]
121+
;
122+
%add1 = add nsw i32 %x, %y
123+
%add2 = add nsw i32 %x, %z
124+
%sext1 = sext i32 %add1 to i64
125+
%sext2 = sext i32 %add2 to i64
126+
%sub = sub i64 %sext1, %sext2
127+
call void @use_i64(i64 %sext1, i64 %sext1)
128+
ret i64 %sub
129+
}
130+
131+
define i64 @src_2add_2sext_sub_multiple_uses_2(i32 %x, i32 %y, i32 %z) {
132+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_2(
133+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X:%.*]], [[Z:%.*]]
134+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
135+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
136+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z]] to i64
137+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
138+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT2]], i64 [[SEXT2]])
139+
; CHECK-NEXT: ret i64 [[SUB]]
140+
;
141+
%add1 = add nsw i32 %x, %y
142+
%add2 = add nsw i32 %x, %z
143+
%sext1 = sext i32 %add1 to i64
144+
%sext2 = sext i32 %add2 to i64
145+
%sub = sub i64 %sext1, %sext2
146+
call void @use_i64(i64 %sext2, i64 %sext2)
147+
ret i64 %sub
148+
}
149+
150+
define i64 @src_2add_2sext_sub_multiple_uses_3(i32 %x, i32 %y, i32 %z) {
151+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_3(
152+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
153+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X]], [[Z:%.*]]
154+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
155+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
156+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
157+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT2]])
158+
; CHECK-NEXT: ret i64 [[SUB]]
159+
;
160+
%add1 = add nsw i32 %x, %y
161+
%add2 = add nsw i32 %x, %z
162+
%sext1 = sext i32 %add1 to i64
163+
%sext2 = sext i32 %add2 to i64
164+
%sub = sub i64 %sext1, %sext2
165+
call void @use_i64(i64 %sext1, i64 %sext2)
166+
ret i64 %sub
167+
}
168+
169+
define i64 @src_2add_2sext_sub_multiple_uses_4(i32 %x, i32 %y, i32 %z) {
170+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_4(
171+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
172+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X]], [[Z:%.*]]
173+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y]] to i64
174+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z]] to i64
175+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
176+
; CHECK-NEXT: call void @use_i32(i32 [[ADD1]], i32 [[ADD2]])
177+
; CHECK-NEXT: ret i64 [[SUB]]
178+
;
179+
%add1 = add nsw i32 %x, %y
180+
%add2 = add nsw i32 %x, %z
181+
%sext1 = sext i32 %add1 to i64
182+
%sext2 = sext i32 %add2 to i64
183+
%sub = sub i64 %sext1, %sext2
184+
call void @use_i32(i32 %add1, i32 %add2)
185+
ret i64 %sub
186+
}
187+
188+
define i64 @src_2add_2sext_sub_multiple_uses_5(i32 %x, i32 %y, i32 %z) {
189+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_5(
190+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
191+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
192+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y]] to i64
193+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z:%.*]] to i64
194+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
195+
; CHECK-NEXT: call void @use_i32(i32 [[ADD1]], i32 [[ADD1]])
196+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT1]])
197+
; CHECK-NEXT: ret i64 [[SUB]]
198+
;
199+
%add1 = add nsw i32 %x, %y
200+
%add2 = add nsw i32 %x, %z
201+
%sext1 = sext i32 %add1 to i64
202+
%sext2 = sext i32 %add2 to i64
203+
%sub = sub i64 %sext1, %sext2
204+
call void @use_i32(i32 %add1, i32 %add1)
205+
call void @use_i64(i64 %sext1, i64 %sext1)
206+
ret i64 %sub
207+
}
208+
209+
define i64 @src_2add_2sext_sub_multiple_uses_6(i32 %x, i32 %y, i32 %z) {
210+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_6(
211+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X:%.*]], [[Z:%.*]]
212+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
213+
; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[Y:%.*]] to i64
214+
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[Z]] to i64
215+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[TMP1]], [[TMP2]]
216+
; CHECK-NEXT: call void @use_i32(i32 [[ADD2]], i32 [[ADD2]])
217+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT2]], i64 [[SEXT2]])
218+
; CHECK-NEXT: ret i64 [[SUB]]
219+
;
220+
%add1 = add nsw i32 %x, %y
221+
%add2 = add nsw i32 %x, %z
222+
%sext1 = sext i32 %add1 to i64
223+
%sext2 = sext i32 %add2 to i64
224+
%sub = sub i64 %sext1, %sext2
225+
call void @use_i32(i32 %add2, i32 %add2)
226+
call void @use_i64(i64 %sext2, i64 %sext2)
227+
ret i64 %sub
228+
}
229+
230+
define i64 @src_2add_2sext_sub_multiple_uses_7(i32 %x, i32 %y, i32 %z) {
231+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_7(
232+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
233+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X]], [[Z:%.*]]
234+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
235+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
236+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
237+
; CHECK-NEXT: call void @use_i32(i32 [[ADD1]], i32 [[ADD2]])
238+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT2]])
239+
; CHECK-NEXT: ret i64 [[SUB]]
240+
;
241+
%add1 = add nsw i32 %x, %y
242+
%add2 = add nsw i32 %x, %z
243+
%sext1 = sext i32 %add1 to i64
244+
%sext2 = sext i32 %add2 to i64
245+
%sub = sub i64 %sext1, %sext2
246+
call void @use_i32(i32 %add1, i32 %add2)
247+
call void @use_i64(i64 %sext1, i64 %sext2)
248+
ret i64 %sub
249+
}
250+
251+
define i64 @src_2add_2sext_sub_multiple_uses_8(i32 %x, i32 %y) {
252+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_8(
253+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], [[Y:%.*]]
254+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X]], 1
255+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
256+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
257+
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i64 [[SEXT1]], [[SEXT2]]
258+
; CHECK-NEXT: call void @use_i32(i32 [[ADD1]], i32 [[ADD2]])
259+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT2]])
260+
; CHECK-NEXT: ret i64 [[SUB]]
261+
;
262+
%add1 = add nsw i32 %x, %y
263+
%add2 = add nsw i32 %x, 1
264+
%sext1 = sext i32 %add1 to i64
265+
%sext2 = sext i32 %add2 to i64
266+
%sub = sub i64 %sext1, %sext2
267+
call void @use_i32(i32 %add1, i32 %add2)
268+
call void @use_i64(i64 %sext1, i64 %sext2)
269+
ret i64 %sub
270+
}
271+
272+
define i64 @src_2add_2sext_sub_multiple_uses_9(i32 %x) {
273+
; CHECK-LABEL: @src_2add_2sext_sub_multiple_uses_9(
274+
; CHECK-NEXT: [[ADD1:%.*]] = add nsw i32 [[X:%.*]], 2
275+
; CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[X]], 1
276+
; CHECK-NEXT: [[SEXT1:%.*]] = sext i32 [[ADD1]] to i64
277+
; CHECK-NEXT: [[SEXT2:%.*]] = sext i32 [[ADD2]] to i64
278+
; CHECK-NEXT: call void @use_i32(i32 [[ADD1]], i32 [[ADD2]])
279+
; CHECK-NEXT: call void @use_i64(i64 [[SEXT1]], i64 [[SEXT2]])
280+
; CHECK-NEXT: ret i64 1
281+
;
282+
%add1 = add nsw i32 %x, 2
283+
%add2 = add nsw i32 %x, 1
284+
%sext1 = sext i32 %add1 to i64
285+
%sext2 = sext i32 %add2 to i64
286+
%sub = sub i64 %sext1, %sext2
287+
call void @use_i32(i32 %add1, i32 %add2)
288+
call void @use_i64(i64 %sext1, i64 %sext2)
289+
ret i64 %sub
290+
}
291+
109292
define i64 @src_x_add_2sext_sub_1(i32 %x, i32 %y) {
110293
; CHECK-LABEL: @src_x_add_2sext_sub_1(
111294
; CHECK-NEXT: [[SUB:%.*]] = sext i32 [[Y:%.*]] to i64

0 commit comments

Comments
 (0)