From f947608ddfe026eaf013524e5fe09d3c425a5cf0 Mon Sep 17 00:00:00 2001 From: David Bolvansky Date: Sat, 28 Jul 2018 06:55:51 +0000 Subject: [InstCombine] Fold Select with AND/OR condition Summary: Fold ``` %A = icmp ne i8 %X, %V1 %B = icmp ne i8 %X, %V2 %C = or i1 %A, %B %D = select i1 %C, i8 %X, i8 %V1 ret i8 %D => ret i8 %X Fixes https://bugs.llvm.org/show_bug.cgi?id=38334 Proof: https://rise4fun.com/Alive/plI8 Reviewers: spatel, lebedev.ri Reviewed By: lebedev.ri Subscribers: craig.topper, llvm-commits Differential Revision: https://reviews.llvm.org/D49919 llvm-svn: 338191 --- llvm/lib/Analysis/InstructionSimplify.cpp | 37 +++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'llvm/lib/Analysis') diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 519d6d67be5..257fa705aa4 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -65,6 +65,40 @@ static Value *SimplifyCastInst(unsigned, Value *, Type *, static Value *SimplifyGEPInst(Type *, ArrayRef, const SimplifyQuery &, unsigned); +/// Fold +/// %A = icmp ne/eq i8 %X, %V1 +/// %B = icmp ne/eq i8 %X, %V2 +/// %C = or/and i1 %A, %B +/// %D = select i1 %C, i8 %X, i8 %V1 +/// To +/// %X/%V1 +static Value *foldSelectWithBinaryOp(Value *Cond, Value *TrueVal, + Value *FalseVal) { + BinaryOperator::BinaryOps BinOpCode; + if (auto *BO = dyn_cast(Cond)) + BinOpCode = BO->getOpcode(); + else + return nullptr; + + CmpInst::Predicate ExpectedPred; + if (BinOpCode == BinaryOperator::Or) { + ExpectedPred = ICmpInst::ICMP_NE; + } else if (BinOpCode == BinaryOperator::And) { + ExpectedPred = ICmpInst::ICMP_EQ; + } else + return nullptr; + + CmpInst::Predicate Pred1, Pred2; + if (!match( + Cond, + m_c_BinOp(m_c_ICmp(Pred1, m_Specific(TrueVal), m_Specific(FalseVal)), + m_c_ICmp(Pred2, m_Specific(TrueVal), m_Value()))) || + Pred1 != Pred2 || Pred1 != ExpectedPred) + return nullptr; + + return BinOpCode == BinaryOperator::Or ? TrueVal : FalseVal; +} + /// For a boolean type or a vector of boolean type, return false or a vector /// with every element false. static Constant *getFalse(Type *Ty) { @@ -3752,6 +3786,9 @@ static Value *SimplifySelectInst(Value *Cond, Value *TrueVal, Value *FalseVal, simplifySelectWithICmpCond(Cond, TrueVal, FalseVal, Q, MaxRecurse)) return V; + if (Value *V = foldSelectWithBinaryOp(Cond, TrueVal, FalseVal)) + return V; + return nullptr; } -- cgit v1.2.3