-
Notifications
You must be signed in to change notification settings - Fork 10.8k
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] fold (icmp eq/ne (or disjoint x, C0), C1)
-> (icmp eq/ne x, C0^C1)
#87734
Conversation
(icmp eq/ne (or disjoint x, C0), C1)
-> (icmp eq/ne x, C0^C1)
@llvm/pr-subscribers-llvm-transforms Author: None (goldsteinn) Changes
Proof: https://alive2.llvm.org/ce/z/m3xoo_ Full diff: https://github.com/llvm/llvm-project/pull/87734.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index db302d7e526844..03a6e7a555c3f7 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -23,6 +23,7 @@
#include "llvm/Analysis/VectorUtils.h"
#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/PatternMatch.h"
#include "llvm/Support/KnownBits.h"
@@ -2049,6 +2050,16 @@ Instruction *InstCombinerImpl::foldICmpOrConstant(ICmpInst &Cmp,
}
Value *OrOp0 = Or->getOperand(0), *OrOp1 = Or->getOperand(1);
+
+ // (icmp eq/ne (or disjoint x, C0), C1)
+ // -> (icmp eq/ne x, C0^C1)
+ if (Cmp.isEquality() && match(OrOp1, m_ImmConstant()) &&
+ cast<PossiblyDisjointInst>(Or)->isDisjoint()) {
+ Constant *NewC = ConstantExpr::getXor(
+ cast<Constant>(OrOp1), ConstantInt::get(OrOp1->getType(), C));
+ return new ICmpInst(Pred, OrOp0, NewC);
+ }
+
const APInt *MaskC;
if (match(OrOp1, m_APInt(MaskC)) && Cmp.isEquality()) {
if (*MaskC == C && (C + 1).isPowerOf2()) {
diff --git a/llvm/test/Transforms/InstCombine/icmp-or.ll b/llvm/test/Transforms/InstCombine/icmp-or.ll
index 922845c1e7e2d8..65d90104cfeeee 100644
--- a/llvm/test/Transforms/InstCombine/icmp-or.ll
+++ b/llvm/test/Transforms/InstCombine/icmp-or.ll
@@ -951,3 +951,49 @@ define i1 @icmp_or_xor_with_sub_3_6(i64 %x1, i64 %y1, i64 %x2, i64 %y2, i64 %x3,
%cmp = icmp eq i64 %or1, 0
ret i1 %cmp
}
+
+
+define i1 @or_disjoint_with_constants(i8 %x) {
+; CHECK-LABEL: @or_disjoint_with_constants(
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1:%.*]], 18
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %or = or disjoint i8 %x, 1
+ %cmp = icmp eq i8 %or, 19
+ ret i1 %cmp
+}
+
+
+define i1 @or_disjoint_with_constants2(i8 %x) {
+; CHECK-LABEL: @or_disjoint_with_constants2(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ne i8 [[TMP1:%.*]], 66
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %or = or disjoint i8 %x, 5
+ %cmp = icmp ne i8 %or, 71
+ ret i1 %cmp
+}
+
+
+define i1 @or_disjoint_with_constants_fail_missing_const1(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_disjoint_with_constants_fail_missing_const1(
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], 19
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %or = or disjoint i8 %x, %y
+ %cmp = icmp eq i8 %or, 19
+ ret i1 %cmp
+}
+
+define i1 @or_disjoint_with_constants_fail_missing_const2(i8 %x, i8 %y) {
+; CHECK-LABEL: @or_disjoint_with_constants_fail_missing_const2(
+; CHECK-NEXT: [[OR:%.*]] = or disjoint i8 [[X:%.*]], 19
+; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[OR]], [[Y:%.*]]
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %or = or disjoint i8 %x, 19
+ %cmp = icmp eq i8 %or, %y
+ ret i1 %cmp
+}
+
|
@@ -2049,6 +2050,16 @@ Instruction *InstCombinerImpl::foldICmpOrConstant(ICmpInst &Cmp, | |||
} | |||
|
|||
Value *OrOp0 = Or->getOperand(0), *OrOp1 = Or->getOperand(1); | |||
|
|||
// (icmp eq/ne (or disjoint x, C0), C1) |
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.
I am not sure whether we should put the logic in InstCombinerImpl::foldICmpBinOpEqualityWithConstant
or not.
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.
We have some other equality folds here, I think we should move them all when/if we move them.
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.
We can't move w.o a non-trivial refactor. Otherwise we hit the X | C == C1
-> X & ~C == C1 ^ C0
fold first.
|
||
define i1 @or_disjoint_with_constants(i8 %x) { | ||
; CHECK-LABEL: @or_disjoint_with_constants( | ||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i8 [[TMP1:%.*]], 18 |
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.
I don't know if this is equivalent to
and tmp, -2
this clears the last bit only
which means 18 and 19 will both result in icmp eq i8 being true.
But when the and is eliminated, that doesn't work
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.
The previous fold covered more cases than where necessary. the disjoint implies that x != 19 (otherwise x | 1 wouldn't be disjoint).
Given how the test cases show variables and not just constants, can this fold apply to variables too? |
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.
If we phrase (or disjoint x, C0) == C1
as x + C0 == C1
, this fold is just like x + C0 == C1
-> X == C1 - C0
: https://alive2.llvm.org/ce/z/aRk27g
Or we should put it in
case Instruction::Add: { |
I don't think the fold is profitable if we can't constant fold the |
I don't think so for two reasons.
|
1156a06
to
6b32f25
Compare
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
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
if (Cmp.isEquality() && match(OrOp1, m_ImmConstant()) && | ||
cast<PossiblyDisjointInst>(Or)->isDisjoint()) { | ||
Constant *NewC = ConstantExpr::getXor( | ||
cast<Constant>(OrOp1), ConstantInt::get(OrOp1->getType(), C)); |
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.
Use IRBuilder for this please, to save me the trouble of replacing it later.
6b32f25
to
4cb341d
Compare
(icmp eq/ne (or disjoint x, C0), C1)
; NFC(icmp eq/ne (or disjoint x, C0), C1)
->(icmp eq/ne x, C0^C1)
Proof: https://alive2.llvm.org/ce/z/m3xoo_