Skip to content

Commit d163935

Browse files
authored
[InstCombine] Fold scmp(x -nsw y, 0) to scmp(x, y) (#105583)
Proof: https://alive2.llvm.org/ce/z/v6VtXz
1 parent f2027a9 commit d163935

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,6 +1929,15 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
19291929

19301930
break;
19311931
}
1932+
case Intrinsic::scmp: {
1933+
Value *I0 = II->getArgOperand(0), *I1 = II->getArgOperand(1);
1934+
Value *LHS, *RHS;
1935+
if (match(I0, m_NSWSub(m_Value(LHS), m_Value(RHS))) && match(I1, m_Zero()))
1936+
return replaceInstUsesWith(
1937+
CI,
1938+
Builder.CreateIntrinsic(II->getType(), Intrinsic::scmp, {LHS, RHS}));
1939+
break;
1940+
}
19321941
case Intrinsic::bitreverse: {
19331942
Value *IIOperand = II->getArgOperand(0);
19341943
// bitrev (zext i1 X to ?) --> X ? SignBitC : 0

llvm/test/Transforms/InstCombine/scmp.ll

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,3 +264,54 @@ define i8 @scmp_from_select_ge(i32 %x, i32 %y) {
264264
%r = select i1 %ge, i8 %ne, i8 -1
265265
ret i8 %r
266266
}
267+
268+
; Fold scmp(x nsw- y, 0) to scmp(x, y)
269+
define i8 @scmp_of_sub_and_zero(i32 %x, i32 %y) {
270+
; CHECK-LABEL: define i8 @scmp_of_sub_and_zero(
271+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
272+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
273+
; CHECK-NEXT: ret i8 [[R]]
274+
;
275+
%diff = sub nsw i32 %x, %y
276+
%r = call i8 @llvm.scmp(i32 %diff, i32 0)
277+
ret i8 %r
278+
}
279+
280+
; Negative test: no nsw
281+
define i8 @scmp_of_sub_and_zero_neg_1(i32 %x, i32 %y) {
282+
; CHECK-LABEL: define i8 @scmp_of_sub_and_zero_neg_1(
283+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
284+
; CHECK-NEXT: [[DIFF:%.*]] = sub i32 [[X]], [[Y]]
285+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[DIFF]], i32 0)
286+
; CHECK-NEXT: ret i8 [[R]]
287+
;
288+
%diff = sub i32 %x, %y
289+
%r = call i8 @llvm.scmp(i32 %diff, i32 0)
290+
ret i8 %r
291+
}
292+
293+
; Negative test: second argument of scmp is not 0
294+
define i8 @scmp_of_sub_and_zero_neg2(i32 %x, i32 %y) {
295+
; CHECK-LABEL: define i8 @scmp_of_sub_and_zero_neg2(
296+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
297+
; CHECK-NEXT: [[DIFF:%.*]] = sub nsw i32 [[X]], [[Y]]
298+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[DIFF]], i32 15)
299+
; CHECK-NEXT: ret i8 [[R]]
300+
;
301+
%diff = sub nsw i32 %x, %y
302+
%r = call i8 @llvm.scmp(i32 %diff, i32 15)
303+
ret i8 %r
304+
}
305+
306+
; Negative test: calling ucmp instead of scmp
307+
define i8 @scmp_of_sub_and_zero_neg3(i32 %x, i32 %y) {
308+
; CHECK-LABEL: define i8 @scmp_of_sub_and_zero_neg3(
309+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
310+
; CHECK-NEXT: [[DIFF:%.*]] = sub nsw i32 [[X]], [[Y]]
311+
; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[DIFF]], i32 0)
312+
; CHECK-NEXT: ret i8 [[R]]
313+
;
314+
%diff = sub nsw i32 %x, %y
315+
%r = call i8 @llvm.ucmp(i32 %diff, i32 0)
316+
ret i8 %r
317+
}

0 commit comments

Comments
 (0)