diff options
| author | Roman Lebedev <lebedev.ri@gmail.com> | 2023-01-02 21:15:31 +0300 |
|---|---|---|
| committer | Roman Lebedev <lebedev.ri@gmail.com> | 2023-01-02 21:26:37 +0300 |
| commit | cf58063a4069b9ff11a99fd49345c1d188813feb (patch) | |
| tree | 9b74992b117c6496185c0801233d094fd11ea6f6 /llvm/lib/Transforms | |
| parent | 1fb07108d4f8606464fad98a49e2cbae7ec4ae25 (diff) | |
| download | llvm-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.cpp | 24 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineInternal.h | 3 |
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); |
