Skip to content

[InstCombine] Implement folds of icmp of UCMP/SCMP call and a constant #96118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 22, 2024

Conversation

Poseydon42
Copy link
Contributor

This patch handles various cases where an operation of the kind icmp (ucmp/scmp x, y), constant folds to icmp x, y. Another patch with cases where this operation folds to a constant (i.e. dumb cases like icmp eq (cmp x, y), 4 should be published in a couple of days.

I wasn't sure what negative tests should be added here, if any are necessary at all. I'd love to hear your suggestions.

Proofs (ucmp): https://alive2.llvm.org/ce/z/qQ7ihz
Proofs (scmp): https://alive2.llvm.org/ce/z/cipKEn

@llvmbot
Copy link
Member

llvmbot commented Jun 19, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (Poseydon42)

Changes

This patch handles various cases where an operation of the kind icmp (ucmp/scmp x, y), constant folds to icmp x, y. Another patch with cases where this operation folds to a constant (i.e. dumb cases like icmp eq (cmp x, y), 4 should be published in a couple of days.

I wasn't sure what negative tests should be added here, if any are necessary at all. I'd love to hear your suggestions.

Proofs (ucmp): https://alive2.llvm.org/ce/z/qQ7ihz
Proofs (scmp): https://alive2.llvm.org/ce/z/cipKEn


Full diff: https://github.com/llvm/llvm-project/pull/96118.diff

3 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp (+91)
  • (added) llvm/test/Transforms/InstCombine/scmp.ll (+156)
  • (added) llvm/test/Transforms/InstCombine/ucmp.ll (+156)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 34b0f8b860497..cb0351259a1f9 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3926,6 +3926,92 @@ foldICmpUSubSatOrUAddSatWithConstant(ICmpInst::Predicate Pred,
       ConstantInt::get(Op1->getType(), EquivInt));
 }
 
+static Instruction *
+foldICmpOfCmpIntrinsicWithConstant(ICmpInst::Predicate Pred, IntrinsicInst *I,
+                                   const APInt &C,
+                                   InstCombiner::BuilderTy &Builder) {
+  Intrinsic::ID IID = I->getIntrinsicID();
+  Value *LHS = I->getOperand(0);
+  Value *RHS = I->getOperand(1);
+
+  switch (Pred) {
+  case ICmpInst::ICMP_EQ:
+    if (C.isZero())
+      return new ICmpInst(Pred, LHS, RHS);
+    if (C.isOne())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGT
+                                                 : ICmpInst::ICMP_UGT,
+                          LHS, RHS);
+    if (C.isAllOnes())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLT
+                                                 : ICmpInst::ICMP_ULT,
+                          LHS, RHS);
+    break;
+
+  case ICmpInst::ICMP_NE:
+    if (C.isZero())
+      return new ICmpInst(Pred, LHS, RHS);
+    if (C.isOne())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLE
+                                                 : ICmpInst::ICMP_ULE,
+                          LHS, RHS);
+    if (C.isAllOnes())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGE
+                                                 : ICmpInst::ICMP_UGE,
+                          LHS, RHS);
+    break;
+
+  case ICmpInst::ICMP_SGT:
+    if (C.isAllOnes())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGE
+                                                 : ICmpInst::ICMP_UGE,
+                          LHS, RHS);
+    if (C.isZero())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGT
+                                                 : ICmpInst::ICMP_UGT,
+                          LHS, RHS);
+    break;
+
+  case ICmpInst::ICMP_SGE:
+    if (C.isZero())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGE
+                                                 : ICmpInst::ICMP_UGE,
+                          LHS, RHS);
+    if (C.isOne())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SGT
+                                                 : ICmpInst::ICMP_UGT,
+                          LHS, RHS);
+    break;
+
+  case ICmpInst::ICMP_SLT:
+    if (C.isZero())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLT
+                                                 : ICmpInst::ICMP_ULT,
+                          LHS, RHS);
+    if (C.isOne())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLE
+                                                 : ICmpInst::ICMP_ULE,
+                          LHS, RHS);
+    break;
+
+  case llvm::ICmpInst::ICMP_SLE:
+    if (C.isZero())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLE
+                                                 : ICmpInst::ICMP_ULE,
+                          LHS, RHS);
+    if (C.isAllOnes())
+      return new ICmpInst(IID == Intrinsic::scmp ? ICmpInst::ICMP_SLT
+                                                 : ICmpInst::ICMP_ULT,
+                          LHS, RHS);
+    break;
+
+  default:
+    return nullptr;
+  }
+
+  return nullptr;
+}
+
 /// Fold an icmp with LLVM intrinsic and constant operand: icmp Pred II, C.
 Instruction *InstCombinerImpl::foldICmpIntrinsicWithConstant(ICmpInst &Cmp,
                                                              IntrinsicInst *II,
@@ -3947,6 +4033,11 @@ Instruction *InstCombinerImpl::foldICmpIntrinsicWithConstant(ICmpInst &Cmp,
     if (Instruction *R = foldCtpopPow2Test(Cmp, II, C, Builder, Q))
       return R;
   } break;
+  case Intrinsic::scmp:
+  case Intrinsic::ucmp:
+    if (auto *Folded = foldICmpOfCmpIntrinsicWithConstant(Pred, II, C, Builder))
+      return Folded;
+    break;
   }
 
   if (Cmp.isEquality())
