diff --git a/llvm/lib/Transforms/Scalar/SCCP.cpp b/llvm/lib/Transforms/Scalar/SCCP.cpp index 6b130a41c4d606..2d83fa38b80fb9 100644 --- a/llvm/lib/Transforms/Scalar/SCCP.cpp +++ b/llvm/lib/Transforms/Scalar/SCCP.cpp @@ -74,26 +74,91 @@ STATISTIC(IPNumGlobalConst, "Number of globals found to be constant by IPSCCP"); namespace { -// Use ValueLatticeElement as LatticeVal. -using LatticeVal = ValueLatticeElement; - -// Helper to check if \p LV is either a constant or a constant -// range with a single element. This should cover exactly the same cases as the -// old LatticeVal::isConstant() and is intended to be used in the transition -// from LatticeVal to LatticeValueElement. -bool isConstant(const LatticeVal &LV) { - return LV.isConstant() || - (LV.isConstantRange() && LV.getConstantRange().isSingleElement()); -} +/// LatticeVal class - This class represents the different lattice values that +/// an LLVM value may occupy. It is a simple class with value semantics. +/// +class LatticeVal { + enum LatticeValueTy { + /// unknown - This LLVM Value has no known value yet. + unknown, -// Helper to check if \p LV is either overdefined or a constant range with more -// than a single element. This should cover exactly the same cases as the old -// LatticeVal::isOverdefined() and is intended to be used in the transition from -// LatticeVal to LatticeValueElement. -bool isOverdefined(const LatticeVal &LV) { - return LV.isOverdefined() || - (LV.isConstantRange() && !LV.getConstantRange().isSingleElement()); -} + /// constant - This LLVM Value has a specific constant value. + constant, + + /// overdefined - This instruction is not known to be constant, and we know + /// it has a value. + overdefined + }; + + /// Val: This stores the current lattice value along with the Constant* for + /// the constant if this is a 'constant' value. + PointerIntPair Val; + + LatticeValueTy getLatticeValue() const { + return Val.getInt(); + } + +public: + LatticeVal() : Val(nullptr, unknown) {} + + bool isUnknown() const { return getLatticeValue() == unknown; } + + bool isConstant() const { return getLatticeValue() == constant; } + + bool isOverdefined() const { return getLatticeValue() == overdefined; } + + Constant *getConstant() const { + assert(isConstant() && "Cannot get the constant of a non-constant!"); + return Val.getPointer(); + } + + /// markOverdefined - Return true if this is a change in status. + bool markOverdefined() { + if (isOverdefined()) + return false; + + Val.setInt(overdefined); + return true; + } + + /// markConstant - Return true if this is a change in status. + bool markConstant(Constant *V) { + if (getLatticeValue() == constant) { // Constant + assert(getConstant() == V && "Marking constant with different value"); + return false; + } + + assert(isUnknown()); + Val.setInt(constant); + assert(V && "Marking constant with NULL"); + Val.setPointer(V); + return true; + } + + /// getConstantInt - If this is a constant with a ConstantInt value, return it + /// otherwise return null. + ConstantInt *getConstantInt() const { + if (isConstant()) + return dyn_cast(getConstant()); + return nullptr; + } + + /// getBlockAddress - If this is a constant with a BlockAddress value, return + /// it, otherwise return null. + BlockAddress *getBlockAddress() const { + if (isConstant()) + return dyn_cast(getConstant()); + return nullptr; + } + + ValueLatticeElement toValueLattice() const { + if (isOverdefined()) + return ValueLatticeElement::getOverdefined(); + if (isConstant()) + return ValueLatticeElement::get(getConstant()); + return ValueLatticeElement(); + } +}; //===----------------------------------------------------------------------===// // @@ -105,6 +170,8 @@ class SCCPSolver : public InstVisitor { std::function GetTLI; SmallPtrSet BBExecutable; // The BBs that are executable. DenseMap ValueState; // The state each value is in. + // The state each parameter is in. + DenseMap ParamState; /// StructValueState - This maintains ValueState for values that have /// StructType, for example for formal arguments, calls, insertelement, etc. @@ -159,8 +226,6 @@ class SCCPSolver : public InstVisitor { DenseMap AnalysisResults; DenseMap> AdditionalUsers; - LLVMContext &Ctx; - public: void addAnalysis(Function &F, AnalysisResultsForFn A) { AnalysisResults.insert({&F, std::move(A)}); @@ -180,9 +245,8 @@ class SCCPSolver : public InstVisitor { } SCCPSolver(const DataLayout &DL, - std::function GetTLI, - LLVMContext &Ctx) - : DL(DL), GetTLI(std::move(GetTLI)), Ctx(Ctx) {} + std::function GetTLI) + : DL(DL), GetTLI(std::move(GetTLI)) {} /// MarkBlockExecutable - This method can be used by clients to mark all of /// the blocks that are known to be intrinsically live in the processed unit. @@ -318,50 +382,23 @@ class SCCPSolver : public InstVisitor { } // isStructLatticeConstant - Return true if all the lattice values - // corresponding to elements of the structure are constants, + // corresponding to elements of the structure are not overdefined, // false otherwise. bool isStructLatticeConstant(Function *F, StructType *STy) { for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i)); assert(It != TrackedMultipleRetVals.end()); LatticeVal LV = It->second; - if (!isConstant(LV)) + if (LV.isOverdefined()) return false; } return true; } - /// Helper to return a Constant if \p LV is either a constant or a constant - /// range with a single element. - Constant *getConstant(const LatticeVal &LV) const { - if (LV.isConstant()) - return LV.getConstant(); - - if (LV.isConstantRange()) { - auto &CR = LV.getConstantRange(); - if (CR.getSingleElement()) - return ConstantInt::get(Ctx, *CR.getSingleElement()); - } - return nullptr; - } - private: - ConstantInt *getConstantInt(const LatticeVal &IV) const { - return dyn_cast_or_null(getConstant(IV)); - } - // pushToWorkList - Helper for markConstant/markOverdefined void pushToWorkList(LatticeVal &IV, Value *V) { - if (isOverdefined(IV)) - return OverdefinedInstWorkList.push_back(V); - InstWorkList.push_back(V); - } - - // Helper to push \p V to the worklist, after updating it to \p IV. Also - // prints a debug message with the updated value. - void pushToWorkListMsg(LatticeVal &IV, Value *V) { - LLVM_DEBUG(dbgs() << "updated " << IV << ": " << *V << '\n'); - if (isOverdefined(IV)) + if (IV.isOverdefined()) return OverdefinedInstWorkList.push_back(V); InstWorkList.push_back(V); } @@ -396,29 +433,22 @@ class SCCPSolver : public InstVisitor { return true; } - bool mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV, - bool Widen = true) { - // Do a simple form of widening, to avoid extending a range repeatedly in a - // loop. If IV is a constant range, it means we already set it once. If - // MergeWithV would extend IV, mark V as overdefined. - if (Widen && IV.isConstantRange() && MergeWithV.isConstantRange() && - !IV.getConstantRange().contains(MergeWithV.getConstantRange())) { - markOverdefined(IV, V); - return true; - } - if (IV.mergeIn(MergeWithV, DL)) { - pushToWorkList(IV, V); - LLVM_DEBUG(dbgs() << "Merged " << MergeWithV << " into " << *V << " : " - << IV << "\n"); - return true; - } + bool mergeInValue(LatticeVal &IV, Value *V, LatticeVal MergeWithV) { + if (IV.isOverdefined() || MergeWithV.isUnknown()) + return false; // Noop. + if (MergeWithV.isOverdefined()) + return markOverdefined(IV, V); + if (IV.isUnknown()) + return markConstant(IV, V, MergeWithV.getConstant()); + if (IV.getConstant() != MergeWithV.getConstant()) + return markOverdefined(IV, V); return false; } - bool mergeInValue(Value *V, LatticeVal MergeWithV, bool Widen = true) { + bool mergeInValue(Value *V, LatticeVal MergeWithV) { assert(!V->getType()->isStructTy() && "non-structs should use markConstant"); - return mergeInValue(ValueState[V], V, MergeWithV, Widen); + return mergeInValue(ValueState[V], V, MergeWithV); } /// getValueState - Return the LatticeVal object that corresponds to the @@ -462,6 +492,18 @@ class SCCPSolver : public InstVisitor { return Res; } + ValueLatticeElement &getParamState(Value *V) { + assert(!V->getType()->isStructTy() && "Should use getStructValueState"); + + std::pair::iterator, bool> + PI = ParamState.insert(std::make_pair(V, ValueLatticeElement())); + ValueLatticeElement &LV = PI.first->second; + if (PI.second) + LV = getValueState(V).toValueLattice(); + + return LV; + } + /// getStructValueState - Return the LatticeVal object that corresponds to the /// value/field pair. This function handles the case when the value hasn't /// been seen yet by properly seeding constants etc. @@ -617,7 +659,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI, } LatticeVal BCValue = getValueState(BI->getCondition()); - ConstantInt *CI = getConstantInt(BCValue); + ConstantInt *CI = BCValue.getConstantInt(); if (!CI) { // Overdefined condition variables, and branches on unfoldable constant // conditions, mean the branch could go either way. @@ -643,7 +685,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI, return; } LatticeVal SCValue = getValueState(SI->getCondition()); - ConstantInt *CI = getConstantInt(SCValue); + ConstantInt *CI = SCValue.getConstantInt(); if (!CI) { // Overdefined or unknown condition? // All destinations are executable! @@ -661,7 +703,7 @@ void SCCPSolver::getFeasibleSuccessors(Instruction &TI, if (auto *IBR = dyn_cast(&TI)) { // Casts are folded by visitCastInst. LatticeVal IBRValue = getValueState(IBR->getAddress()); - BlockAddress *Addr = dyn_cast_or_null(getConstant(IBRValue)); + BlockAddress *Addr = IBRValue.getBlockAddress(); if (!Addr) { // Overdefined or unknown condition? // All destinations are executable! if (!IBRValue.isUnknown()) @@ -728,9 +770,8 @@ void SCCPSolver::visitPHINode(PHINode &PN) { if (PN.getType()->isStructTy()) return (void)markOverdefined(&PN); - if (isOverdefined(getValueState(&PN))) { - return (void)markOverdefined(&PN); - } + if (getValueState(&PN).isOverdefined()) + return; // Quick exit // Super-extra-high-degree PHI nodes are unlikely to ever be marked constant, // and slow us down a lot. Just mark them overdefined. @@ -750,11 +791,11 @@ void SCCPSolver::visitPHINode(PHINode &PN) { if (!isEdgeFeasible(PN.getIncomingBlock(i), PN.getParent())) continue; - if (isOverdefined(IV)) // PHI node becomes overdefined! + if (IV.isOverdefined()) // PHI node becomes overdefined! return (void)markOverdefined(&PN); if (!OperandVal) { // Grab the first value. - OperandVal = getConstant(IV); + OperandVal = IV.getConstant(); continue; } @@ -764,7 +805,7 @@ void SCCPSolver::visitPHINode(PHINode &PN) { // Check to see if there are two different constants merging, if so, the PHI // node is overdefined. - if (getConstant(IV) != OperandVal) + if (IV.getConstant() != OperandVal) return (void)markOverdefined(&PN); } @@ -781,7 +822,7 @@ void SCCPSolver::visitReturnInst(ReturnInst &I) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&I])) + if (ValueState[&I].isOverdefined()) return; Function *F = I.getParent()->getParent(); @@ -822,25 +863,27 @@ void SCCPSolver::visitTerminator(Instruction &TI) { void SCCPSolver::visitCastInst(CastInst &I) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&I])) + if (ValueState[&I].isOverdefined()) return; LatticeVal OpSt = getValueState(I.getOperand(0)); - if (Constant *OpC = getConstant(OpSt)) { + if (OpSt.isOverdefined()) // Inherit overdefinedness of operand + markOverdefined(&I); + else if (OpSt.isConstant()) { // Fold the constant as we build. - Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL); + Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpSt.getConstant(), + I.getType(), DL); if (isa(C)) return; // Propagate constant value markConstant(&I, C); - } else if (!OpSt.isUnknown()) - markOverdefined(&I); + } } void SCCPSolver::visitExtractValueInst(ExtractValueInst &EVI) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&EVI])) + if (ValueState[&EVI].isOverdefined()) return; // If this returns a struct, mark all elements over defined, we don't track @@ -870,7 +913,7 @@ void SCCPSolver::visitInsertValueInst(InsertValueInst &IVI) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&IVI])) + if (ValueState[&IVI].isOverdefined()) return; // If this has more than one index, we can't handle it, drive all results to @@ -909,14 +952,14 @@ void SCCPSolver::visitSelectInst(SelectInst &I) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&I])) + if (ValueState[&I].isOverdefined()) return; LatticeVal CondValue = getValueState(I.getCondition()); if (CondValue.isUnknown()) return; - if (ConstantInt *CondCB = getConstantInt(CondValue)) { + if (ConstantInt *CondCB = CondValue.getConstantInt()) { Value *OpVal = CondCB->isZero() ? I.getFalseValue() : I.getTrueValue(); mergeInValue(&I, getValueState(OpVal)); return; @@ -929,9 +972,9 @@ void SCCPSolver::visitSelectInst(SelectInst &I) { LatticeVal FVal = getValueState(I.getFalseValue()); // select ?, C, C -> C. - if (isConstant(TVal) && isConstant(FVal) && - getConstant(TVal) == getConstant(FVal)) - return (void)markConstant(&I, getConstant(FVal)); + if (TVal.isConstant() && FVal.isConstant() && + TVal.getConstant() == FVal.getConstant()) + return (void)markConstant(&I, FVal.getConstant()); if (TVal.isUnknown()) // select ?, undef, X -> X. return (void)mergeInValue(&I, FVal); @@ -947,10 +990,10 @@ void SCCPSolver::visitUnaryOperator(Instruction &I) { LatticeVal &IV = ValueState[&I]; // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(IV)) return; + if (IV.isOverdefined()) return; - if (isConstant(V0State)) { - Constant *C = ConstantExpr::get(I.getOpcode(), getConstant(V0State)); + if (V0State.isConstant()) { + Constant *C = ConstantExpr::get(I.getOpcode(), V0State.getConstant()); // op Y -> undef. if (isa(C)) @@ -959,7 +1002,7 @@ void SCCPSolver::visitUnaryOperator(Instruction &I) { } // If something is undef, wait for it to resolve. - if (!isOverdefined(V0State)) + if (!V0State.isOverdefined()) return; markOverdefined(&I); @@ -971,14 +1014,11 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) { LatticeVal V2State = getValueState(I.getOperand(1)); LatticeVal &IV = ValueState[&I]; - if (isOverdefined(IV)) { - markOverdefined(&I); - return; - } + if (IV.isOverdefined()) return; - if (isConstant(V1State) && isConstant(V2State)) { - Constant *C = ConstantExpr::get(I.getOpcode(), getConstant(V1State), - getConstant(V2State)); + if (V1State.isConstant() && V2State.isConstant()) { + Constant *C = ConstantExpr::get(I.getOpcode(), V1State.getConstant(), + V2State.getConstant()); // X op Y -> undef. if (isa(C)) return; @@ -986,16 +1026,18 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) { } // If something is undef, wait for it to resolve. - if (V1State.isUnknown() || V2State.isUnknown()) + if (!V1State.isOverdefined() && !V2State.isOverdefined()) { + return; + } // Otherwise, one of our operands is overdefined. Try to produce something // better than overdefined with some tricks. // If this is 0 / Y, it doesn't matter that the second operand is // overdefined, and we can replace it with zero. if (I.getOpcode() == Instruction::UDiv || I.getOpcode() == Instruction::SDiv) - if (isConstant(V1State) && getConstant(V1State)->isNullValue()) - return (void)markConstant(IV, &I, getConstant(V1State)); + if (V1State.isConstant() && V1State.getConstant()->isNullValue()) + return (void)markConstant(IV, &I, V1State.getConstant()); // If this is: // -> AND/MUL with 0 @@ -1004,10 +1046,9 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) { if (I.getOpcode() == Instruction::And || I.getOpcode() == Instruction::Mul || I.getOpcode() == Instruction::Or) { LatticeVal *NonOverdefVal = nullptr; - if (!isOverdefined(V1State)) + if (!V1State.isOverdefined()) NonOverdefVal = &V1State; - - else if (!isOverdefined(V2State)) + else if (!V2State.isOverdefined()) NonOverdefVal = &V2State; if (NonOverdefVal) { if (NonOverdefVal->isUnknown()) @@ -1017,13 +1058,13 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) { I.getOpcode() == Instruction::Mul) { // X and 0 = 0 // X * 0 = 0 - if (getConstant(*NonOverdefVal)->isNullValue()) - return (void)markConstant(IV, &I, getConstant(*NonOverdefVal)); + if (NonOverdefVal->getConstant()->isNullValue()) + return (void)markConstant(IV, &I, NonOverdefVal->getConstant()); } else { // X or -1 = -1 - if (ConstantInt *CI = getConstantInt(*NonOverdefVal)) + if (ConstantInt *CI = NonOverdefVal->getConstantInt()) if (CI->isMinusOne()) - return (void)markConstant(IV, &I, CI); + return (void)markConstant(IV, &I, NonOverdefVal->getConstant()); } } } @@ -1035,18 +1076,22 @@ void SCCPSolver::visitBinaryOperator(Instruction &I) { void SCCPSolver::visitCmpInst(CmpInst &I) { // Do not cache this lookup, getValueState calls later in the function might // invalidate the reference. - if (isOverdefined(ValueState[&I])) { - markOverdefined(&I); - return; - } + if (ValueState[&I].isOverdefined()) return; Value *Op1 = I.getOperand(0); Value *Op2 = I.getOperand(1); // For parameters, use ParamState which includes constant range info if // available. - auto V1State = getValueState(Op1); - auto V2State = getValueState(Op2); + auto V1Param = ParamState.find(Op1); + ValueLatticeElement V1State = (V1Param != ParamState.end()) + ? V1Param->second + : getValueState(Op1).toValueLattice(); + + auto V2Param = ParamState.find(Op2); + ValueLatticeElement V2State = V2Param != ParamState.end() + ? V2Param->second + : getValueState(Op2).toValueLattice(); Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State); if (C) { @@ -1059,8 +1104,8 @@ void SCCPSolver::visitCmpInst(CmpInst &I) { } // If operands are still unknown, wait for it to resolve. - if ((V1State.isUnknown() || V2State.isUnknown()) && - !isConstant(ValueState[&I])) + if (!V1State.isOverdefined() && !V2State.isOverdefined() && + !ValueState[&I].isConstant()) return; markOverdefined(&I); @@ -1069,7 +1114,7 @@ void SCCPSolver::visitCmpInst(CmpInst &I) { // Handle getelementptr instructions. If all operands are constants then we // can turn this into a getelementptr ConstantExpr. void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) { - if (isOverdefined(ValueState[&I])) return; + if (ValueState[&I].isOverdefined()) return; SmallVector Operands; Operands.reserve(I.getNumOperands()); @@ -1079,15 +1124,11 @@ void SCCPSolver::visitGetElementPtrInst(GetElementPtrInst &I) { if (State.isUnknown()) return; // Operands are not resolved yet. - if (isOverdefined(State)) + if (State.isOverdefined()) return (void)markOverdefined(&I); - if (Constant *C = getConstant(State)) { - Operands.push_back(C); - continue; - } - - return (void)markOverdefined(&I); + assert(State.isConstant() && "Unknown state!"); + Operands.push_back(State.getConstant()); } Constant *Ptr = Operands[0]; @@ -1109,17 +1150,16 @@ void SCCPSolver::visitStoreInst(StoreInst &SI) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&SI])) + if (ValueState[&SI].isOverdefined()) return; GlobalVariable *GV = cast(SI.getOperand(1)); DenseMap::iterator I = TrackedGlobals.find(GV); - if (I == TrackedGlobals.end()) - return; + if (I == TrackedGlobals.end() || I->second.isOverdefined()) return; // Get the value we are storing into the global, then merge it. mergeInValue(I->second, GV, getValueState(SI.getOperand(0))); - if (isOverdefined(I->second)) + if (I->second.isOverdefined()) TrackedGlobals.erase(I); // No need to keep tracking this! } @@ -1132,7 +1172,7 @@ void SCCPSolver::visitLoadInst(LoadInst &I) { // ResolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(ValueState[&I])) + if (ValueState[&I].isOverdefined()) return; LatticeVal PtrVal = getValueState(I.getOperand(0)); @@ -1140,10 +1180,10 @@ void SCCPSolver::visitLoadInst(LoadInst &I) { LatticeVal &IV = ValueState[&I]; - if (!isConstant(PtrVal) || I.isVolatile()) + if (!PtrVal.isConstant() || I.isVolatile()) return (void)markOverdefined(IV, &I); - Constant *Ptr = getConstant(PtrVal); + Constant *Ptr = PtrVal.getConstant(); // load null is undefined. if (isa(Ptr)) { @@ -1184,7 +1224,7 @@ void SCCPSolver::visitCallSite(CallSite CS) { if (auto *II = dyn_cast(I)) { if (II->getIntrinsicID() == Intrinsic::ssa_copy) { - if (isOverdefined(ValueState[I])) + if (ValueState[I].isOverdefined()) return; auto *PI = getPredicateInfoFor(I); @@ -1222,7 +1262,7 @@ void SCCPSolver::visitCallSite(CallSite CS) { LatticeVal &IV = ValueState[I]; if (PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_EQ) { addAdditionalUser(CmpOp1, I); - if (isConstant(OriginalVal)) + if (OriginalVal.isConstant()) mergeInValue(IV, I, OriginalVal); else mergeInValue(IV, I, EqVal); @@ -1230,7 +1270,7 @@ void SCCPSolver::visitCallSite(CallSite CS) { } if (!PBranch->TrueEdge && Cmp->getPredicate() == CmpInst::ICMP_NE) { addAdditionalUser(CmpOp1, I); - if (isConstant(OriginalVal)) + if (OriginalVal.isConstant()) mergeInValue(IV, I, OriginalVal); else mergeInValue(IV, I, EqVal); @@ -1262,13 +1302,13 @@ void SCCPSolver::visitCallSite(CallSite CS) { if (State.isUnknown()) return; // Operands are not resolved yet. - if (isOverdefined(State)) + if (State.isOverdefined()) return (void)markOverdefined(I); - assert(isConstant(State) && "Unknown state!"); - Operands.push_back(getConstant(State)); + assert(State.isConstant() && "Unknown state!"); + Operands.push_back(State.getConstant()); } - if (isOverdefined(getValueState(I))) + if (getValueState(I).isOverdefined()) return; // If we can constant fold this, mark the result of the call as a @@ -1306,10 +1346,24 @@ void SCCPSolver::visitCallSite(CallSite CS) { if (auto *STy = dyn_cast(AI->getType())) { for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) { LatticeVal CallArg = getStructValueState(*CAI, i); - mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg, false); + mergeInValue(getStructValueState(&*AI, i), &*AI, CallArg); } - } else - mergeInValue(&*AI, getValueState(*CAI), false); + } else { + // Most other parts of the Solver still only use the simpler value + // lattice, so we propagate changes for parameters to both lattices. + ValueLatticeElement ConcreteArgument = + isa(*CAI) ? getParamState(*CAI) + : getValueState(*CAI).toValueLattice(); + bool ParamChanged = getParamState(&*AI).mergeIn(ConcreteArgument, DL); + bool ValueChanged = + mergeInValue(&*AI, toLatticeVal(ConcreteArgument, AI->getType())); + // Add argument to work list, if the state of a parameter changes but + // ValueState does not change (because it is already overdefined there), + // We have to take changes in ParamState into account, as it is used + // when evaluating Cmp instructions. + if (!ValueChanged && ParamChanged) + pushToWorkList(ValueState[&*AI], &*AI); + } } } @@ -1367,7 +1421,7 @@ void SCCPSolver::Solve() { // since all of its users will have already been marked as overdefined. // Update all of the users of this instruction's value. // - if (I->getType()->isStructTy() || !isOverdefined(getValueState(I))) + if (I->getType()->isStructTy() || !getValueState(I).isOverdefined()) markUsersAsChanged(I); } @@ -1546,24 +1600,24 @@ static bool tryToReplaceWithConstant(SCCPSolver &Solver, Value *V) { Constant *Const = nullptr; if (V->getType()->isStructTy()) { std::vector IVs = Solver.getStructLatticeValueFor(V); - if (any_of(IVs, [](const LatticeVal &LV) { return isOverdefined(LV); })) + if (llvm::any_of(IVs, + [](const LatticeVal &LV) { return LV.isOverdefined(); })) return false; std::vector ConstVals; auto *ST = cast(V->getType()); for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { LatticeVal V = IVs[i]; - ConstVals.push_back(isConstant(V) - ? Solver.getConstant(V) + ConstVals.push_back(V.isConstant() + ? V.getConstant() : UndefValue::get(ST->getElementType(i))); } Const = ConstantStruct::get(ST, ConstVals); } else { const LatticeVal &IV = Solver.getLatticeValueFor(V); - if (isOverdefined(IV)) + if (IV.isOverdefined()) return false; - Const = - isConstant(IV) ? Solver.getConstant(IV) : UndefValue::get(V->getType()); + Const = IV.isConstant() ? IV.getConstant() : UndefValue::get(V->getType()); } assert(Const && "Constant is nullptr here!"); @@ -1596,8 +1650,7 @@ static bool runSCCP(Function &F, const DataLayout &DL, const TargetLibraryInfo *TLI) { LLVM_DEBUG(dbgs() << "SCCP on function '" << F.getName() << "'\n"); SCCPSolver Solver( - DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; }, - F.getContext()); + DL, [TLI](Function &F) -> const TargetLibraryInfo & { return *TLI; }); // Mark the first block of the function as being executable. Solver.MarkBlockExecutable(&F.front()); @@ -1740,9 +1793,9 @@ static void findReturnsToZap(Function &F, if (U->getType()->isStructTy()) { return all_of( Solver.getStructLatticeValueFor(U), - [](const LatticeVal &LV) { return !isOverdefined(LV); }); + [](const LatticeVal &LV) { return !LV.isOverdefined(); }); } - return !isOverdefined(Solver.getLatticeValueFor(U)); + return !Solver.getLatticeValueFor(U).isOverdefined(); }) && "We can only zap functions where all live users have a concrete value"); @@ -1799,7 +1852,7 @@ bool llvm::runIPSCCP( Module &M, const DataLayout &DL, std::function GetTLI, function_ref getAnalysis) { - SCCPSolver Solver(DL, GetTLI, M.getContext()); + SCCPSolver Solver(DL, GetTLI); // Loop over all functions, marking arguments to those with their addresses // taken or that are external as overdefined. @@ -1985,7 +2038,7 @@ bool llvm::runIPSCCP( const MapVector &RV = Solver.getTrackedRetVals(); for (const auto &I : RV) { Function *F = I.first; - if (isOverdefined(I.second) || F->getReturnType()->isVoidTy()) + if (I.second.isOverdefined() || F->getReturnType()->isVoidTy()) continue; findReturnsToZap(*F, ReturnsToZap, Solver); } @@ -2010,8 +2063,8 @@ bool llvm::runIPSCCP( for (DenseMap::const_iterator I = TG.begin(), E = TG.end(); I != E; ++I) { GlobalVariable *GV = I->first; - if (isOverdefined(I->second)) - continue; + assert(!I->second.isOverdefined() && + "Overdefined values should have been taken out of the map!"); LLVM_DEBUG(dbgs() << "Found that GV '" << GV->getName() << "' is constant!\n"); while (!GV->use_empty()) { diff --git a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll index dbaedaa739bf40..08de8dba4046a5 100644 --- a/llvm/test/Transforms/SCCP/ip-constant-ranges.ll +++ b/llvm/test/Transforms/SCCP/ip-constant-ranges.ll @@ -230,7 +230,7 @@ define i32 @caller6() { ; CHECK-NEXT: %call.1 = call i32 @callee6.1(i32 30) ; CHECK-NEXT: %call.2 = call i32 @callee6.1(i32 43) ; CHECK-NEXT: ret i32 2 -; + %call.1 = call i32 @callee6.1(i32 30) %call.2 = call i32 @callee6.1(i32 43) %res = add i32 %call.1, %call.2 diff --git a/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll b/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll index d56c91061cadc8..0fa465d09fd530 100644 --- a/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll +++ b/llvm/test/Transforms/SCCP/resolvedundefsin-tracked-fn.ll @@ -40,7 +40,9 @@ define internal i32 @test1_k(i8 %h, i32 %i) { ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1* ; CHECK-NEXT: [[CALL:%.*]] = call i1 @test1_g(%t1* [[TMP1]], i32 0) -; CHECK-NEXT: call void @use.1(i1 false) +; CHECK-NEXT: [[FROMBOOL_1:%.*]] = zext i1 false to i8 +; CHECK-NEXT: [[TOBOOL_1:%.*]] = trunc i8 [[FROMBOOL_1]] to i1 +; CHECK-NEXT: call void @use.1(i1 [[TOBOOL_1]]) ; CHECK-NEXT: ret i32 undef ; entry: @@ -117,7 +119,9 @@ define internal i32 @test2_k(i8 %h, i32 %i) { ; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[TMP0]] to i64 ; CHECK-NEXT: [[TMP1:%.*]] = inttoptr i64 [[CONV]] to %t1* ; CHECK-NEXT: [[CALL:%.*]] = call i1 @test3_g(%t1* [[TMP1]], i32 0) -; CHECK-NEXT: call void @use.1(i1 false) +; CHECK-NEXT: [[FROMBOOL:%.*]] = icmp slt i1 false, true +; CHECK-NEXT: [[ADD:%.*]] = add i1 [[FROMBOOL]], [[FROMBOOL]] +; CHECK-NEXT: call void @use.1(i1 [[FROMBOOL]]) ; CHECK-NEXT: ret i32 undef ; entry: @@ -389,6 +393,7 @@ define void @test3() { ; CHECK-NEXT: [[CMP25474:%.*]] = icmp sgt i32 [[TMP2]], 0 ; CHECK-NEXT: br i1 [[CMP25474]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] ; CHECK: for.body: +; CHECK-NEXT: [[DIV30:%.*]] = sdiv i32 0, [[SUB19]] ; CHECK-NEXT: ret void ; CHECK: for.end: ; CHECK-NEXT: ret void