Skip to content
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

[ValueTracking] Infer relationship for the select with ICmp #66668

Merged
merged 3 commits into from
Aug 6, 2024

Conversation

vfdff
Copy link
Contributor

@vfdff vfdff commented Sep 18, 2023

x -nsw y < C is false when x > y and C <= 0
Alive2 proof for sgt, sge, ugt, uge : https://alive2.llvm.org/ce/z/tupvfi

Fixes #54735

@llvmbot
Copy link
Member

llvmbot commented Sep 18, 2023

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-analysis

Changes

x-y+1 is positive when x > y, so abs (x-y+1) --> x-y+1

Fixes #54735


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

2 Files Affected:

  • (modified) llvm/lib/Analysis/InstructionSimplify.cpp (+25)
  • (added) llvm/test/Transforms/InstSimplify/select-icmp.ll (+33)
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 5fe0d53c313d40e..ecb261716cb71fb 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4547,6 +4547,20 @@ static Value *simplifySelectWithICmpEq(Value *CmpLHS, Value *CmpRHS,
   return nullptr;
 }
 
+/// Return nullptr if the comparison relationship of X and Y can't be inferred.
+static Value *simplifySelectWithICmpKnownRelation(ICmpInst::Predicate Pred,
+                                                  Value *CmpLHS, Value *CmpRHS,
+                                                  Value *TrueVal,
+                                                  Value *FalseVal,
+                                                  const SimplifyQuery &Q) {
+  if (std::optional<bool> Flag =
+          isImpliedByDomCondition(Pred, CmpLHS, CmpRHS, Q.CxtI, Q.DL)) {
+    if (Flag)
+      return *Flag ? TrueVal : FalseVal;
+  }
+  return nullptr;
+}
+
 /// Try to simplify a select instruction when its condition operand is an
 /// integer comparison.
 static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
@@ -4669,6 +4683,17 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
     }
   }
 
+  if (Pred == ICmpInst::ICMP_SLT) {
+    Value *X;
+    Value *Y;
+    const APInt *C;
+    // x-y+1 is positive when x >= y or non-positive when x < y
+    if (match(CmpLHS, m_NSWSub(m_Value(X), m_Value(Y))) &&
+        match(CmpRHS, m_AllOnes()))
+      return simplifySelectWithICmpKnownRelation(ICmpInst::ICMP_SLT, X, Y,
+                                                 TrueVal, FalseVal, Q);
+  }
+
   return nullptr;
 }
 
diff --git a/llvm/test/Transforms/InstSimplify/select-icmp.ll b/llvm/test/Transforms/InstSimplify/select-icmp.ll
new file mode 100755
index 000000000000000..1271941565d9dc3
--- /dev/null
+++ b/llvm/test/Transforms/InstSimplify/select-icmp.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
+
+; https://alive2.llvm.org/ce/z/zKX64J
+define i32 @pr54735(i32 noundef %x, i32 noundef %y) {
+; CHECK-LABEL: @pr54735(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_END:%.*]]
+; CHECK:       cond.true:
+; CHECK-NEXT:    [[SUB:%.*]] = sub nsw i32 [[X]], [[Y]]
+; CHECK-NEXT:    [[ADD:%.*]] = add nsw i32 [[SUB]], 1
+; CHECK-NEXT:    br label [[COND_END]]
+; CHECK:       cond.end:
+; CHECK-NEXT:    [[COND:%.*]] = phi i32 [ [[ADD]], [[COND_TRUE]] ], [ 0, [[ENTRY:%.*]] ]
+; CHECK-NEXT:    ret i32 [[COND]]
+;
+entry:
+  %cmp = icmp sgt i32 %x, %y
+  br i1 %cmp, label %cond.true, label %cond.end
+
+cond.true:                                        ; preds = %entry
+  %sub = sub nsw i32 %x, %y
+  %add = add nsw i32 %sub, 1
+  %neg = xor i32 %sub, -1                         ; sub nsw i32 0, %add
+  %abscond = icmp slt i32 %sub, -1
+  %abs = select i1 %abscond, i32 %neg, i32 %add
+  br label %cond.end
+
+cond.end:                                         ; preds = %entry, %cond.true
+  %cond = phi i32 [ %abs, %cond.true ], [ 0, %entry ]
+  ret i32 %cond
+}

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.

