Skip to content

Commit 572493f

Browse files
Poseydon42aaryanshukla
authored andcommitted
[InstCombine] Fold negation of calls to ucmp/scmp by swapping its operands (llvm#98360)
Proofs: https://alive2.llvm.org/ce/z/cp_a36
1 parent 3a5f6d0 commit 572493f

File tree

3 files changed

+63
-0
lines changed

3 files changed

+63
-0
lines changed

llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ std::array<Value *, 2> Negator::getSortedOperandsOfBinOp(Instruction *I) {
222222
}
223223
break;
224224
}
225+
case Instruction::Call:
226+
if (auto *CI = dyn_cast<CmpIntrinsic>(I); CI && CI->hasOneUse())
227+
return Builder.CreateIntrinsic(CI->getType(), CI->getIntrinsicID(),
228+
{CI->getRHS(), CI->getLHS()});
229+
break;
225230
default:
226231
break; // Other instructions require recursive reasoning.
227232
}

llvm/test/Transforms/InstCombine/scmp.ll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
33

4+
declare void @use(i8 %value)
5+
46
define i1 @scmp_eq_0(i32 %x, i32 %y) {
57
; CHECK-LABEL: define i1 @scmp_eq_0(
68
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
@@ -154,3 +156,30 @@ define i1 @scmp_sle_neg_1(i32 %x, i32 %y) {
154156
%2 = icmp sle i8 %1, -1
155157
ret i1 %2
156158
}
159+
160+
; ========== Fold -scmp(x, y) => scmp(y, x) ==========
161+
define i8 @scmp_negated(i32 %x, i32 %y) {
162+
; CHECK-LABEL: define i8 @scmp_negated(
163+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
164+
; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[Y]], i32 [[X]])
165+
; CHECK-NEXT: ret i8 [[TMP2]]
166+
;
167+
%1 = call i8 @llvm.scmp(i32 %x, i32 %y)
168+
%2 = sub i8 0, %1
169+
ret i8 %2
170+
}
171+
172+
; Negative test: do not fold if the original scmp result is already used
173+
define i8 @scmp_negated_multiuse(i32 %x, i32 %y) {
174+
; CHECK-LABEL: define i8 @scmp_negated_multiuse(
175+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
176+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
177+
; CHECK-NEXT: call void @use(i8 [[TMP1]])
178+
; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[TMP1]]
179+
; CHECK-NEXT: ret i8 [[TMP2]]
180+
;
181+
%1 = call i8 @llvm.scmp(i32 %x, i32 %y)
182+
call void @use(i8 %1)
183+
%2 = sub i8 0, %1
184+
ret i8 %2
185+
}

llvm/test/Transforms/InstCombine/ucmp.ll

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
22
; RUN: opt < %s -passes=instcombine -S | FileCheck %s
33

4+
declare void @use(i8 %value)
5+
46
define i1 @ucmp_eq_0(i32 %x, i32 %y) {
57
; CHECK-LABEL: define i1 @ucmp_eq_0(
68
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
@@ -154,3 +156,30 @@ define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
154156
%2 = icmp sle i8 %1, -1
155157
ret i1 %2
156158
}
159+
160+
; ========== Fold -ucmp(x, y) => ucmp(y, x) ==========
161+
define i8 @ucmp_negated(i32 %x, i32 %y) {
162+
; CHECK-LABEL: define i8 @ucmp_negated(
163+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
164+
; CHECK-NEXT: [[TMP2:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[Y]], i32 [[X]])
165+
; CHECK-NEXT: ret i8 [[TMP2]]
166+
;
167+
%1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
168+
%2 = sub i8 0, %1
169+
ret i8 %2
170+
}
171+
172+
; Negative test: do not fold if the original ucmp result is already used
173+
define i8 @ucmp_negated_multiuse(i32 %x, i32 %y) {
174+
; CHECK-LABEL: define i8 @ucmp_negated_multiuse(
175+
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
176+
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
177+
; CHECK-NEXT: call void @use(i8 [[TMP1]])
178+
; CHECK-NEXT: [[TMP2:%.*]] = sub nsw i8 0, [[TMP1]]
179+
; CHECK-NEXT: ret i8 [[TMP2]]
180+
;
181+
%1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
182+
call void @use(i8 %1)
183+
%2 = sub i8 0, %1
184+
ret i8 %2
185+
}

0 commit comments

Comments
 (0)