[llvm] 0f7d148 - [InstCombine] Add shared helper for logical and bitwise and/or (NFC)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 17 05:25:53 PDT 2024
Author: Nikita Popov
Date: 2024-10-17T14:25:44+02:00
New Revision: 0f7d148db45e782373c5d6a0faf745986753982b
URL: https://github.com/llvm/llvm-project/commit/0f7d148db45e782373c5d6a0faf745986753982b
DIFF: https://github.com/llvm/llvm-project/commit/0f7d148db45e782373c5d6a0faf745986753982b.diff
LOG: [InstCombine] Add shared helper for logical and bitwise and/or (NFC)
Add a helper for shared folds between logical and bitwise and/or
and move the and/or of icmp and fcmp folds in there. This makes
it easier to extend to more folds.
A possible extension would be to base the current and/or of icmp
reassociation logic on this helper, so that it for example also
applies to fcmp.
Added:
Modified:
llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
llvm/lib/Transforms/InstCombine/InstCombineInternal.h
llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index c8407e8ba5aba8..8112255a0b6c45 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -2722,13 +2722,15 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
return BinaryOperator::CreateAnd(Builder.CreateNot(A), B);
}
+ if (Value *Res =
+ foldBooleanAndOr(Op0, Op1, I, /*IsAnd=*/true, /*IsLogical=*/false))
+ return replaceInstUsesWith(I, Res);
+
{
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
- if (LHS && RHS)
- if (Value *Res = foldAndOrOfICmps(LHS, RHS, I, /* IsAnd */ true))
- return replaceInstUsesWith(I, Res);
+ // TODO: Base this on foldBooleanAndOr instead?
// TODO: Make this recursive; it's a little tricky because an arbitrary
// number of 'and' instructions might have to be created.
if (LHS && match(Op1, m_OneUse(m_LogicalAnd(m_Value(X), m_Value(Y))))) {
@@ -2767,11 +2769,6 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) {
}
}
- if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
- if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
- if (Value *Res = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ true))
- return replaceInstUsesWith(I, Res);
-
if (Instruction *FoldedFCmps = reassociateFCmps(I, Builder))
return FoldedFCmps;
@@ -3523,6 +3520,27 @@ Value *InstCombinerImpl::foldAndOrOfICmps(ICmpInst *LHS, ICmpInst *RHS,
return foldAndOrOfICmpsUsingRanges(LHS, RHS, IsAnd);
}
+/// If IsLogical is true, then the and/or is in select form and the transform
+/// must be poison-safe.
+Value *InstCombinerImpl::foldBooleanAndOr(Value *LHS, Value *RHS,
+ Instruction &I, bool IsAnd,
+ bool IsLogical) {
+ if (!LHS->getType()->isIntOrIntVectorTy(1))
+ return nullptr;
+
+ if (auto *LHSCmp = dyn_cast<ICmpInst>(LHS))
+ if (auto *RHSCmp = dyn_cast<ICmpInst>(RHS))
+ if (Value *Res = foldAndOrOfICmps(LHSCmp, RHSCmp, I, IsAnd, IsLogical))
+ return Res;
+
+ if (auto *LHSCmp = dyn_cast<FCmpInst>(LHS))
+ if (auto *RHSCmp = dyn_cast<FCmpInst>(RHS))
+ if (Value *Res = foldLogicOfFCmps(LHSCmp, RHSCmp, IsAnd, IsLogical))
+ return Res;
+
+ return nullptr;
+}
+
static Value *foldOrOfInversions(BinaryOperator &I,
InstCombiner::BuilderTy &Builder) {
assert(I.getOpcode() == Instruction::Or &&
@@ -3804,13 +3822,15 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
if (SwappedForXor)
std::swap(Op0, Op1);
+ if (Value *Res =
+ foldBooleanAndOr(Op0, Op1, I, /*IsAnd=*/false, /*IsLogical=*/false))
+ return replaceInstUsesWith(I, Res);
+
{
ICmpInst *LHS = dyn_cast<ICmpInst>(Op0);
ICmpInst *RHS = dyn_cast<ICmpInst>(Op1);
- if (LHS && RHS)
- if (Value *Res = foldAndOrOfICmps(LHS, RHS, I, /* IsAnd */ false))
- return replaceInstUsesWith(I, Res);
+ // TODO: Base this on foldBooleanAndOr instead?
// TODO: Make this recursive; it's a little tricky because an arbitrary
// number of 'or' instructions might have to be created.
Value *X, *Y;
@@ -3850,11 +3870,6 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
}
}
- if (FCmpInst *LHS = dyn_cast<FCmpInst>(I.getOperand(0)))
- if (FCmpInst *RHS = dyn_cast<FCmpInst>(I.getOperand(1)))
- if (Value *Res = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ false))
- return replaceInstUsesWith(I, Res);
-
if (Instruction *FoldedFCmps = reassociateFCmps(I, Builder))
return FoldedFCmps;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 7c6f42de77fc71..7a060cdab2d37d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -425,6 +425,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
Instruction *foldLogicOfIsFPClass(BinaryOperator &Operator, Value *LHS,
Value *RHS);
+ Value *foldBooleanAndOr(Value *LHS, Value *RHS, Instruction &I, bool IsAnd,
+ bool IsLogical);
+
Instruction *
canonicalizeConditionalNegationViaMathToSelect(BinaryOperator &i);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index ed44f0596f3272..c5f39a4c381ed1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -3143,12 +3143,6 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
SI, Builder.CreateLogicalOr(A, Builder.CreateOr(B, FalseVal)));
}
- if (auto *LHS = dyn_cast<FCmpInst>(CondVal))
- if (auto *RHS = dyn_cast<FCmpInst>(FalseVal))
- if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ false,
- /*IsSelectLogical*/ true))
- return replaceInstUsesWith(SI, V);
-
// (A && B) || (C && B) --> (A || C) && B
if (match(CondVal, m_LogicalAnd(m_Value(A), m_Value(B))) &&
match(FalseVal, m_LogicalAnd(m_Value(C), m_Value(D))) &&
@@ -3191,12 +3185,6 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
SI, Builder.CreateLogicalAnd(A, Builder.CreateAnd(B, TrueVal)));
}
- if (auto *LHS = dyn_cast<FCmpInst>(CondVal))
- if (auto *RHS = dyn_cast<FCmpInst>(TrueVal))
- if (Value *V = foldLogicOfFCmps(LHS, RHS, /*IsAnd*/ true,
- /*IsSelectLogical*/ true))
- return replaceInstUsesWith(SI, V);
-
// (A || B) && (C || B) --> (A && C) || B
if (match(CondVal, m_LogicalOr(m_Value(A), m_Value(B))) &&
match(TrueVal, m_LogicalOr(m_Value(C), m_Value(D))) &&
@@ -3305,11 +3293,9 @@ Instruction *InstCombinerImpl::foldSelectOfBools(SelectInst &SI) {
return replaceInstUsesWith(SI, Op1);
}
- if (auto *ICmp0 = dyn_cast<ICmpInst>(CondVal))
- if (auto *ICmp1 = dyn_cast<ICmpInst>(Op1))
- if (auto *V = foldAndOrOfICmps(ICmp0, ICmp1, SI, IsAnd,
- /* IsLogical */ true))
- return replaceInstUsesWith(SI, V);
+ if (auto *V = foldBooleanAndOr(CondVal, Op1, SI, IsAnd,
+ /*IsLogical=*/true))
+ return replaceInstUsesWith(SI, V);
}
// select (a || b), c, false -> select a, c, false
More information about the llvm-commits
mailing list