diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Transforms/Utils/SCCPSolver.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) |
Diffstat (limited to 'llvm/lib/Transforms/Utils/SCCPSolver.cpp')
-rw-r--r-- | llvm/lib/Transforms/Utils/SCCPSolver.cpp | 422 |
1 files changed, 362 insertions, 60 deletions
diff --git a/llvm/lib/Transforms/Utils/SCCPSolver.cpp b/llvm/lib/Transforms/Utils/SCCPSolver.cpp index 09a83f1ea094..8d03a0d8a2c4 100644 --- a/llvm/lib/Transforms/Utils/SCCPSolver.cpp +++ b/llvm/lib/Transforms/Utils/SCCPSolver.cpp @@ -16,11 +16,13 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/Analysis/InstructionSimplify.h" #include "llvm/Analysis/ValueLattice.h" +#include "llvm/Analysis/ValueLatticeUtils.h" #include "llvm/IR/InstVisitor.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Local.h" #include <cassert> #include <utility> #include <vector> @@ -39,28 +41,257 @@ static ValueLatticeElement::MergeOptions getMaxWidenStepsOpts() { MaxNumRangeExtensions); } -namespace { +namespace llvm { -// 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 ValueLatticeElement::isConstant() and is intended to be used in the -// transition to ValueLatticeElement. -bool isConstant(const ValueLatticeElement &LV) { +bool SCCPSolver::isConstant(const ValueLatticeElement &LV) { return LV.isConstant() || (LV.isConstantRange() && LV.getConstantRange().isSingleElement()); } -// 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 -// ValueLatticeElement::isOverdefined() and is intended to be used in the -// transition to ValueLatticeElement. -bool isOverdefined(const ValueLatticeElement &LV) { - return !LV.isUnknownOrUndef() && !isConstant(LV); +bool SCCPSolver::isOverdefined(const ValueLatticeElement &LV) { + return !LV.isUnknownOrUndef() && !SCCPSolver::isConstant(LV); } -} // namespace +static bool canRemoveInstruction(Instruction *I) { + if (wouldInstructionBeTriviallyDead(I)) + return true; -namespace llvm { + // Some instructions can be handled but are rejected above. Catch + // those cases by falling through to here. + // TODO: Mark globals as being constant earlier, so + // TODO: wouldInstructionBeTriviallyDead() knows that atomic loads + // TODO: are safe to remove. + return isa<LoadInst>(I); +} + +bool SCCPSolver::tryToReplaceWithConstant(Value *V) { + Constant *Const = nullptr; + if (V->getType()->isStructTy()) { + std::vector<ValueLatticeElement> IVs = getStructLatticeValueFor(V); + if (llvm::any_of(IVs, isOverdefined)) + return false; + std::vector<Constant *> ConstVals; + auto *ST = cast<StructType>(V->getType()); + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { + ValueLatticeElement V = IVs[i]; + ConstVals.push_back(SCCPSolver::isConstant(V) + ? getConstant(V) + : UndefValue::get(ST->getElementType(i))); + } + Const = ConstantStruct::get(ST, ConstVals); + } else { + const ValueLatticeElement &IV = getLatticeValueFor(V); + if (isOverdefined(IV)) + return false; + + Const = SCCPSolver::isConstant(IV) ? getConstant(IV) + : UndefValue::get(V->getType()); + } + assert(Const && "Constant is nullptr here!"); + + // Replacing `musttail` instructions with constant breaks `musttail` invariant + // unless the call itself can be removed. + // Calls with "clang.arc.attachedcall" implicitly use the return value and + // those uses cannot be updated with a constant. + CallBase *CB = dyn_cast<CallBase>(V); + if (CB && ((CB->isMustTailCall() && + !canRemoveInstruction(CB)) || + CB->getOperandBundle(LLVMContext::OB_clang_arc_attachedcall))) { + Function *F = CB->getCalledFunction(); + + // Don't zap returns of the callee + if (F) + addToMustPreserveReturnsInFunctions(F); + + LLVM_DEBUG(dbgs() << " Can\'t treat the result of call " << *CB + << " as a constant\n"); + return false; + } + + LLVM_DEBUG(dbgs() << " Constant: " << *Const << " = " << *V << '\n'); + + // Replaces all of the uses of a variable with uses of the constant. + V->replaceAllUsesWith(Const); + return true; +} + +/// Try to replace signed instructions with their unsigned equivalent. +static bool replaceSignedInst(SCCPSolver &Solver, + SmallPtrSetImpl<Value *> &InsertedValues, + Instruction &Inst) { + // Determine if a signed value is known to be >= 0. + auto isNonNegative = [&Solver](Value *V) { + // If this value was constant-folded, it may not have a solver entry. + // Handle integers. Otherwise, return false. + if (auto *C = dyn_cast<Constant>(V)) { + auto *CInt = dyn_cast<ConstantInt>(C); + return CInt && !CInt->isNegative(); + } + const ValueLatticeElement &IV = Solver.getLatticeValueFor(V); + return IV.isConstantRange(/*UndefAllowed=*/false) && + IV.getConstantRange().isAllNonNegative(); + }; + + Instruction *NewInst = nullptr; + switch (Inst.getOpcode()) { + // Note: We do not fold sitofp -> uitofp here because that could be more + // expensive in codegen and may not be reversible in the backend. + case Instruction::SExt: { + // If the source value is not negative, this is a zext. + Value *Op0 = Inst.getOperand(0); + if (InsertedValues.count(Op0) || !isNonNegative(Op0)) + return false; + NewInst = new ZExtInst(Op0, Inst.getType(), "", &Inst); + break; + } + case Instruction::AShr: { + // If the shifted value is not negative, this is a logical shift right. + Value *Op0 = Inst.getOperand(0); + if (InsertedValues.count(Op0) || !isNonNegative(Op0)) + return false; + NewInst = BinaryOperator::CreateLShr(Op0, Inst.getOperand(1), "", &Inst); + break; + } + case Instruction::SDiv: + case Instruction::SRem: { + // If both operands are not negative, this is the same as udiv/urem. + Value *Op0 = Inst.getOperand(0), *Op1 = Inst.getOperand(1); + if (InsertedValues.count(Op0) || InsertedValues.count(Op1) || + !isNonNegative(Op0) || !isNonNegative(Op1)) + return false; + auto NewOpcode = Inst.getOpcode() == Instruction::SDiv ? Instruction::UDiv + : Instruction::URem; + NewInst = BinaryOperator::Create(NewOpcode, Op0, Op1, "", &Inst); + break; + } + default: + return false; + } + + // Wire up the new instruction and update state. + assert(NewInst && "Expected replacement instruction"); + NewInst->takeName(&Inst); + InsertedValues.insert(NewInst); + Inst.replaceAllUsesWith(NewInst); + Solver.removeLatticeValueFor(&Inst); + Inst.eraseFromParent(); + return true; +} + +bool SCCPSolver::simplifyInstsInBlock(BasicBlock &BB, + SmallPtrSetImpl<Value *> &InsertedValues, + Statistic &InstRemovedStat, + Statistic &InstReplacedStat) { + bool MadeChanges = false; + for (Instruction &Inst : make_early_inc_range(BB)) { + if (Inst.getType()->isVoidTy()) + continue; + if (tryToReplaceWithConstant(&Inst)) { + if (canRemoveInstruction(&Inst)) + Inst.eraseFromParent(); + + MadeChanges = true; + ++InstRemovedStat; + } else if (replaceSignedInst(*this, InsertedValues, Inst)) { + MadeChanges = true; + ++InstReplacedStat; + } + } + return MadeChanges; +} + +bool SCCPSolver::removeNonFeasibleEdges(BasicBlock *BB, DomTreeUpdater &DTU, + BasicBlock *&NewUnreachableBB) const { + SmallPtrSet<BasicBlock *, 8> FeasibleSuccessors; + bool HasNonFeasibleEdges = false; + for (BasicBlock *Succ : successors(BB)) { + if (isEdgeFeasible(BB, Succ)) + FeasibleSuccessors.insert(Succ); + else + HasNonFeasibleEdges = true; + } + + // All edges feasible, nothing to do. + if (!HasNonFeasibleEdges) + return false; + + // SCCP can only determine non-feasible edges for br, switch and indirectbr. + Instruction *TI = BB->getTerminator(); + assert((isa<BranchInst>(TI) || isa<SwitchInst>(TI) || + isa<IndirectBrInst>(TI)) && + "Terminator must be a br, switch or indirectbr"); + + if (FeasibleSuccessors.size() == 0) { + // Branch on undef/poison, replace with unreachable. + SmallPtrSet<BasicBlock *, 8> SeenSuccs; + SmallVector<DominatorTree::UpdateType, 8> Updates; + for (BasicBlock *Succ : successors(BB)) { + Succ->removePredecessor(BB); + if (SeenSuccs.insert(Succ).second) + Updates.push_back({DominatorTree::Delete, BB, Succ}); + } + TI->eraseFromParent(); + new UnreachableInst(BB->getContext(), BB); + DTU.applyUpdatesPermissive(Updates); + } else if (FeasibleSuccessors.size() == 1) { + // Replace with an unconditional branch to the only feasible successor. + BasicBlock *OnlyFeasibleSuccessor = *FeasibleSuccessors.begin(); + SmallVector<DominatorTree::UpdateType, 8> Updates; + bool HaveSeenOnlyFeasibleSuccessor = false; + for (BasicBlock *Succ : successors(BB)) { + if (Succ == OnlyFeasibleSuccessor && !HaveSeenOnlyFeasibleSuccessor) { + // Don't remove the edge to the only feasible successor the first time + // we see it. We still do need to remove any multi-edges to it though. + HaveSeenOnlyFeasibleSuccessor = true; + continue; + } + + Succ->removePredecessor(BB); + Updates.push_back({DominatorTree::Delete, BB, Succ}); + } + + BranchInst::Create(OnlyFeasibleSuccessor, BB); + TI->eraseFromParent(); + DTU.applyUpdatesPermissive(Updates); + } else if (FeasibleSuccessors.size() > 1) { + SwitchInstProfUpdateWrapper SI(*cast<SwitchInst>(TI)); + SmallVector<DominatorTree::UpdateType, 8> Updates; + + // If the default destination is unfeasible it will never be taken. Replace + // it with a new block with a single Unreachable instruction. + BasicBlock *DefaultDest = SI->getDefaultDest(); + if (!FeasibleSuccessors.contains(DefaultDest)) { + if (!NewUnreachableBB) { + NewUnreachableBB = + BasicBlock::Create(DefaultDest->getContext(), "default.unreachable", + DefaultDest->getParent(), DefaultDest); + new UnreachableInst(DefaultDest->getContext(), NewUnreachableBB); + } + + SI->setDefaultDest(NewUnreachableBB); + Updates.push_back({DominatorTree::Delete, BB, DefaultDest}); + Updates.push_back({DominatorTree::Insert, BB, NewUnreachableBB}); + } + + for (auto CI = SI->case_begin(); CI != SI->case_end();) { + if (FeasibleSuccessors.contains(CI->getCaseSuccessor())) { + ++CI; + continue; + } + + BasicBlock *Succ = CI->getCaseSuccessor(); + Succ->removePredecessor(BB); + Updates.push_back({DominatorTree::Delete, BB, Succ}); + SI.removeCase(CI); + // Don't increment CI, as we removed a case. + } + + DTU.applyUpdatesPermissive(Updates); + } else { + llvm_unreachable("Must have at least one feasible successor"); + } + return true; +} /// Helper class for SCCPSolver. This implements the instruction visitor and /// holds all the state. @@ -270,6 +501,8 @@ private: void handleCallOverdefined(CallBase &CB); void handleCallResult(CallBase &CB); void handleCallArguments(CallBase &CB); + void handleExtractOfWithOverflow(ExtractValueInst &EVI, + const WithOverflowInst *WO, unsigned Idx); private: friend class InstVisitor<SCCPInstVisitor>; @@ -339,6 +572,13 @@ public: return A->second.PredInfo->getPredicateInfoFor(I); } + const LoopInfo &getLoopInfo(Function &F) { + auto A = AnalysisResults.find(&F); + assert(A != AnalysisResults.end() && A->second.LI && + "Need LoopInfo analysis results for function."); + return *A->second.LI; + } + DomTreeUpdater getDTU(Function &F) { auto A = AnalysisResults.find(&F); assert(A != AnalysisResults.end() && "Need analysis results for function."); @@ -442,6 +682,7 @@ public: bool isStructLatticeConstant(Function *F, StructType *STy); Constant *getConstant(const ValueLatticeElement &LV) const; + ConstantRange getConstantRange(const ValueLatticeElement &LV, Type *Ty) const; SmallPtrSetImpl<Function *> &getArgumentTrackedFunctions() { return TrackingIncomingArguments; @@ -454,6 +695,26 @@ public: for (auto &BB : *F) BBExecutable.erase(&BB); } + + void solveWhileResolvedUndefsIn(Module &M) { + bool ResolvedUndefs = true; + while (ResolvedUndefs) { + solve(); + ResolvedUndefs = false; + for (Function &F : M) + ResolvedUndefs |= resolvedUndefsIn(F); + } + } + + void solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) { + bool ResolvedUndefs = true; + while (ResolvedUndefs) { + solve(); + ResolvedUndefs = false; + for (Function *F : WorkList) + ResolvedUndefs |= resolvedUndefsIn(*F); + } + } }; } // namespace llvm @@ -504,7 +765,7 @@ bool SCCPInstVisitor::isStructLatticeConstant(Function *F, StructType *STy) { const auto &It = TrackedMultipleRetVals.find(std::make_pair(F, i)); assert(It != TrackedMultipleRetVals.end()); ValueLatticeElement LV = It->second; - if (!isConstant(LV)) + if (!SCCPSolver::isConstant(LV)) return false; } return true; @@ -522,6 +783,15 @@ Constant *SCCPInstVisitor::getConstant(const ValueLatticeElement &LV) const { return nullptr; } +ConstantRange +SCCPInstVisitor::getConstantRange(const ValueLatticeElement &LV, + Type *Ty) const { + assert(Ty->isIntOrIntVectorTy() && "Should be int or int vector"); + if (LV.isConstantRange()) + return LV.getConstantRange(); + return ConstantRange::getFull(Ty->getScalarSizeInBits()); +} + void SCCPInstVisitor::markArgInFuncSpecialization( Function *F, const SmallVectorImpl<ArgInfo> &Args) { assert(!Args.empty() && "Specialization without arguments"); @@ -820,13 +1090,10 @@ void SCCPInstVisitor::visitCastInst(CastInst &I) { // Fold the constant as we build. Constant *C = ConstantFoldCastOperand(I.getOpcode(), OpC, I.getType(), DL); markConstant(&I, C); - } else if (I.getDestTy()->isIntegerTy()) { + } else if (I.getDestTy()->isIntegerTy() && + I.getSrcTy()->isIntOrIntVectorTy()) { auto &LV = getValueState(&I); - ConstantRange OpRange = - OpSt.isConstantRange() - ? OpSt.getConstantRange() - : ConstantRange::getFull( - I.getOperand(0)->getType()->getScalarSizeInBits()); + ConstantRange OpRange = getConstantRange(OpSt, I.getSrcTy()); Type *DestTy = I.getDestTy(); // Vectors where all elements have the same known constant range are treated @@ -846,6 +1113,33 @@ void SCCPInstVisitor::visitCastInst(CastInst &I) { markOverdefined(&I); } +void SCCPInstVisitor::handleExtractOfWithOverflow(ExtractValueInst &EVI, + const WithOverflowInst *WO, + unsigned Idx) { + Value *LHS = WO->getLHS(), *RHS = WO->getRHS(); + ValueLatticeElement L = getValueState(LHS); + ValueLatticeElement R = getValueState(RHS); + addAdditionalUser(LHS, &EVI); + addAdditionalUser(RHS, &EVI); + if (L.isUnknownOrUndef() || R.isUnknownOrUndef()) + return; // Wait to resolve. + + Type *Ty = LHS->getType(); + ConstantRange LR = getConstantRange(L, Ty); + ConstantRange RR = getConstantRange(R, Ty); + if (Idx == 0) { + ConstantRange Res = LR.binaryOp(WO->getBinaryOp(), RR); + mergeInValue(&EVI, ValueLatticeElement::getRange(Res)); + } else { + assert(Idx == 1 && "Index can only be 0 or 1"); + ConstantRange NWRegion = ConstantRange::makeGuaranteedNoWrapRegion( + WO->getBinaryOp(), RR, WO->getNoWrapKind()); + if (NWRegion.contains(LR)) + return (void)markConstant(&EVI, ConstantInt::getFalse(EVI.getType())); + markOverdefined(&EVI); + } +} + void SCCPInstVisitor::visitExtractValueInst(ExtractValueInst &EVI) { // If this returns a struct, mark all elements over defined, we don't track // structs in structs. @@ -864,6 +1158,8 @@ void SCCPInstVisitor::visitExtractValueInst(ExtractValueInst &EVI) { Value *AggVal = EVI.getAggregateOperand(); if (AggVal->getType()->isStructTy()) { unsigned i = *EVI.idx_begin(); + if (auto *WO = dyn_cast<WithOverflowInst>(AggVal)) + return handleExtractOfWithOverflow(EVI, WO, i); ValueLatticeElement EltVal = getStructValueState(AggVal, i); mergeInValue(getValueState(&EVI), &EVI, EltVal); } else { @@ -879,7 +1175,7 @@ void SCCPInstVisitor::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 (SCCPSolver::isOverdefined(ValueState[&IVI])) return (void)markOverdefined(&IVI); // If this has more than one index, we can't handle it, drive all results to @@ -950,14 +1246,14 @@ void SCCPInstVisitor::visitUnaryOperator(Instruction &I) { ValueLatticeElement &IV = ValueState[&I]; // resolvedUndefsIn might mark I as overdefined. Bail out, even if we would // discover a concrete value later. - if (isOverdefined(IV)) + if (SCCPSolver::isOverdefined(IV)) return (void)markOverdefined(&I); // If something is unknown/undef, wait for it to resolve. if (V0State.isUnknownOrUndef()) return; - if (isConstant(V0State)) + if (SCCPSolver::isConstant(V0State)) if (Constant *C = ConstantFoldUnaryOpOperand(I.getOpcode(), getConstant(V0State), DL)) return (void)markConstant(IV, &I, C); @@ -984,8 +1280,10 @@ void SCCPInstVisitor::visitBinaryOperator(Instruction &I) { // If either of the operands is a constant, try to fold it to a constant. // TODO: Use information from notconstant better. if ((V1State.isConstant() || V2State.isConstant())) { - Value *V1 = isConstant(V1State) ? getConstant(V1State) : I.getOperand(0); - Value *V2 = isConstant(V2State) ? getConstant(V2State) : I.getOperand(1); + Value *V1 = SCCPSolver::isConstant(V1State) ? getConstant(V1State) + : I.getOperand(0); + Value *V2 = SCCPSolver::isConstant(V2State) ? getConstant(V2State) + : I.getOperand(1); Value *R = simplifyBinOp(I.getOpcode(), V1, V2, SimplifyQuery(DL)); auto *C = dyn_cast_or_null<Constant>(R); if (C) { @@ -1005,13 +1303,8 @@ void SCCPInstVisitor::visitBinaryOperator(Instruction &I) { return markOverdefined(&I); // Try to simplify to a constant range. - ConstantRange A = ConstantRange::getFull(I.getType()->getScalarSizeInBits()); - ConstantRange B = ConstantRange::getFull(I.getType()->getScalarSizeInBits()); - if (V1State.isConstantRange()) - A = V1State.getConstantRange(); - if (V2State.isConstantRange()) - B = V2State.getConstantRange(); - + ConstantRange A = getConstantRange(V1State, I.getType()); + ConstantRange B = getConstantRange(V2State, I.getType()); ConstantRange R = A.binaryOp(cast<BinaryOperator>(&I)->getOpcode(), B); mergeInValue(&I, ValueLatticeElement::getRange(R)); @@ -1024,7 +1317,7 @@ void SCCPInstVisitor::visitBinaryOperator(Instruction &I) { void SCCPInstVisitor::visitCmpInst(CmpInst &I) { // Do not cache this lookup, getValueState calls later in the function might // invalidate the reference. - if (isOverdefined(ValueState[&I])) + if (SCCPSolver::isOverdefined(ValueState[&I])) return (void)markOverdefined(&I); Value *Op1 = I.getOperand(0); @@ -1035,11 +1328,8 @@ void SCCPInstVisitor::visitCmpInst(CmpInst &I) { auto V1State = getValueState(Op1); auto V2State = getValueState(Op2); - Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State); + Constant *C = V1State.getCompare(I.getPredicate(), I.getType(), V2State, DL); if (C) { - // TODO: getCompare() currently has incorrect handling for unknown/undef. - if (isa<UndefValue>(C)) - return; ValueLatticeElement CV; CV.markConstant(C); mergeInValue(&I, CV); @@ -1048,7 +1338,7 @@ void SCCPInstVisitor::visitCmpInst(CmpInst &I) { // If operands are still unknown, wait for it to resolve. if ((V1State.isUnknownOrUndef() || V2State.isUnknownOrUndef()) && - !isConstant(ValueState[&I])) + !SCCPSolver::isConstant(ValueState[&I])) return; markOverdefined(&I); @@ -1057,7 +1347,7 @@ void SCCPInstVisitor::visitCmpInst(CmpInst &I) { // Handle getelementptr instructions. If all operands are constants then we // can turn this into a getelementptr ConstantExpr. void SCCPInstVisitor::visitGetElementPtrInst(GetElementPtrInst &I) { - if (isOverdefined(ValueState[&I])) + if (SCCPSolver::isOverdefined(ValueState[&I])) return (void)markOverdefined(&I); SmallVector<Constant *, 8> Operands; @@ -1068,7 +1358,7 @@ void SCCPInstVisitor::visitGetElementPtrInst(GetElementPtrInst &I) { if (State.isUnknownOrUndef()) return; // Operands are not resolved yet. - if (isOverdefined(State)) + if (SCCPSolver::isOverdefined(State)) return (void)markOverdefined(&I); if (Constant *C = getConstant(State)) { @@ -1080,7 +1370,7 @@ void SCCPInstVisitor::visitGetElementPtrInst(GetElementPtrInst &I) { } Constant *Ptr = Operands[0]; - auto Indices = makeArrayRef(Operands.begin() + 1, Operands.end()); + auto Indices = ArrayRef(Operands.begin() + 1, Operands.end()); Constant *C = ConstantExpr::getGetElementPtr(I.getSourceElementType(), Ptr, Indices); markConstant(&I, C); @@ -1136,7 +1426,7 @@ void SCCPInstVisitor::visitLoadInst(LoadInst &I) { ValueLatticeElement &IV = ValueState[&I]; - if (isConstant(PtrVal)) { + if (SCCPSolver::isConstant(PtrVal)) { Constant *Ptr = getConstant(PtrVal); // load null is undefined. @@ -1191,17 +1481,19 @@ void SCCPInstVisitor::handleCallOverdefined(CallBase &CB) { for (const Use &A : CB.args()) { if (A.get()->getType()->isStructTy()) return markOverdefined(&CB); // Can't handle struct args. + if (A.get()->getType()->isMetadataTy()) + continue; // Carried in CB, not allowed in Operands. ValueLatticeElement State = getValueState(A); if (State.isUnknownOrUndef()) return; // Operands are not resolved yet. - if (isOverdefined(State)) + if (SCCPSolver::isOverdefined(State)) return (void)markOverdefined(&CB); - assert(isConstant(State) && "Unknown state!"); + assert(SCCPSolver::isConstant(State) && "Unknown state!"); Operands.push_back(getConstant(State)); } - if (isOverdefined(getValueState(&CB))) + if (SCCPSolver::isOverdefined(getValueState(&CB))) return (void)markOverdefined(&CB); // If we can constant fold this, mark the result of the call as a @@ -1219,8 +1511,7 @@ void SCCPInstVisitor::handleCallArguments(CallBase &CB) { // If this is a local function that doesn't have its address taken, mark its // entry block executable and merge in the actual arguments to the call into // the formal arguments of the function. - if (!TrackingIncomingArguments.empty() && - TrackingIncomingArguments.count(F)) { + if (TrackingIncomingArguments.count(F)) { markBlockExecutable(&F->front()); // Propagate information from this call site into the callee. @@ -1259,7 +1550,8 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) { const auto *PI = getPredicateInfoFor(&CB); assert(PI && "Missing predicate info for ssa.copy"); - const Optional<PredicateConstraint> &Constraint = PI->getConstraint(); + const std::optional<PredicateConstraint> &Constraint = + PI->getConstraint(); if (!Constraint) { mergeInValue(ValueState[&CB], &CB, CopyOfVal); return; @@ -1287,10 +1579,7 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) { // Combine range info for the original value with the new range from the // condition. - auto CopyOfCR = CopyOfVal.isConstantRange() - ? CopyOfVal.getConstantRange() - : ConstantRange::getFull( - DL.getTypeSizeInBits(CopyOf->getType())); + auto CopyOfCR = getConstantRange(CopyOfVal, CopyOf->getType()); auto NewCR = ImposedCR.intersectWith(CopyOfCR); // If the existing information is != x, do not use the information from // a chained predicate, as the != x information is more likely to be @@ -1308,9 +1597,10 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) { IV, &CB, ValueLatticeElement::getRange(NewCR, /*MayIncludeUndef*/ false)); return; - } else if (Pred == CmpInst::ICMP_EQ && CondVal.isConstant()) { + } else if (Pred == CmpInst::ICMP_EQ && + (CondVal.isConstant() || CondVal.isNotConstant())) { // For non-integer values or integer constant expressions, only - // propagate equal constants. + // propagate equal constants or not-constants. addAdditionalUser(OtherOp, &CB); mergeInValue(IV, &CB, CondVal); return; @@ -1332,11 +1622,7 @@ void SCCPInstVisitor::handleCallResult(CallBase &CB) { SmallVector<ConstantRange, 2> OpRanges; for (Value *Op : II->args()) { const ValueLatticeElement &State = getValueState(Op); - if (State.isConstantRange()) - OpRanges.push_back(State.getConstantRange()); - else - OpRanges.push_back( - ConstantRange::getFull(Op->getType()->getScalarSizeInBits())); + OpRanges.push_back(getConstantRange(State, Op->getType())); } ConstantRange Result = @@ -1498,6 +1784,9 @@ bool SCCPInstVisitor::resolvedUndefsIn(Function &F) { } } + LLVM_DEBUG(if (MadeChange) dbgs() + << "\nResolved undefs in " << F.getName() << '\n'); + return MadeChange; } @@ -1525,6 +1814,10 @@ const PredicateBase *SCCPSolver::getPredicateInfoFor(Instruction *I) { return Visitor->getPredicateInfoFor(I); } +const LoopInfo &SCCPSolver::getLoopInfo(Function &F) { + return Visitor->getLoopInfo(F); +} + DomTreeUpdater SCCPSolver::getDTU(Function &F) { return Visitor->getDTU(F); } void SCCPSolver::trackValueOfGlobalVariable(GlobalVariable *GV) { @@ -1557,6 +1850,15 @@ bool SCCPSolver::resolvedUndefsIn(Function &F) { return Visitor->resolvedUndefsIn(F); } +void SCCPSolver::solveWhileResolvedUndefsIn(Module &M) { + Visitor->solveWhileResolvedUndefsIn(M); +} + +void +SCCPSolver::solveWhileResolvedUndefsIn(SmallVectorImpl<Function *> &WorkList) { + Visitor->solveWhileResolvedUndefsIn(WorkList); +} + bool SCCPSolver::isBlockExecutable(BasicBlock *BB) const { return Visitor->isBlockExecutable(BB); } |