diff --git a/llvm/test/Transforms/InstCombine/scmp.ll b/llvm/test/Transforms/InstCombine/scmp.ll
new file mode 100644
index 0000000000000..4f903a79afd5d
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/scmp.ll
@@ -0,0 +1,156 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @scmp_eq_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_eq_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_ne_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_ne_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_eq_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_eq_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @scmp_ne_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_ne_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @scmp_eq_negative_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_eq_negative_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @scmp_ne_negative_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_ne_negative_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @scmp_sgt_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sgt_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sgt i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_sgt_neg_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sgt_neg_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sgt i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @scmp_sge_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sge_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sge i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_sge_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sge_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sge i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @scmp_slt_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_slt_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp slt i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_slt_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_slt_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp slt i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @scmp_sle_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sle_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp sle i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sle i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @scmp_sle_neg_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @scmp_sle_neg_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp slt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.scmp(i32 %x, i32 %y)
+  %2 = icmp sle i8 %1, -1
+  ret i1 %2
+}
diff --git a/llvm/test/Transforms/InstCombine/ucmp.ll b/llvm/test/Transforms/InstCombine/ucmp.ll
new file mode 100644
index 0000000000000..9ab67560c9117
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/ucmp.ll
@@ -0,0 +1,156 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @ucmp_eq_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_eq_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_ne_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ne_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ne i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_eq_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_eq_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @ucmp_ne_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ne_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @ucmp_eq_negative_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_eq_negative_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp eq i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @ucmp_ne_negative_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_ne_negative_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp ne i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @ucmp_sgt_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sgt_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sgt i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_sgt_neg_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sgt_neg_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sgt i8 %1, -1
+  ret i1 %2
+}
+
+define i1 @ucmp_sge_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sge_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp uge i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sge i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_sge_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sge_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ugt i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sge i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @ucmp_slt_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_slt_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp slt i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_slt_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_slt_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp slt i8 %1, 1
+  ret i1 %2
+}
+
+define i1 @ucmp_sle_0(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sle_0(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ule i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sle i8 %1, 0
+  ret i1 %2
+}
+
+define i1 @ucmp_sle_neg_1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i1 @ucmp_sle_neg_1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[TMP2:%.*]] = icmp ult i32 [[X]], [[Y]]
+; CHECK-NEXT:    ret i1 [[TMP2]]
+;
+  %1 = call i8 @llvm.ucmp(i32 %x, i32 %y)
+  %2 = icmp sle i8 %1, -1
+  ret i1 %2
+}

Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank you!

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dtcxzyw dtcxzyw merged commit 905e4ec into llvm:main Jun 22, 2024
7 checks passed
AlexisPerry pushed a commit to llvm-project-tlp/llvm-project that referenced this pull request Jul 9, 2024
llvm#96118)

This patch handles various cases where an operation of the kind `icmp
(ucmp/scmp x, y), constant` folds to `icmp x, y`. Another patch with
cases where this operation folds to a constant (i.e. dumb cases like
`icmp eq (cmp x, y), 4` should be published in a couple of days.

I wasn't sure what negative tests should be added here, if any are
necessary at all. I'd love to hear your suggestions.

Proofs (ucmp): https://alive2.llvm.org/ce/z/qQ7ihz
Proofs (scmp): https://alive2.llvm.org/ce/z/cipKEn

---------

Co-authored-by: Nikita Popov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants