-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[InstCombine] Handle ICMP_EQ when flooring by constant two
#73706
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
[InstCombine] Handle ICMP_EQ when flooring by constant two
#73706
Conversation
|
@llvm/pr-subscribers-llvm-transforms Author: Antonio Frighetto (antoniofrighetto) ChangesSupport Shouldn't be needed to check directly for constant Fixes: #73622. Full diff: https://github.com/llvm/llvm-project/pull/73706.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 24a166906f1f46d..856fc388f855e7e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1234,14 +1234,21 @@ static Instruction *foldAddToAshr(BinaryOperator &Add) {
return nullptr;
// Rounding is done by adding -1 if the dividend (X) is negative and has any
- // low bits set. The canonical pattern for that is an "ugt" compare with SMIN:
- // sext (icmp ugt (X & (DivC - 1)), SMIN)
- const APInt *MaskC;
+ // low bits set. It recognizes two canonical patterns:
+ // 1. For an 'ugt' cmp with the signed minimum value (SMIN), the
+ // pattern is: sext (icmp ugt (X & (DivC - 1)), SMIN).
+ // 2. For an 'eq' cmp, the pattern is: sext (icmp eq (SMIN + 1), SMIN + 1).
+ // Note that, by the time we end up here, if possible, ugt has been
+ // canonicalized into eq.
+ const APInt *MaskC, *MaskCCmp;
ICmpInst::Predicate Pred;
if (!match(Add.getOperand(1),
m_SExt(m_ICmp(Pred, m_And(m_Specific(X), m_APInt(MaskC)),
- m_SignMask()))) ||
- Pred != ICmpInst::ICMP_UGT)
+ m_APInt(MaskCCmp)))))
+ return nullptr;
+
+ if ((Pred != ICmpInst::ICMP_UGT || !MaskCCmp->isSignMask()) &&
+ (Pred != ICmpInst::ICMP_EQ || *MaskCCmp != *MaskC))
return nullptr;
APInt SMin = APInt::getSignedMinValue(Add.getType()->getScalarSizeInBits());
diff --git a/llvm/test/Transforms/InstCombine/add.ll b/llvm/test/Transforms/InstCombine/add.ll
index c35d2af42a4beae..eb986137c2cf9a9 100644
--- a/llvm/test/Transforms/InstCombine/add.ll
+++ b/llvm/test/Transforms/InstCombine/add.ll
@@ -2700,6 +2700,19 @@ define i32 @floor_sdiv(i32 %x) {
ret i32 %r
}
+define i8 @floor_sdiv_by_2(i8 %x) {
+; CHECK-LABEL: @floor_sdiv_by_2(
+; CHECK-NEXT: [[RV:%.*]] = ashr i8 [[X:%.*]], 1
+; CHECK-NEXT: ret i8 [[RV]]
+;
+ %div = sdiv i8 %x, 2
+ %and = and i8 %x, -127
+ %icmp = icmp eq i8 %and, -127
+ %sext = sext i1 %icmp to i8
+ %rv = add nsw i8 %div, %sext
+ ret i8 %rv
+}
+
; vectors work too and commute is handled by complexity-based canonicalization
define <2 x i32> @floor_sdiv_vec_commute(<2 x i32> %x) {
|
d0c7665 to
f34cb2d
Compare
|
Can you please add an alive2 proof? |
f34cb2d to
840b2d4
Compare
dtcxzyw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
|
As far as I can tell, your optimization is not limited for DivC == 2, but I don't think it's valid for other cases? I've tried to transfer the generic pre-conditions in this proof, maybe I did something wrong: https://alive2.llvm.org/ce/z/XaWD7N |
|
That was my concern too, but I couldn't find any instance that would violate this, so I believed restricting it to |
840b2d4 to
ad492c0
Compare
|
Can you please also add a negative test with DivC != 2? |
ad492c0 to
63b3b1e
Compare
|
Reviewed tests, thanks. |
63b3b1e to
bd8f0a6
Compare
nikic
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Support `icmp eq` when reducing signed divisions by power of 2 to arithmetic shift right, as `icmp ugt` may have been canonicalized into `icmp eq` by the time additions are folded into `ashr`. Fixes: llvm#73622. Proof: https://alive2.llvm.org/ce/z/8-eUdb.
bd8f0a6 to
7d5f79f
Compare
Support
icmp eqwhen reducing signed divisions by power of two to arithmetic shift right, asicmp ugtmight have been canonicalized intoicmp eqby the time we fold additions intoashr.Shouldn't be needed to check directly for constant
-127, as we already check that*MaskC != (SMin | (*DivC - 1)).Alive2: https://alive2.llvm.org/ce/z/d0q2px
Fixes: #73622.