aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2023-01-02 21:15:31 +0300
committerRoman Lebedev <lebedev.ri@gmail.com>2023-01-02 21:26:37 +0300
commitcf58063a4069b9ff11a99fd49345c1d188813feb (patch)
tree9b74992b117c6496185c0801233d094fd11ea6f6 /llvm/lib/Transforms
parent1fb07108d4f8606464fad98a49e2cbae7ec4ae25 (diff)
downloadllvm-cf58063a4069b9ff11a99fd49345c1d188813feb.zip
llvm-cf58063a4069b9ff11a99fd49345c1d188813feb.tar.gz
llvm-cf58063a4069b9ff11a99fd49345c1d188813feb.tar.bz2
[InstCombine] Canonicalize math-y conditional negation into a `select`
https://alive2.llvm.org/ce/z/vPs-gZ This is a larger pattern than would seem necessary, with minimal being: * `and` https://alive2.llvm.org/ce/z/q9-MqK * `or` https://alive2.llvm.org/ce/z/AUUEMZ * `xor` https://alive2.llvm.org/ce/z/dm3Ume .. so for all others, we canonicalize away from math to `select`, but there we canonicalize in the opposite direction. Fixes https://github.com/llvm/llvm-project/issues/59791
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp24
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineInternal.h3
2 files changed, 27 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 47f8c14..a4b14ad 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -1356,6 +1356,27 @@ Instruction *InstCombinerImpl::foldLogicOfIsFPClass(BinaryOperator &BO,
return nullptr;
}
+/// Look for the pattern that conditionally negates a value via math operations:
+/// cond.splat = sext i1 cond
+/// sub = add cond.splat, x
+/// xor = xor sub, cond.splat
+/// and rewrite it to do the same, but via logical operations:
+/// value.neg = sub 0, value
+/// cond = select i1 neg, value.neg, value
+Instruction *InstCombinerImpl::canonicalizeConditionalNegationViaMathToSelect(
+ BinaryOperator &I) {
+ assert(I.getOpcode() == BinaryOperator::Xor && "Only for xor!");
+ Value *Cond, *X;
+ // As per complexity ordering, `xor` is not commutative here.
+ if (!match(&I, m_c_BinOp(m_OneUse(m_Value()), m_Value())) ||
+ !match(I.getOperand(1), m_SExt(m_Value(Cond))) ||
+ !Cond->getType()->isIntOrIntVectorTy(1) ||
+ !match(I.getOperand(0), m_c_Add(m_SExt(m_Deferred(Cond)), m_Value(X))))
+ return nullptr;
+ return SelectInst::Create(Cond, Builder.CreateNeg(X, X->getName() + ".neg"),
+ X);
+}
+
/// This a limited reassociation for a special case (see above) where we are
/// checking if two values are either both NAN (unordered) or not-NAN (ordered).
/// This could be handled more generally in '-reassociation', but it seems like
@@ -4237,5 +4258,8 @@ Instruction *InstCombinerImpl::visitXor(BinaryOperator &I) {
if (Instruction *Folded = foldLogicOfIsFPClass(I, Op0, Op1))
return Folded;
+ if (Instruction *Folded = canonicalizeConditionalNegationViaMathToSelect(I))
+ return Folded;
+
return nullptr;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index f700cdb..bfbc31e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -365,6 +365,9 @@ private:
Instruction *foldLogicOfIsFPClass(BinaryOperator &Operator, Value *LHS,
Value *RHS);
+ Instruction *
+ canonicalizeConditionalNegationViaMathToSelect(BinaryOperator &i);
+
Value *foldAndOrOfICmpsOfAndWithPow2(ICmpInst *LHS, ICmpInst *RHS,
Instruction *CxtI, bool IsAnd,
bool IsLogical = false);