diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp')
| -rw-r--r-- | contrib/llvm-project/llvm/lib/Transforms/Scalar/NewGVN.cpp | 198 |
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; |
