-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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] Simplify select if it combinated and/or/xor #73362
Conversation
@llvm/pr-subscribers-llvm-transforms @llvm/pr-subscribers-llvm-analysis Author: hanbum (ParkHanbum) Changes
certain combinations of bitwise operators can be simplified to returning the value of the True or False clause. Proofs : https://alive2.llvm.org/ce/z/9jidcw Fixed llvm#71792. hello! It's an honor to send a PR to LLVM! I'm sending this to get your opinion on whether it's okay to write a patch this way. Full diff: https://github.com/llvm/llvm-project/pull/73362.diff 1 Files Affected:
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 7ef2ffd23b95e76..a69de0da8b6d046 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4425,6 +4425,48 @@ Value *llvm::simplifyWithOpReplaced(Value *V, Value *Op, Value *RepOp,
RecursionLimit);
}
+/// Try simplifying the selection command when condition, trueValue, and
+/// falseValue are combinations of special bitwise operators.
+static Value *simplifySelectBitTestSpec(Value *TrueVal, Value *FalseVal,
+ Value *X, Value *Y,
+ bool TrueWhenUnset) {
+ // (X & Y) == 0 ? X | Y : X ^ Y --> X ^ Y
+ // (X & Y) == 0 ? X ^ Y : X | Y --> X | Y
+ // (X & Y) == 1 ? X | Y : X ^ Y --> X | Y
+ // (X & Y) == 1 ? X ^ Y : X | Y --> X ^ Y
+ if (match(TrueVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+ match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ } else if (match(FalseVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+ match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ }
+ // (X | Y) == 0 ? X & Y : X ^ Y --> X ^ Y
+ // (X | Y) == 0 ? X ^ Y : X & Y --> X & Y
+ // (X | Y) == 1 ? X & Y : X ^ Y --> X & Y
+ // (X | Y) == 1 ? X ^ Y : X & Y --> X ^ Y
+ if (match(TrueVal, m_And(m_Specific(X), m_Specific(Y))) &&
+ match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ } else if (match(FalseVal, m_And(m_Specific(X), m_Specific(Y))) &&
+ match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ }
+ // (X ^ Y) == 0 ? X | Y : X & Y --> X & Y
+ // (X ^ Y) == 0 ? X & Y : X | Y --> X | Y
+ // (X ^ Y) == 1 ? X | Y : X & Y --> X | Y
+ // (X ^ Y) == 1 ? X & Y : X | Y --> X & Y
+ if (match(TrueVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+ match(FalseVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ } else if (match(FalseVal, m_Or(m_Specific(X), m_Specific(Y))) &&
+ match(TrueVal, m_Xor(m_Specific(X), m_Specific(Y)))) {
+ return TrueWhenUnset ? TrueVal : FalseVal;
+ }
+
+ return nullptr;
+}
+
/// Try to simplify a select instruction when its condition operand is an
/// integer comparison where one operand of the compare is a constant.
static Value *simplifySelectBitTest(Value *TrueVal, Value *FalseVal, Value *X,
@@ -4572,12 +4614,37 @@ static Value *simplifySelectWithICmpCond(Value *CondVal, Value *TrueVal,
unsigned MaxRecurse) {
ICmpInst::Predicate Pred;
Value *CmpLHS, *CmpRHS;
+ const APInt *C;
if (!match(CondVal, m_ICmp(Pred, m_Value(CmpLHS), m_Value(CmpRHS))))
return nullptr;
if (Value *V = simplifyCmpSelOfMaxMin(CmpLHS, CmpRHS, Pred, TrueVal, FalseVal))
return V;
+ if (ICmpInst::isEquality(Pred) && match(CmpRHS, m_APInt(C)) &&
+ (C->isZero() | C->isOne())) {
+ bool which;
+ Value *X, *Y;
+
+ if (Pred == ICmpInst::ICMP_EQ)
+ which = C->isZero() ? false : true;
+ else
+ which = C->isZero() ? true : false;
+
+ if (match(CmpLHS, m_And(m_Value(X), m_Value(Y)))) {
+ if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+ return V;
+ }
+ if (match(CmpLHS, m_Or(m_Value(X), m_Value(Y)))) {
+ if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+ return V;
+ }
+ if (match(CmpLHS, m_Xor(m_Value(X), m_Value(Y)))) {
+ if (Value *V = simplifySelectBitTestSpec(TrueVal, FalseVal, X, Y, which))
+ return V;
+ }
+ }
+
// Canonicalize ne to eq predicate.
if (Pred == ICmpInst::ICMP_NE) {
Pred = ICmpInst::ICMP_EQ;
|
and/or/xor
and/or/xor
02515c5
to
76af103
Compare
76af103
to
c06c901
Compare
44486d2
to
6539259
Compare
6539259
to
bc80240
Compare
I have mistake while resolve conflict. sorry. |
25e67e1
to
f0abaf4
Compare
✅ With the latest revision this PR passed the C/C++ code formatter. |
Just a missing matcher that came up in llvm#73362
Just a missing matcher that came up in llvm#73362
`and/or/xor` operations can each be changed to sum of logical operations including operators other than themselves. `x&y -> (x|y) ^ (x^y)` `x|y -> (x&y) | (x^y)` `x^y -> (x|y) ^ (x&y)` This commit contains to test these cases. Proof: https://alive2.llvm.org/ce/z/WW8iRR
b6c0124
to
0855e56
Compare
LGTM. |
@goldsteinn thanks for review. I wish I could take TODOs. |
You can, I think the way to do this is actually to handle this case in We currently have:
But we could (and should) also have:
Likewise for the
The only case that requires special logic is That case I think you could handle here in a future patch. Let me know if you are going to pursue a patch in Edit: Maybe wait a bit, I looked at this a bit and it creates some bugs related to #87015, |
@dtcxzyw can you provide a second review of this? |
Think its a non-issue actually. @ParkHanbum lmk if you want to make a patch for this. |
0855e56
to
b96149d
Compare
`and/or/xor` operations can each be changed to sum of logical operations including operators other than themselves. `x&y -> (x|y) ^ (x^y)` `x|y -> (x&y) | (x^y)` `x^y -> (x|y) ^ (x&y)` if left of condition of `SelectInst` is `and/or/xor` logical operation and right is equal to `0, -1`, or a `constant`, and if `TrueVal` consist of `and/or/xor` logical operation then we can optimize this case. This patch implements this combination. Proof: https://alive2.llvm.org/ce/z/WW8iRR
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. BTW the current implementation is a bit larger than the first version I approved. I am not sure whether it is an over-generalization. So I will leave the final decision to @goldsteinn and @nikic.
LGTM |
@ParkHanbum do you have commit access or do you need me to merge for you? |
@goldsteinn I don't remember receiving any commit access. can I ask you why you asking that to me because I'm newbie. |
…d simple cases. The original intent of the folds (from llvm#71792) where to handle selects where the condition was a bitwise operator compared with zero. During review of the original PR (llvm#73362), however, we ended up over generalizing at the expense of code complexity, and ironically in a way that didn't actually fix the issue as reported. The goal of this PR is to simplify the code and only handle the compares with zero cases that actually show up in the real world. New code handles three cases: 1) `X & Y == 0` implies `X | Y == X ^ Y` thus: - `X & Y == 0 ? X |/^/+ Y : X |/^/+ Y` -> `X |/^/+ Y` (the false arm) - https://alive2.llvm.org/ce/z/jjcduh 2) `X | Y == 0` implies `X == Y == 0` thus for `Op0` and `Op1` s.t `0 Op0 0 == 0 Op1 0 == 0`: - `X & Y == 0 ? X Op0 Y : X Op1 Y` -> `X Op1 Y` - `X & Y == 0 ? 0 : X Op1 Y` -> `X Op1 Y` - https://alive2.llvm.org/ce/z/RBuFQE 3) `X ^ Y == 0` (`X == Y`) implies `X | Y == X & Y`: - `X ^ Y == 0 ? X | Y : X & Y` -> `X & Y` - `X ^ Y == 0 ? X & Y : X | Y` -> `X | Y` - https://alive2.llvm.org/ce/z/SJskbz
and/or/xor
operations can each be changed to sum of logicaloperations including operators other than themselves.
x&y -> (x|y) ^ (x^y)
x|y -> (x&y) | (x^y)
x^y -> (x|y) ^ (x&y)
if left of condition of
SelectInst
isand/or/xor
logicaloperation and right is equal to
0, -1
, or aconstant
, andif
TrueVal
consist ofand/or/xor
logical operation then wecan optimize this case.
This patch implements this combination.
Proof: https://alive2.llvm.org/ce/z/WW8iRR
Fixed #71792.