Skip to content

[ConstraintElim] Teach checkAndReplaceCondition about samesign #128168

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 2 commits into from
Feb 24, 2025

Conversation

citymarina
Copy link
Contributor

@citymarina citymarina commented Feb 21, 2025

samesign upred is equivalent to spred: https://alive2.llvm.org/ce/z/57iaEC

@llvmbot
Copy link
Member

llvmbot commented Feb 21, 2025

@llvm/pr-subscribers-llvm-transforms

Author: Marina Taylor (citymarina)

Changes

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

2 Files Affected:

  • (modified) llvm/lib/Transforms/Scalar/ConstraintElimination.cpp (+8-1)
  • (modified) llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll (+20)
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 6dd26910f6846..9a1a3f3dfeabc 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -1427,7 +1427,7 @@ static std::optional<bool> checkCondition(CmpInst::Predicate Pred, Value *A,
 }
 
 static bool checkAndReplaceCondition(
-    CmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut,
+    ICmpInst *Cmp, ConstraintInfo &Info, unsigned NumIn, unsigned NumOut,
     Instruction *ContextInst, Module *ReproducerModule,
     ArrayRef<ReproducerEntry> ReproducerCondStack, DominatorTree &DT,
     SmallVectorImpl<Instruction *> &ToRemove) {
@@ -1460,6 +1460,13 @@ static bool checkAndReplaceCondition(
           checkCondition(Cmp->getPredicate(), Cmp->getOperand(0),
                          Cmp->getOperand(1), Cmp, Info))
     return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
+
+  if (Cmp->hasSameSign())
+    if (auto ImpliedCondition = checkCondition(
+            ICmpInst::getFlippedSignednessPredicate(Cmp->getPredicate()),
+            Cmp->getOperand(0), Cmp->getOperand(1), Cmp, Info))
+      return ReplaceCmpWithConstant(Cmp, *ImpliedCondition);
+
   return false;
 }
 
diff --git a/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll b/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll
index 1b155e050de29..09cbbf1c661c7 100644
--- a/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll
+++ b/llvm/test/Transforms/ConstraintElimination/transfer-samesign-facts.ll
@@ -303,3 +303,23 @@ define i1 @ugt_assumed_positive_values(i8 %a, i8 %b) {
 
   ret i1 %result
 }
+
+define i1 @samesign_flipped_signedness(i8 %a)  {
+; CHECK-LABEL: @samesign_flipped_signedness(
+; CHECK-NEXT:    [[TMP1:%.*]] = icmp ugt i8 [[A:%.*]], 0
+; CHECK-NEXT:    br i1 [[TMP1]], label [[GREATER:%.*]], label [[EXIT:%.*]]
+; CHECK:       greater:
+; CHECK-NEXT:    ret i1 true
+; CHECK:       exit:
+; CHECK-NEXT:    ret i1 false
+;
+  %1 = icmp ugt i8 %a, 0
+  br i1 %1, label %greater, label %exit
+
+greater:
+  %2 = icmp samesign sgt i8 %a, 0
+  ret i1 %2
+
+exit:
+  ret i1 false
+}

@dtcxzyw
Copy link
Member

dtcxzyw commented Feb 21, 2025

I implemented the same feature last year :) 33c92a0
Maybe it caused some regressions in real-world programs.

Compile-time impact: https://llvm-compile-time-tracker.com/compare.php?from=d1a7225076218ce224cd29c74259b715b393dc9d&to=33c92a07b3a831778592b60962cced91d0b07275&stat=instructions:u

@dtcxzyw
Copy link
Member

dtcxzyw commented Feb 21, 2025

Maybe it caused some regressions in real-world programs.

IR diff looks OK.

Copy link
Contributor

@artagnon artagnon left a comment

Choose a reason for hiding this comment

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

Looks reasonable, but I think the test coverage is lacking: how about a dominating samesign condition as well?

@citymarina
Copy link
Contributor Author

Looks reasonable, but I think the test coverage is lacking: how about a dominating samesign condition as well?

Does the added test from #120089 (comment) cover the scenario that you were looking for? If not, could you sketch out for me what you had in mind?

Copy link
Contributor

@artagnon artagnon left a comment

Choose a reason for hiding this comment

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

Almost there.

Comment on lines 336 to 362
%cmp_ult = icmp samesign ult i32 %a, 65
br i1 %cmp_ult, label %for.cond.preheader, label %if.else

for.cond.preheader:
ret i1 false

if.else:
%cmp_ugt = icmp samesign ugt i32 %a, -65
ret i1 %cmp_ugt
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: -65 is interpreted as INT_MAX - 64 unsigned, and this wouldn't have been simplified to false before samesign support. However, the samesign on ult is redundant. Typically, we want two tests: one of the icmps should have samesign, and the other shouldn't.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Putting together the recent comments:

  • Exactly one of the icmps should have samesign
  • samesign only goes with unsigned
  • Want a dominating samesign test

that lead me to write:

define i1 @implied_condition_ugt_sgt(i8 %a, i8 %b)  {
  %cmp_ugt = icmp samesign ugt i8 %a, %b
  br i1 %cmp_ugt, label %greater, label %exit

greater:
  %cmp_sgt = icmp sgt i8 %a, %b
  ret i1 %cmp_sgt

exit:
  ret i1 false
}

but in this code, greater: is already optimized to ret i1 true even without this patch. Have I misunderstood some part?

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, my bad! There are already tests for this. If you could just write one test with %a and %b and another with %a and a constant, that would be good.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does the latest update capture what you had in mind?

@artagnon
Copy link
Contributor

Could you also re-title this PR "[ConstraintElim] Teach checkAndReplaceCondition about samesign", as there are already other patches that teach other parts of ConstraintElim about samesign, and we want to disambiguate.

@citymarina citymarina changed the title [ConstraintElim] Check the other signedness when hasSameSign [ConstraintElim] Teach checkAndReplaceCondition about samesign Feb 21, 2025
Copy link
Contributor

@artagnon artagnon left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

br i1 %cmp_sle, label %less_or_equal, label %exit

less_or_equal:
%cmp_ule = icmp samesign ule i8 %a, 42
Copy link
Contributor

Choose a reason for hiding this comment

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

could you also add a test with samesign that cannot be simplified to also guard the negative case?

And maybe a variant with samesign on the signed known condition to also cover the case where we have samesign but a single predicate?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And maybe a variant with samesign on the signed known condition

Based on comments above, I thought samesign mustn't go on signed predicates?

Copy link
Contributor

Choose a reason for hiding this comment

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

Unless I misunderstood something, @fhahn: samesign is always canonicalized with unsigned predicates, and we generally avoid writing tests with samesign and signed predicates.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep, AFAIK you can have samesign with signed predicates in general, it looks like ConstraintElimination already handles those case (https://llvm.godbolt.org/z/fhs3r5M56), so this may already be covered by tests

Copy link
Contributor

@fhahn fhahn left a comment

Choose a reason for hiding this comment

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

LGTM, thanks!

When landing, could you add a brief description to the commit message, perhaps including a link to an alive2 proof for the motivating example?

@citymarina
Copy link
Contributor Author

Thanks, I've updated the description. If this is good to go, I could use some help to land as I don't yet have write access (I'll probably have enough commits to request it after this).

@fhahn fhahn merged commit 72768d9 into llvm:main Feb 24, 2025
11 checks passed
@citymarina
Copy link
Contributor Author

Thank you!

@citymarina citymarina deleted the ce-ne-zero-3 branch May 12, 2025 16:07
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.

[ConstraintElim] icmp spred x, y implies icmp samesign upred x, y
6 participants