diff options
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); |
