From ccd412f48d796102cc7694abf1be3ff43953eb99 Mon Sep 17 00:00:00 2001 From: Hiroshi Yamauchi Date: Thu, 10 Aug 2017 02:23:14 +0000 Subject: [PATCH] [LVI] Fix LVI compile time regression around constantFoldUser() Summary: Avoid checking each operand and calling getValueFromCondition() before calling constantFoldUser() when the instruction type isn't supported by constantFoldUser(). This fixes a large compile time regression in an internal build. Reviewers: sanjoy Reviewed By: sanjoy Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D36552 llvm-svn: 310545 --- llvm/lib/Analysis/LazyValueInfo.cpp | 42 ++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp index e72eede..9be773f 100644 --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1370,23 +1370,32 @@ static bool usesOperand(User *Usr, Value *Op) { return find(Usr->operands(), Op) != Usr->op_end(); } -// Check if Val can be simplified to an integer constant when the value of one +// Return true if the instruction type of Val is supported by +// constantFoldUser(). Currently CastInst and BinaryOperator only. Call this +// before calling constantFoldUser() to find out if it's even worth attempting +// to call it. +static bool isOperationFoldable(User *Usr) { + return isa(Usr) || isa(Usr); +} + +// Check if Usr can be simplified to an integer constant when the value of one // of its operands Op is an integer constant OpConstVal. If so, return it as an // lattice value range with a single element or otherwise return an overdefined // lattice value. -static LVILatticeVal constantFoldUser(Value *Val, Value *Op, +static LVILatticeVal constantFoldUser(User *Usr, Value *Op, const APInt &OpConstVal, const DataLayout &DL) { + assert(isOperationFoldable(Usr) && "Precondition"); Constant* OpConst = Constant::getIntegerValue(Op->getType(), OpConstVal); - // Check if Val can be simplified to a constant. - if (auto *CI = dyn_cast(Val)) { + // Check if Usr can be simplified to a constant. + if (auto *CI = dyn_cast(Usr)) { assert(CI->getOperand(0) == Op && "Operand 0 isn't Op"); if (auto *C = dyn_cast_or_null( SimplifyCastInst(CI->getOpcode(), OpConst, CI->getDestTy(), DL))) { return LVILatticeVal::getRange(ConstantRange(C->getValue())); } - } else if (auto *BO = dyn_cast(Val)) { + } else if (auto *BO = dyn_cast(Usr)) { bool Op0Match = BO->getOperand(0) == Op; bool Op1Match = BO->getOperand(1) == Op; assert((Op0Match || Op1Match) && @@ -1434,7 +1443,10 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, if (User *Usr = dyn_cast(Val)) { assert(Result.isOverdefined() && "Result isn't overdefined"); - if (isa(Val->getType())) { + // Check with isOperationFoldable() first to avoid linearly iterating + // over the operands unnecessarily which can be expensive for + // instructions with many operands. + if (isa(Usr->getType()) && isOperationFoldable(Usr)) { const DataLayout &DL = BBTo->getModule()->getDataLayout(); if (usesOperand(Usr, Condition)) { // If Val has Condition as an operand and Val can be folded into a @@ -1445,7 +1457,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, // %Val = and i1 %Condition, true. // br %Condition, label %then, label %else APInt ConditionVal(1, isTrueDest ? 1 : 0); - Result = constantFoldUser(Val, Condition, ConditionVal, DL); + Result = constantFoldUser(Usr, Condition, ConditionVal, DL); } else { // If one of Val's operand has an inferred value, we may be able to // infer the value of Val. @@ -1459,7 +1471,7 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, LVILatticeVal OpLatticeVal = getValueFromCondition(Op, Condition, isTrueDest); if (Optional OpConst = OpLatticeVal.asConstantInteger()) { - Result = constantFoldUser(Val, Op, OpConst.getValue(), DL); + Result = constantFoldUser(Usr, Op, OpConst.getValue(), DL); break; } } @@ -1477,15 +1489,16 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, Value *Condition = SI->getCondition(); if (!isa(Val->getType())) return false; - bool ValUsesCondition = false; + bool ValUsesConditionAndMayBeFoldable = false; if (Condition != Val) { // Check if Val has Condition as an operand. if (User *Usr = dyn_cast(Val)) - ValUsesCondition = usesOperand(Usr, Condition); - if (!ValUsesCondition) + ValUsesConditionAndMayBeFoldable = isOperationFoldable(Usr) && + usesOperand(Usr, Condition); + if (!ValUsesConditionAndMayBeFoldable) return false; } - assert((Condition == Val || ValUsesCondition) && + assert((Condition == Val || ValUsesConditionAndMayBeFoldable) && "Condition != Val nor Val doesn't use Condition"); bool DefaultCase = SI->getDefaultDest() == BBTo; @@ -1495,10 +1508,11 @@ static bool getEdgeValueLocal(Value *Val, BasicBlock *BBFrom, for (auto Case : SI->cases()) { APInt CaseValue = Case.getCaseValue()->getValue(); ConstantRange EdgeVal(CaseValue); - if (ValUsesCondition) { + if (ValUsesConditionAndMayBeFoldable) { + User *Usr = cast(Val); const DataLayout &DL = BBTo->getModule()->getDataLayout(); LVILatticeVal EdgeLatticeVal = - constantFoldUser(Val, Condition, CaseValue, DL); + constantFoldUser(Usr, Condition, CaseValue, DL); if (EdgeLatticeVal.isOverdefined()) return false; EdgeVal = EdgeLatticeVal.getConstantRange(); -- 2.7.4