[llvm] [ConstraintElimination] Add support for UCMP/SCMP intrinsics (PR #97974)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jul 10 12:01:55 PDT 2024
https://github.com/Poseydon42 updated https://github.com/llvm/llvm-project/pull/97974
>From 4cc8e51b5c7ae9db99b710f2cde3e5a63b0cc5e6 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Sun, 7 Jul 2024 23:00:38 +0100
Subject: [PATCH 1/3] [ConstraintElimination] Add support for UCMP/SCMP
intrinsics
---
.../Scalar/ConstraintElimination.cpp | 26 +++++
.../Transforms/ConstraintElimination/uscmp.ll | 110 ++++++++++++++++++
2 files changed, 136 insertions(+)
create mode 100644 llvm/test/Transforms/ConstraintElimination/uscmp.ll
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 52d9969426105..ea382e8e7ef37 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1087,6 +1087,8 @@ void State::addInfoFor(BasicBlock &BB) {
}
// Enqueue ssub_with_overflow for simplification.
case Intrinsic::ssub_with_overflow:
+ case Intrinsic::ucmp:
+ case Intrinsic::scmp:
WorkList.push_back(
FactOrCheck::getCheck(DT.getNode(&BB), cast<CallInst>(&I)));
break;
@@ -1448,6 +1450,28 @@ static bool checkAndReplaceMinMax(MinMaxIntrinsic *MinMax, ConstraintInfo &Info,
return false;
}
+static bool checkAndReplaceCmp(CmpIntrinsic *I, ConstraintInfo &Info,
+ SmallVectorImpl<Instruction *> &ToRemove) {
+ Value *LHS = I->getOperand(0);
+ Value *RHS = I->getOperand(1);
+ if (checkCondition(I->getGTPredicate(), LHS, RHS, I, Info).value_or(false)) {
+ I->replaceAllUsesWith(ConstantInt::get(I->getType(), 1));
+ ToRemove.push_back(I);
+ return true;
+ }
+ if (checkCondition(I->getLTPredicate(), LHS, RHS, I, Info).value_or(false)) {
+ I->replaceAllUsesWith(ConstantInt::getSigned(I->getType(), -1));
+ ToRemove.push_back(I);
+ return true;
+ }
+ if (checkCondition(ICmpInst::ICMP_EQ, LHS, RHS, I, Info)) {
+ I->replaceAllUsesWith(ConstantInt::get(I->getType(), 0));
+ ToRemove.push_back(I);
+ return true;
+ }
+ return false;
+}
+
static void
removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
Module *ReproducerModule,
@@ -1750,6 +1774,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
Changed |= Simplified;
} else if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
Changed |= checkAndReplaceMinMax(MinMax, Info, ToRemove);
+ } else if (auto *CmpIntrinsic = dyn_cast<class CmpIntrinsic>(Inst)) {
+ Changed |= checkAndReplaceCmp(CmpIntrinsic, Info, ToRemove);
}
continue;
}
diff --git a/llvm/test/Transforms/ConstraintElimination/uscmp.ll b/llvm/test/Transforms/ConstraintElimination/uscmp.ll
new file mode 100644
index 0000000000000..16ca93f0427e7
--- /dev/null
+++ b/llvm/test/Transforms/ConstraintElimination/uscmp.ll
@@ -0,0 +1,110 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s
+
+define i8 @scmp_1(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_1(
+; CHECK-NEXT: [[COND:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 1
+; CHECK: false:
+; CHECK-NEXT: ret i8 20
+;
+ %cond = icmp sgt i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ %r = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %r
+false:
+ ret i8 20
+}
+
+define i8 @ucmp_1(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_1(
+; CHECK-NEXT: [[COND:%.*]] = icmp ult i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 -1
+; CHECK: false:
+; CHECK-NEXT: ret i8 20
+;
+ %cond = icmp ult i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ %r = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %r
+false:
+ ret i8 20
+}
+
+define i8 @scmp_2(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_2(
+; CHECK-NEXT: [[COND:%.*]] = icmp sge i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 20
+; CHECK: false:
+; CHECK-NEXT: ret i8 -1
+;
+ %cond = icmp sge i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ ret i8 20
+false:
+ %r = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %r
+}
+
+define i8 @ucmp_2(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_2(
+; CHECK-NEXT: [[COND:%.*]] = icmp ule i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 20
+; CHECK: false:
+; CHECK-NEXT: ret i8 1
+;
+ %cond = icmp ule i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ ret i8 20
+false:
+ %r = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %r
+}
+
+define i8 @scmp_3(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_3(
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 0
+; CHECK: false:
+; CHECK-NEXT: ret i8 20
+;
+ %cond = icmp eq i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ %r = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %r
+false:
+ ret i8 20
+}
+
+define i8 @ucmp_3(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_3(
+; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 0
+; CHECK: false:
+; CHECK-NEXT: ret i8 20
+;
+ %cond = icmp eq i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ %r = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %r
+false:
+ ret i8 20
+}
>From 114c4f8dd9b2f14d43de2455df4c7df9143adf90 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Tue, 9 Jul 2024 12:40:33 +0100
Subject: [PATCH 2/3] Added negative tests for mismatched signedness
---
.../Transforms/ConstraintElimination/uscmp.ll | 39 +++++++++++++++++++
1 file changed, 39 insertions(+)
diff --git a/llvm/test/Transforms/ConstraintElimination/uscmp.ll b/llvm/test/Transforms/ConstraintElimination/uscmp.ll
index 16ca93f0427e7..63ac050f2c3c5 100644
--- a/llvm/test/Transforms/ConstraintElimination/uscmp.ll
+++ b/llvm/test/Transforms/ConstraintElimination/uscmp.ll
@@ -108,3 +108,42 @@ true:
false:
ret i8 20
}
+
+; Negative test: signedness mismatch
+define i8 @scmp_4(i32 %x, i32 %y) {
+; CHECK-LABEL: @scmp_4(
+; CHECK-NEXT: [[COND:%.*]] = icmp ugt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 20
+; CHECK: false:
+; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.scmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %cond = icmp ugt i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ ret i8 20
+false:
+ %r = call i8 @llvm.scmp(i32 %x, i32 %y)
+ ret i8 %r
+}
+
+define i8 @ucmp_4(i32 %x, i32 %y) {
+; CHECK-LABEL: @ucmp_4(
+; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: br i1 [[COND]], label [[TRUE:%.*]], label [[FALSE:%.*]]
+; CHECK: true:
+; CHECK-NEXT: ret i8 20
+; CHECK: false:
+; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.ucmp.i8.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: ret i8 [[R]]
+;
+ %cond = icmp slt i32 %x, %y
+ br i1 %cond, label %true, label %false
+true:
+ ret i8 20
+false:
+ %r = call i8 @llvm.ucmp(i32 %x, i32 %y)
+ ret i8 %r
+}
>From 48a31bf1904a7c5993540a38351433ac6a477648 Mon Sep 17 00:00:00 2001
From: Poseydon42 <vvmposeydon at gmail.com>
Date: Wed, 10 Jul 2024 20:01:27 +0100
Subject: [PATCH 3/3] Variable renaming
---
llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index ea382e8e7ef37..c31173879af1e 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1774,8 +1774,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
Changed |= Simplified;
} else if (auto *MinMax = dyn_cast<MinMaxIntrinsic>(Inst)) {
Changed |= checkAndReplaceMinMax(MinMax, Info, ToRemove);
- } else if (auto *CmpIntrinsic = dyn_cast<class CmpIntrinsic>(Inst)) {
- Changed |= checkAndReplaceCmp(CmpIntrinsic, Info, ToRemove);
+ } else if (auto *CmpIntr = dyn_cast<CmpIntrinsic>(Inst)) {
+ Changed |= checkAndReplaceCmp(CmpIntr, Info, ToRemove);
}
continue;
}
More information about the llvm-commits
mailing list