From c5f425b201b7711e7ce9d4fc73c6a4472067b1f0 Mon Sep 17 00:00:00 2001 From: Chad Rosier Date: Tue, 1 Aug 2017 19:22:36 +0000 Subject: [PATCH] [Value Tracking] Refactor and/or logic into helper. NFC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309726 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/ValueTracking.cpp | 92 ++++++++++++++++++++++++------------------ 1 file changed, 52 insertions(+), 40 deletions(-) diff --git a/lib/Analysis/ValueTracking.cpp b/lib/Analysis/ValueTracking.cpp index f5557b5881d..fd73f25660f 100644 --- a/lib/Analysis/ValueTracking.cpp +++ b/lib/Analysis/ValueTracking.cpp @@ -4493,62 +4493,74 @@ static Optional isImpliedCondICmps(const ICmpInst *LHS, return None; } +/// Return true if LHS implies RHS is true. Return false if LHS implies RHS is +/// false. Otherwise, return None if we can't infer anything. We expect the +/// RHS to be an icmp and the LHS to be an 'and' or an 'or' instruction. +static Optional isImpliedCondAndOr(const BinaryOperator *LHS, + const ICmpInst *RHS, + const DataLayout &DL, bool LHSIsFalse, + unsigned Depth) { + // The LHS must be an 'or' or an 'and' instruction. + assert((LHS->getOpcode() == Instruction::And || + LHS->getOpcode() == Instruction::Or) && + "Expected LHS to be 'and' or 'or'."); + + // The remaining tests are all recursive, so bail out if we hit the limit. + if (Depth == MaxDepth) + return None; + + // If the result of an 'or' is false, then we know both legs of the 'or' are + // false. Similarly, if the result of an 'and' is true, then we know both + // legs of the 'and' are true. + Value *ALHS, *ARHS; + if ((LHSIsFalse && match(LHS, m_Or(m_Value(ALHS), m_Value(ARHS)))) || + (!LHSIsFalse && match(LHS, m_And(m_Value(ALHS), m_Value(ARHS))))) { + // FIXME: Make this non-recursion. + if (Optional Implication = + isImpliedCondition(ALHS, RHS, DL, LHSIsFalse, Depth + 1)) + return Implication; + if (Optional Implication = + isImpliedCondition(ARHS, RHS, DL, LHSIsFalse, Depth + 1)) + return Implication; + return None; + } + return None; +} + Optional llvm::isImpliedCondition(const Value *LHS, const Value *RHS, const DataLayout &DL, bool LHSIsFalse, unsigned Depth) { - // A mismatch occurs when we compare a scalar cmp to a vector cmp, for example. + // A mismatch occurs when we compare a scalar cmp to a vector cmp, for + // example. if (LHS->getType() != RHS->getType()) return None; Type *OpTy = LHS->getType(); - assert(OpTy->isIntOrIntVectorTy(1)); + assert(OpTy->isIntOrIntVectorTy(1) && "Expected integer type only!"); // LHS ==> RHS by definition if (LHS == RHS) return !LHSIsFalse; + // FIXME: Extending the code below to handle vectors. if (OpTy->isVectorTy()) - // TODO: extending the code below to handle vectors return None; - assert(OpTy->isIntegerTy(1) && "implied by above"); - // We expect the RHS to be an icmp. - if (!isa(RHS)) - return None; + assert(OpTy->isIntegerTy(1) && "implied by above"); // Both LHS and RHS are icmps. - if (isa(LHS)) - return isImpliedCondICmps(cast(LHS), cast(RHS), DL, - LHSIsFalse, Depth); - - // The LHS can be an 'or' or an 'and' instruction. - const Instruction *LHSInst = dyn_cast(LHS); - if (!LHSInst) - return None; - - switch (LHSInst->getOpcode()) { - default: - return None; - case Instruction::Or: - case Instruction::And: { - // The remaining tests are all recursive, so bail out if we hit the limit. - if (Depth == MaxDepth) - return None; - // If the result of an 'or' is false, then we know both legs of the 'or' are - // false. Similarly, if the result of an 'and' is true, then we know both - // legs of the 'and' are true. - Value *ALHS, *ARHS; - if ((LHSIsFalse && match(LHS, m_Or(m_Value(ALHS), m_Value(ARHS)))) || - (!LHSIsFalse && match(LHS, m_And(m_Value(ALHS), m_Value(ARHS))))) { - if (Optional Implication = - isImpliedCondition(ALHS, RHS, DL, LHSIsFalse, Depth + 1)) - return Implication; - if (Optional Implication = - isImpliedCondition(ARHS, RHS, DL, LHSIsFalse, Depth + 1)) - return Implication; - return None; - } - return None; - } + const ICmpInst *LHSCmp = dyn_cast(LHS); + const ICmpInst *RHSCmp = dyn_cast(RHS); + if (LHSCmp && RHSCmp) + return isImpliedCondICmps(LHSCmp, RHSCmp, DL, LHSIsFalse, Depth); + + // The LHS should be an 'or' or an 'and' instruction. We expect the RHS to be + // an icmp. FIXME: Add support for and/or on the RHS. + const BinaryOperator *LHSBO = dyn_cast(LHS); + if (LHSBO && RHSCmp) { + if ((LHSBO->getOpcode() == Instruction::And || + LHSBO->getOpcode() == Instruction::Or)) + return isImpliedCondAndOr(LHSBO, RHSCmp, DL, LHSIsFalse, Depth); } + return None; } -- 2.11.0