aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/SCCPSolver.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Transforms/Utils/SCCPSolver.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/Transforms/Utils/SCCPSolver.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/SCCPSolver.cpp422
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);
}