-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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] Folding (icmp eq/ne (and X, -P2), INT_MIN)
#110880
[InstCombine] Folding (icmp eq/ne (and X, -P2), INT_MIN)
#110880
Conversation
Folds to `(icmp slt/sge X, (INT_MIN + P2))` Proofs: https://alive2.llvm.org/ce/z/vpNFY5
(icmp eq/ne (and X, -P2), INT_MIN)
@llvm/pr-subscribers-llvm-transforms Author: None (goldsteinn) Changes
Folds to Proofs: https://alive2.llvm.org/ce/z/vpNFY5 Full diff: https://github.com/llvm/llvm-project/pull/110880.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index b0771ffcc38a83..5e1d9a1c52b2f2 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -5015,6 +5015,22 @@ Instruction *InstCombinerImpl::foldICmpBinOp(ICmpInst &I,
}
}
+ // (icmp eq/ne (X, -P2), INT_MIN)
+ // -> (icmp slt/sge X, INT_MIN + P2)
+ if (ICmpInst::isEquality(Pred) && BO0 &&
+ match(I.getOperand(1), m_SignMask())) {
+ Value *X;
+ if (match(BO0, m_And(m_Value(X), m_CheckedInt([](const APInt &C) {
+ return C.isZero() || C.isNegatedPowerOf2();
+ })))) {
+ // Will Constant fold.
+ Value *NewC = Builder.CreateSub(I.getOperand(1), BO0->getOperand(1));
+ return new ICmpInst(Pred == ICmpInst::ICMP_EQ ? ICmpInst::ICMP_SLT
+ : ICmpInst::ICMP_SGE,
+ X, NewC);
+ }
+ }
+
{
// Similar to above: an unsigned overflow comparison may use offset + mask:
// ((Op1 + C) & C) u< Op1 --> Op1 != 0
diff --git a/llvm/test/Transforms/InstCombine/icmp-signmask.ll b/llvm/test/Transforms/InstCombine/icmp-signmask.ll
new file mode 100644
index 00000000000000..5424f7d7e8021f
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/icmp-signmask.ll
@@ -0,0 +1,54 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define i1 @cmp_x_and_negp2_with_eq(i8 %x) {
+; CHECK-LABEL: @cmp_x_and_negp2_with_eq(
+; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X:%.*]], -126
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %andx = and i8 %x, -2
+ %r = icmp eq i8 %andx, 128
+ ret i1 %r
+}
+
+define i1 @cmp_x_and_negp2_with_eq_fail_not_signmask(i8 %x) {
+; CHECK-LABEL: @cmp_x_and_negp2_with_eq_fail_not_signmask(
+; CHECK-NEXT: [[ANDX:%.*]] = and i8 [[X:%.*]], -2
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[ANDX]], -124
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %andx = and i8 %x, -2
+ %r = icmp eq i8 %andx, 132
+ ret i1 %r
+}
+
+define <2 x i1> @cmp_x_and_negp2_with_ne(<2 x i8> %x) {
+; CHECK-LABEL: @cmp_x_and_negp2_with_ne(
+; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[X:%.*]], <i8 -121, i8 -113>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %andx = and <2 x i8> %x, <i8 -8, i8 -16>
+ %r = icmp ne <2 x i8> %andx, <i8 128, i8 128>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @cmp_x_and_negp2_with_ne_or_z(<2 x i8> %x) {
+; CHECK-LABEL: @cmp_x_and_negp2_with_ne_or_z(
+; CHECK-NEXT: [[R:%.*]] = icmp sge <2 x i8> [[X:%.*]], <i8 -128, i8 -112>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %andx = and <2 x i8> %x, <i8 0, i8 -16>
+ %r = icmp ne <2 x i8> %andx, <i8 128, i8 128>
+ ret <2 x i1> %r
+}
+
+define <2 x i1> @cmp_x_and_negp2_with_ne_fail_not_p2(<2 x i8> %x) {
+; CHECK-LABEL: @cmp_x_and_negp2_with_ne_fail_not_p2(
+; CHECK-NEXT: [[ANDX:%.*]] = and <2 x i8> [[X:%.*]], <i8 -8, i8 -15>
+; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[ANDX]], <i8 -128, i8 -128>
+; CHECK-NEXT: ret <2 x i1> [[R]]
+;
+ %andx = and <2 x i8> %x, <i8 -8, i8 -15>
+ %r = icmp ne <2 x i8> %andx, <i8 128, i8 128>
+ ret <2 x i1> %r
+}
|
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.
LG
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.
LG
// -> (icmp slt/sge X, INT_MIN + P2) | ||
if (ICmpInst::isEquality(Pred) && BO0 && | ||
match(I.getOperand(1), m_SignMask())) { | ||
Value *X; |
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.
There's already a Value *X
declaration above, so you can drop this one and merge both ifs.
Folds to `(icmp slt/sge X, (INT_MIN + P2))` Proofs: https://alive2.llvm.org/ce/z/vpNFY5 Closes llvm#110880
Looks like this breaks msan And I mean msan itself, not the code. |
Hmm? As in MSAN no longer works correctly when compiled with this PR? |
Yes, I bisected locally.. |
Okay, might just be this PR is buggy and causes miscompiles, although its pretty simple and I don't see it. |
This is a problem with MSan handling of signed comparison - it is not entirely correct as a compromise for performance and code size. Do you mind reverting the change while we figure out how to fix MSan? |
I can confirm that -msan-handle-icmp-exact=1 avoids this issue, and increases .text size of the clang binary by 2.9%. |
#111212 to fix MSan. |
…lvm#111236) Reverts llvm#110880 because of exposed issue is Msan instrumentation llvm#111212. This reverts commit a646436.
(icmp eq/ne (and X, -P2), INT_MIN)
; NFC(icmp eq/ne (and X, -P2), INT_MIN)
Folds to
(icmp slt/sge X, (INT_MIN + P2))
Proofs: https://alive2.llvm.org/ce/z/vpNFY5