aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp198
1 files changed, 103 insertions, 95 deletions
diff --git a/contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp b/contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp
index 1af40e2c4e62..19ac9526b5f8 100644
--- a/contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp
+++ b/contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp
@@ -774,7 +774,7 @@ private:
// Symbolic evaluation.
ExprResult checkExprResults(Expression *, Instruction *, Value *) const;
- ExprResult performSymbolicEvaluation(Value *,
+ ExprResult performSymbolicEvaluation(Instruction *,
SmallPtrSetImpl<Value *> &) const;
const Expression *performSymbolicLoadCoercion(Type *, Value *, LoadInst *,
Instruction *,
@@ -1904,7 +1904,7 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
LastPredInfo = PI;
// In phi of ops cases, we may have predicate info that we are evaluating
// in a different context.
- if (!DT->dominates(PBranch->To, getBlockForValue(I)))
+ if (!DT->dominates(PBranch->To, I->getParent()))
continue;
// TODO: Along the false edge, we may know more things too, like
// icmp of
@@ -1961,95 +1961,88 @@ NewGVN::ExprResult NewGVN::performSymbolicCmpEvaluation(Instruction *I) const {
return createExpression(I);
}
-// Substitute and symbolize the value before value numbering.
+// Substitute and symbolize the instruction before value numbering.
NewGVN::ExprResult
-NewGVN::performSymbolicEvaluation(Value *V,
+NewGVN::performSymbolicEvaluation(Instruction *I,
SmallPtrSetImpl<Value *> &Visited) const {
const Expression *E = nullptr;
- if (auto *C = dyn_cast<Constant>(V))
- E = createConstantExpression(C);
- else if (isa<Argument>(V) || isa<GlobalVariable>(V)) {
- E = createVariableExpression(V);
- } else {
- // TODO: memory intrinsics.
- // TODO: Some day, we should do the forward propagation and reassociation
- // parts of the algorithm.
- auto *I = cast<Instruction>(V);
- switch (I->getOpcode()) {
- case Instruction::ExtractValue:
- case Instruction::InsertValue:
- E = performSymbolicAggrValueEvaluation(I);
- break;
- case Instruction::PHI: {
- SmallVector<ValPair, 3> Ops;
- auto *PN = cast<PHINode>(I);
- for (unsigned i = 0; i < PN->getNumOperands(); ++i)
- Ops.push_back({PN->getIncomingValue(i), PN->getIncomingBlock(i)});
- // Sort to ensure the invariant createPHIExpression requires is met.
- sortPHIOps(Ops);
- E = performSymbolicPHIEvaluation(Ops, I, getBlockForValue(I));
- } break;
- case Instruction::Call:
- return performSymbolicCallEvaluation(I);
- break;
- case Instruction::Store:
- E = performSymbolicStoreEvaluation(I);
- break;
- case Instruction::Load:
- E = performSymbolicLoadEvaluation(I);
- break;
- case Instruction::BitCast:
- case Instruction::AddrSpaceCast:
- case Instruction::Freeze:
- return createExpression(I);
- break;
- case Instruction::ICmp:
- case Instruction::FCmp:
- return performSymbolicCmpEvaluation(I);
- break;
- case Instruction::FNeg:
- case Instruction::Add:
- case Instruction::FAdd:
- case Instruction::Sub:
- case Instruction::FSub:
- case Instruction::Mul:
- case Instruction::FMul:
- case Instruction::UDiv:
- case Instruction::SDiv:
- case Instruction::FDiv:
- case Instruction::URem:
- case Instruction::SRem:
- case Instruction::FRem:
- case Instruction::Shl:
- case Instruction::LShr:
- case Instruction::AShr:
- case Instruction::And:
- case Instruction::Or:
- case Instruction::Xor:
- case Instruction::Trunc:
- case Instruction::ZExt:
- case Instruction::SExt:
- case Instruction::FPToUI:
- case Instruction::FPToSI:
- case Instruction::UIToFP:
- case Instruction::SIToFP:
- case Instruction::FPTrunc:
- case Instruction::FPExt:
- case Instruction::PtrToInt:
- case Instruction::IntToPtr:
- case Instruction::Select:
- case Instruction::ExtractElement:
- case Instruction::InsertElement:
- case Instruction::GetElementPtr:
- return createExpression(I);
- break;
- case Instruction::ShuffleVector:
- // FIXME: Add support for shufflevector to createExpression.
- return ExprResult::none();
- default:
- return ExprResult::none();
- }
+ // TODO: memory intrinsics.
+ // TODO: Some day, we should do the forward propagation and reassociation
+ // parts of the algorithm.
+ switch (I->getOpcode()) {
+ case Instruction::ExtractValue:
+ case Instruction::InsertValue:
+ E = performSymbolicAggrValueEvaluation(I);
+ break;
+ case Instruction::PHI: {
+ SmallVector<ValPair, 3> Ops;
+ auto *PN = cast<PHINode>(I);
+ for (unsigned i = 0; i < PN->getNumOperands(); ++i)
+ Ops.push_back({PN->getIncomingValue(i), PN->getIncomingBlock(i)});
+ // Sort to ensure the invariant createPHIExpression requires is met.
+ sortPHIOps(Ops);
+ E = performSymbolicPHIEvaluation(Ops, I, getBlockForValue(I));
+ } break;
+ case Instruction::Call:
+ return performSymbolicCallEvaluation(I);
+ break;
+ case Instruction::Store:
+ E = performSymbolicStoreEvaluation(I);
+ break;
+ case Instruction::Load:
+ E = performSymbolicLoadEvaluation(I);
+ break;
+ case Instruction::BitCast:
+ case Instruction::AddrSpaceCast:
+ case Instruction::Freeze:
+ return createExpression(I);
+ break;
+ case Instruction::ICmp:
+ case Instruction::FCmp:
+ return performSymbolicCmpEvaluation(I);
+ break;
+ case Instruction::FNeg:
+ case Instruction::Add:
+ case Instruction::FAdd:
+ case Instruction::Sub:
+ case Instruction::FSub:
+ case Instruction::Mul:
+ case Instruction::FMul:
+ case Instruction::UDiv:
+ case Instruction::SDiv:
+ case Instruction::FDiv:
+ case Instruction::URem:
+ case Instruction::SRem:
+ case Instruction::FRem:
+ case Instruction::Shl:
+ case Instruction::LShr:
+ case Instruction::AShr:
+ case Instruction::And:
+ case Instruction::Or:
+ case Instruction::Xor:
+ case Instruction::Trunc:
+ case Instruction::ZExt:
+ case Instruction::SExt:
+ case Instruction::FPToUI:
+ case Instruction::FPToSI:
+ case Instruction::UIToFP:
+ case Instruction::SIToFP:
+ case Instruction::FPTrunc:
+ case Instruction::FPExt:
+ case Instruction::PtrToInt:
+ case Instruction::IntToPtr:
+ case Instruction::Select:
+ case Instruction::ExtractElement:
+ case Instruction::InsertElement:
+ case Instruction::GetElementPtr:
+ return createExpression(I);
+ break;
+ case Instruction::ShuffleVector:
+ // FIXME: Add support for shufflevector to createExpression.
+ return ExprResult::none();
+ default:
+ return ExprResult::none();
}
return ExprResult::some(E);
}
@@ -2772,6 +2765,9 @@ NewGVN::makePossiblePHIOfOps(Instruction *I,
// Clone the instruction, create an expression from it that is
// translated back into the predecessor, and see if we have a leader.
Instruction *ValueOp = I->clone();
+ // Emit the temporal instruction in the predecessor basic block where the
+ // corresponding value is defined.
+ ValueOp->insertBefore(PredBB->getTerminator());
if (MemAccess)
TempToMemory.insert({ValueOp, MemAccess});
bool SafeForPHIOfOps = true;
@@ -2801,7 +2797,7 @@ NewGVN::makePossiblePHIOfOps(Instruction *I,
FoundVal = !SafeForPHIOfOps ? nullptr
: findLeaderForInst(ValueOp, Visited,
MemAccess, I, PredBB);
- ValueOp->deleteValue();
+ ValueOp->eraseFromParent();
if (!FoundVal) {
// We failed to find a leader for the current ValueOp, but this might
// change in case of the translated operands change.
@@ -3542,7 +3538,7 @@ struct NewGVN::ValueDFS {
// the second. We only want it to be less than if the DFS orders are equal.
//
// Each LLVM instruction only produces one value, and thus the lowest-level
- // differentiator that really matters for the stack (and what we use as as a
+ // differentiator that really matters for the stack (and what we use as a
// replacement) is the local dfs number.
// Everything else in the structure is instruction level, and only affects
// the order in which we will replace operands of a given instruction.
@@ -4034,9 +4030,18 @@ bool NewGVN::eliminateInstructions(Function &F) {
// because stores are put in terms of the stored value, we skip
// stored values here. If the stored value is really dead, it will
// still be marked for deletion when we process it in its own class.
- if (!EliminationStack.empty() && Def != EliminationStack.back() &&
- isa<Instruction>(Def) && !FromStore)
- markInstructionForDeletion(cast<Instruction>(Def));
+ auto *DefI = dyn_cast<Instruction>(Def);
+ if (!EliminationStack.empty() && DefI && !FromStore) {
+ Value *DominatingLeader = EliminationStack.back();
+ if (DominatingLeader != Def) {
+ // Even if the instruction is removed, we still need to update
+ // flags/metadata due to downstreams users of the leader.
+ if (!match(DefI, m_Intrinsic<Intrinsic::ssa_copy>()))
+ patchReplacementInstruction(DefI, DominatingLeader);
+
+ markInstructionForDeletion(DefI);
+ }
+ }
continue;
}
// At this point, we know it is a Use we are trying to possibly
@@ -4095,9 +4100,12 @@ bool NewGVN::eliminateInstructions(Function &F) {
// For copy instructions, we use their operand as a leader,
// which means we remove a user of the copy and it may become dead.
if (isSSACopy) {
- unsigned &IIUseCount = UseCounts[II];
- if (--IIUseCount == 0)
- ProbablyDead.insert(II);
+ auto It = UseCounts.find(II);
+ if (It != UseCounts.end()) {
+ unsigned &IIUseCount = It->second;
+ if (--IIUseCount == 0)
+ ProbablyDead.insert(II);
+ }
}
++LeaderUseCount;
AnythingReplaced = true;