From 37a41034b83395a3691193bf2e78b8d107ebf627 Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Mon, 14 Apr 2025 17:15:46 +0800 Subject: [PATCH 1/4] pre-commit test --- .../ConstraintElimination/uadd-usub-sat.ll | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll new file mode 100644 index 0000000000000..89a0a7717979d --- /dev/null +++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll @@ -0,0 +1,38 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5 +; RUN: opt -passes=constraint-elimination -S %s | FileCheck %s + +declare i64 @llvm.uadd.sat.i64(i64, i64) +declare i64 @llvm.usub.sat.i64(i64, i64) + +define i1 @uadd_sat_uge(i64 %a, i64 %b) { +; CHECK-LABEL: define i1 @uadd_sat_uge( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { +; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[A]], [[B]] +; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) +; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 1) +; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[ADD_SAT]], [[B]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %precond = icmp ugt i64 %a, %b + call void @llvm.assume(i1 %precond) + %add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 1) + %cmp = icmp ugt i64 %add.sat, %b + ret i1 %cmp +} + + +define i1 @usub_sat_ule(i64 %a, i64 %b) { +; CHECK-LABEL: define i1 @usub_sat_ule( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { +; CHECK-NEXT: [[PRECOND:%.*]] = icmp ult i64 [[A]], [[B]] +; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) +; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 1) +; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SUB_SAT]], [[B]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %precond = icmp ult i64 %a, %b + call void @llvm.assume(i1 %precond) + %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 1) + %cmp = icmp ult i64 %sub.sat, %b + ret i1 %cmp +} From 3f7fc12e018ca63f029fbf1f561d94bba2e6f23b Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Mon, 14 Apr 2025 17:19:32 +0800 Subject: [PATCH 2/4] [ConstraintElim] Simplify cmp after uadd.sat/usub.sat --- .../Transforms/Scalar/ConstraintElimination.cpp | 17 ++++++++++++++++- .../ConstraintElimination/uadd-usub-sat.ll | 6 ++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index 456f5086309cf..ea03b6e5d5570 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1141,6 +1141,8 @@ void State::addInfoFor(BasicBlock &BB) { break; [[fallthrough]]; case Intrinsic::abs: + case Intrinsic::uadd_sat: + case Intrinsic::usub_sat: WorkList.push_back(FactOrCheck::getInstFact(DT.getNode(&BB), &I)); break; } @@ -1891,13 +1893,26 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, AddFact(CmpInst::ICMP_SGE, CB.Inst, X); continue; } - if (auto *MinMax = dyn_cast(CB.Inst)) { Pred = ICmpInst::getNonStrictPredicate(MinMax->getPredicate()); AddFact(Pred, MinMax, MinMax->getLHS()); AddFact(Pred, MinMax, MinMax->getRHS()); continue; } + if (auto *SatI = dyn_cast(CB.Inst)) { + switch (SatI->getIntrinsicID()) { + default: + continue; + case Intrinsic::uadd_sat: + Pred = ICmpInst::ICMP_UGE; + break; + case Intrinsic::usub_sat: + Pred = ICmpInst::ICMP_ULE; + break; + } + AddFact(Pred, SatI, SatI->getLHS()); + continue; + } } Value *A = nullptr, *B = nullptr; diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll index 89a0a7717979d..ec30795a3e95a 100644 --- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll +++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll @@ -10,8 +10,7 @@ define i1 @uadd_sat_uge(i64 %a, i64 %b) { ; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[A]], [[B]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) ; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 1) -; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i64 [[ADD_SAT]], [[B]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %precond = icmp ugt i64 %a, %b call void @llvm.assume(i1 %precond) @@ -27,8 +26,7 @@ define i1 @usub_sat_ule(i64 %a, i64 %b) { ; CHECK-NEXT: [[PRECOND:%.*]] = icmp ult i64 [[A]], [[B]] ; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) ; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 1) -; CHECK-NEXT: [[CMP:%.*]] = icmp ult i64 [[SUB_SAT]], [[B]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %precond = icmp ult i64 %a, %b call void @llvm.assume(i1 %precond) From 40944b9ce5a9798aee9c417013cf56651fa89687 Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Mon, 14 Apr 2025 18:15:44 +0800 Subject: [PATCH 3/4] test --- .../ConstraintElimination/uadd-usub-sat.ll | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll index ec30795a3e95a..6feb87c49f406 100644 --- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll +++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll @@ -7,30 +7,40 @@ declare i64 @llvm.usub.sat.i64(i64, i64) define i1 @uadd_sat_uge(i64 %a, i64 %b) { ; CHECK-LABEL: define i1 @uadd_sat_uge( ; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { -; CHECK-NEXT: [[PRECOND:%.*]] = icmp ugt i64 [[A]], [[B]] -; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 1) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[ADD_SAT]], [[A]] +; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[ADD_SAT]], [[B]] +; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: ret i1 [[CMP]] ; - %precond = icmp ugt i64 %a, %b - call void @llvm.assume(i1 %precond) - %add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 1) - %cmp = icmp ugt i64 %add.sat, %b + %add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b) + %cmp1 = icmp uge i64 %add.sat, %a + %cmp2 = icmp uge i64 %add.sat, %b + %cmp = and i1 %cmp1, %cmp2 ret i1 %cmp } +define i1 @usub_sat_ule_lhs(i64 %a, i64 %b) { +; CHECK-LABEL: define i1 @usub_sat_ule_lhs( +; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { +; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[A]] +; CHECK-NEXT: ret i1 [[CMP]] +; + %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b) + %cmp = icmp ule i64 %sub.sat, %a + ret i1 %cmp +} -define i1 @usub_sat_ule(i64 %a, i64 %b) { -; CHECK-LABEL: define i1 @usub_sat_ule( +; Negative test +define i1 @usub_sat_not_ule_rhs(i64 %a, i64 %b) { +; CHECK-LABEL: define i1 @usub_sat_not_ule_rhs( ; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { -; CHECK-NEXT: [[PRECOND:%.*]] = icmp ult i64 [[A]], [[B]] -; CHECK-NEXT: call void @llvm.assume(i1 [[PRECOND]]) -; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 1) -; CHECK-NEXT: ret i1 true +; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) +; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[B]] +; CHECK-NEXT: ret i1 [[CMP]] ; - %precond = icmp ult i64 %a, %b - call void @llvm.assume(i1 %precond) - %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 1) - %cmp = icmp ult i64 %sub.sat, %b + %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b) + %cmp = icmp ule i64 %sub.sat, %b ret i1 %cmp } From 479ed213f3fdaf022e78f299ce14b7dca781a639 Mon Sep 17 00:00:00 2001 From: Iris Shi <0.0@owo.li> Date: Mon, 14 Apr 2025 18:18:00 +0800 Subject: [PATCH 4/4] update --- llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 12 ++++++------ .../ConstraintElimination/uadd-usub-sat.ll | 7 ++----- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index ea03b6e5d5570..ad41ea735f0fd 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1899,18 +1899,18 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, AddFact(Pred, MinMax, MinMax->getRHS()); continue; } - if (auto *SatI = dyn_cast(CB.Inst)) { - switch (SatI->getIntrinsicID()) { + if (auto *USatI = dyn_cast(CB.Inst)) { + switch (USatI->getIntrinsicID()) { default: - continue; + llvm_unreachable("Unexpected intrinsic."); case Intrinsic::uadd_sat: - Pred = ICmpInst::ICMP_UGE; + AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getLHS()); + AddFact(ICmpInst::ICMP_UGE, USatI, USatI->getRHS()); break; case Intrinsic::usub_sat: - Pred = ICmpInst::ICMP_ULE; + AddFact(ICmpInst::ICMP_ULE, USatI, USatI->getLHS()); break; } - AddFact(Pred, SatI, SatI->getLHS()); continue; } } diff --git a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll index 6feb87c49f406..b0db89dcfdab8 100644 --- a/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll +++ b/llvm/test/Transforms/ConstraintElimination/uadd-usub-sat.ll @@ -8,9 +8,7 @@ define i1 @uadd_sat_uge(i64 %a, i64 %b) { ; CHECK-LABEL: define i1 @uadd_sat_uge( ; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { ; CHECK-NEXT: [[ADD_SAT:%.*]] = call i64 @llvm.uadd.sat.i64(i64 [[A]], i64 [[B]]) -; CHECK-NEXT: [[CMP1:%.*]] = icmp uge i64 [[ADD_SAT]], [[A]] -; CHECK-NEXT: [[CMP2:%.*]] = icmp uge i64 [[ADD_SAT]], [[B]] -; CHECK-NEXT: [[CMP:%.*]] = and i1 [[CMP1]], [[CMP2]] +; CHECK-NEXT: [[CMP:%.*]] = and i1 true, true ; CHECK-NEXT: ret i1 [[CMP]] ; %add.sat = call i64 @llvm.uadd.sat.i64(i64 %a, i64 %b) @@ -24,8 +22,7 @@ define i1 @usub_sat_ule_lhs(i64 %a, i64 %b) { ; CHECK-LABEL: define i1 @usub_sat_ule_lhs( ; CHECK-SAME: i64 [[A:%.*]], i64 [[B:%.*]]) { ; CHECK-NEXT: [[SUB_SAT:%.*]] = call i64 @llvm.usub.sat.i64(i64 [[A]], i64 [[B]]) -; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[SUB_SAT]], [[A]] -; CHECK-NEXT: ret i1 [[CMP]] +; CHECK-NEXT: ret i1 true ; %sub.sat = call i64 @llvm.usub.sat.i64(i64 %a, i64 %b) %cmp = icmp ule i64 %sub.sat, %a