I believe this needs to be handled in isImpliedCondition. There is already existing code that will simplify implications from dominating conditions.

Though really, this seems like something that ConstraintElimination should handle, not InstSimplify.

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.

Please add an alive2 proof to the patch description. This should also needs additional tests (preferably more minimal than the example you added), e.g. that this does not fold without nsw, wrong constant, etc.

llvm/lib/Analysis/ValueTracking.cpp Outdated Show resolved Hide resolved
@vfdff
Copy link
Contributor Author

vfdff commented Sep 21, 2023

Please add an alive2 proof to the patch description. This should also needs additional tests (preferably more minimal than the example you added), e.g. that this does not fold without nsw, wrong constant, etc.

Thanks, Added alive2 proof link and 2 extra negative test cases.

@vfdff
Copy link
Contributor Author

vfdff commented Sep 28, 2023

ping ?

@vfdff vfdff requested review from nikic and goldsteinn October 7, 2023 16:53
@vfdff vfdff requested a review from dtcxzyw October 15, 2023 09:04
llvm/lib/Analysis/ValueTracking.cpp Outdated Show resolved Hide resolved
@github-actions
Copy link

github-actions bot commented Oct 17, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@vfdff
Copy link
Contributor Author

vfdff commented Nov 4, 2023

revert the change for x -nsw y <= -1 <==> x < y because sle -1 will get canonicalized to slt 0, so should consider other way to address that.

@vfdff vfdff requested a review from dtcxzyw November 7, 2023 03:19
@vfdff
Copy link
Contributor Author

vfdff commented Nov 22, 2023

ping ?

@@ -8294,6 +8294,17 @@ static std::optional<bool> isImpliedCondICmps(const ICmpInst *LHS,
if (areMatchingOperands(L0, L1, R0, R1, AreSwappedOps))
return isImpliedCondMatchingOperands(LPred, RPred, AreSwappedOps);

if (LPred == ICmpInst::ICMP_SGT) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should also handle the less-than variant no?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hi @goldsteinn
I reverted the change for less-than because the commit #66668 (review), so I think it may be addressed with some other method.
If you don't object, I think it is fine to keep this PR to fix the issue in the comment link.

@vfdff
Copy link
Contributor Author

vfdff commented Mar 9, 2024

If there's no objection, I'll take a try for this commit in the next week?

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Mar 9, 2024
@dtcxzyw
Copy link
Member

dtcxzyw commented Mar 9, 2024

Ping @nikic @goldsteinn

@vfdff vfdff force-pushed the PR54735 branch 2 times, most recently from 5aa207b to 8a732dc Compare June 1, 2024 09:42
@dtcxzyw dtcxzyw requested a review from goldsteinn June 1, 2024 14:17
@preames preames removed their request for review June 4, 2024 15:49
@goldsteinn
Copy link
Contributor

LGTM. Please wait for an additional approval

@vfdff
Copy link
Contributor Author

vfdff commented Jun 7, 2024

LGTM. Please wait for an additional approval
Thank very much for your reviewing

@vfdff
Copy link
Contributor Author

vfdff commented Jun 20, 2024

hi @nikic , would you give me some advice? thanks

@vfdff
Copy link
Contributor Author

vfdff commented Jul 20, 2024

This PR has no update for a long time, so try rebasing to top upstream to see if there's any conflict.

@vfdff
Copy link
Contributor Author

vfdff commented Aug 5, 2024

ping
can I try to land this PR as there is no new comment for a long time ?

@goldsteinn
Copy link
Contributor

LGTM, should be fine to push.

@vfdff
Copy link
Contributor Author

vfdff commented Aug 6, 2024

Thanks very much

vfdff added 3 commits August 6, 2024 10:30
x-y+1 is positive when x > y, so abs (x-y+1) --> x-y+1

Fixes llvm#54735
x -nsw y < -C is false when x > y and C >= 0
Alive2 proof for sgt, sge : https://alive2.llvm.org/ce/z/tupvfi
Note: It only really makes sense in the context of signed comparison for
      "X - Y must be positive if X >= Y and no overflow".

Fixes llvm#54735
@vfdff vfdff merged commit 2bd568f into llvm:main Aug 6, 2024
3 of 7 checks passed
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.

[optimization] gcc generate better code than clang base on value range propagation
5 participants