mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Merge remote-tracking branch 'origin/main' into rebranch
This commit is contained in:
@@ -97,7 +97,8 @@ class DCE {
|
||||
typedef llvm::DomTreeNodeBase<SILBasicBlock> PostDomTreeNode;
|
||||
|
||||
SILFunction *F;
|
||||
llvm::SmallPtrSet<SILNode *, 16> LiveValues;
|
||||
llvm::SmallPtrSet<SILArgument *, 16> LiveArguments;
|
||||
llvm::SmallPtrSet<SILInstruction *, 16> LiveInstructions;
|
||||
BasicBlockSet LiveBlocks;
|
||||
llvm::SmallVector<SILInstruction *, 64> Worklist;
|
||||
PostDominanceInfo *PDT;
|
||||
@@ -138,7 +139,8 @@ class DCE {
|
||||
void computeMinPredecessorLevels(PostDomTreeNode *root);
|
||||
void insertControllingInfo(SILBasicBlock *Block, unsigned Level);
|
||||
|
||||
void markValueLive(SILNode *V);
|
||||
void markValueLive(SILValue V);
|
||||
void markInstructionLive(SILInstruction *Inst);
|
||||
void markTerminatorArgsLive(SILBasicBlock *Pred, SILBasicBlock *Succ,
|
||||
size_t ArgIndex);
|
||||
void markControllingTerminatorsLive(SILBasicBlock *Block);
|
||||
@@ -173,32 +175,33 @@ public:
|
||||
|
||||
// Keep track of the fact that V is live and add it to our worklist
|
||||
// so that we can process the values it depends on.
|
||||
void DCE::markValueLive(SILNode *V) {
|
||||
V = V->getRepresentativeSILNodeInObject();
|
||||
if (LiveValues.count(V) || isa<SILUndef>(V))
|
||||
void DCE::markValueLive(SILValue V) {
|
||||
if (SILInstruction *inst = V->getDefiningInstruction())
|
||||
return markInstructionLive(inst);
|
||||
|
||||
if (isa<SILUndef>(V))
|
||||
return;
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Marking as live:\n");
|
||||
LLVM_DEBUG(V->dump());
|
||||
|
||||
LiveValues.insert(V);
|
||||
|
||||
if (auto *Def = dyn_cast<SILInstruction>(V)) {
|
||||
markControllingTerminatorsLive(Def->getParent());
|
||||
Worklist.push_back(Def);
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: MultiValueInstruction
|
||||
|
||||
assert(isa<SILArgument>(V) &&
|
||||
"Only expected instructions and arguments!");
|
||||
LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *V);
|
||||
|
||||
auto *Arg = cast<SILArgument>(V);
|
||||
if (!LiveArguments.insert(Arg).second)
|
||||
return;
|
||||
|
||||
markControllingTerminatorsLive(Arg->getParent());
|
||||
propagateLiveBlockArgument(Arg);
|
||||
}
|
||||
|
||||
void DCE::markInstructionLive(SILInstruction *Inst) {
|
||||
if (!LiveInstructions.insert(Inst).second)
|
||||
return;
|
||||
|
||||
LLVM_DEBUG(llvm::dbgs() << "Marking as live: " << *Inst);
|
||||
|
||||
markControllingTerminatorsLive(Inst->getParent());
|
||||
Worklist.push_back(Inst);
|
||||
}
|
||||
|
||||
/// Gets the producing instruction of a cond_fail condition. Currently these
|
||||
/// are overflow builtins but may be extended to other instructions in the
|
||||
/// future.
|
||||
@@ -228,7 +231,7 @@ void DCE::markLive() {
|
||||
if (auto *Prod = getProducer(cast<CondFailInst>(&I))) {
|
||||
addReverseDependency(Prod, &I);
|
||||
} else {
|
||||
markValueLive(&I);
|
||||
markInstructionLive(&I);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -237,7 +240,7 @@ void DCE::markLive() {
|
||||
if (!Op->getType().isAddress()) {
|
||||
addReverseDependency(Op, &I);
|
||||
} else {
|
||||
markValueLive(&I);
|
||||
markInstructionLive(&I);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -255,7 +258,7 @@ void DCE::markLive() {
|
||||
}
|
||||
default:
|
||||
if (seemsUseful(&I))
|
||||
markValueLive(&I);
|
||||
markInstructionLive(&I);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -284,7 +287,7 @@ void DCE::markTerminatorArgsLive(SILBasicBlock *Pred,
|
||||
|
||||
// If the arguments are live, we need to keep the terminator that
|
||||
// delivers those arguments.
|
||||
markValueLive(Term);
|
||||
markInstructionLive(Term);
|
||||
|
||||
switch (Term->getTermKind()) {
|
||||
case TermKind::ReturnInst:
|
||||
@@ -345,11 +348,11 @@ void DCE::propagateLiveBlockArgument(SILArgument *Arg) {
|
||||
// is in reverse direction: Only if its definition (the Arg) is alive, also
|
||||
// the debug_value instruction is alive.
|
||||
for (Operand *DU : getDebugUses(Arg))
|
||||
markValueLive(DU->getUser());
|
||||
markInstructionLive(DU->getUser());
|
||||
|
||||
// Mark all reverse dependencies on the Arg live
|
||||
for (auto *depInst : ReverseDependencies.lookup(Arg)) {
|
||||
markValueLive(depInst);
|
||||
markInstructionLive(depInst);
|
||||
}
|
||||
|
||||
auto *Block = Arg->getParent();
|
||||
@@ -371,14 +374,14 @@ void DCE::propagateLiveness(SILInstruction *I) {
|
||||
// debug_value instruction is alive.
|
||||
for (auto result : I->getResults())
|
||||
for (Operand *DU : getDebugUses(result))
|
||||
markValueLive(DU->getUser());
|
||||
markInstructionLive(DU->getUser());
|
||||
|
||||
// Handle all other reverse-dependency instructions, like cond_fail,
|
||||
// fix_lifetime, destroy_value, etc. Only if the definition is alive, the
|
||||
// user itself is alive.
|
||||
for (auto res : I->getResults()) {
|
||||
for (auto *depInst : ReverseDependencies.lookup(res)) {
|
||||
markValueLive(depInst);
|
||||
markInstructionLive(depInst);
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -448,7 +451,7 @@ void DCE::replaceBranchWithJump(SILInstruction *Inst, SILBasicBlock *Block) {
|
||||
std::vector<SILValue> Args;
|
||||
auto E = Block->args_end();
|
||||
for (auto A = Block->args_begin(); A != E; ++A) {
|
||||
assert(!LiveValues.count(*A) && "Unexpected live block argument!");
|
||||
assert(!LiveArguments.count(*A) && "Unexpected live block argument!");
|
||||
Args.push_back(SILUndef::get((*A)->getType(), *(*A)->getFunction()));
|
||||
}
|
||||
Branch =
|
||||
@@ -462,8 +465,12 @@ void DCE::replaceBranchWithJump(SILInstruction *Inst, SILBasicBlock *Block) {
|
||||
}
|
||||
|
||||
void DCE::endLifetimeOfLiveValue(SILValue value, SILInstruction *insertPt) {
|
||||
if (!LiveValues.count(value->getRepresentativeSILNodeInObject())) {
|
||||
return;
|
||||
if (SILInstruction *inst = value->getDefiningInstruction()) {
|
||||
if (!LiveInstructions.count(inst))
|
||||
return;
|
||||
} else if (auto *arg = dyn_cast<SILArgument>(value)) {
|
||||
if (!LiveArguments.count(arg))
|
||||
return;
|
||||
}
|
||||
SILBuilderWithScope builder(insertPt);
|
||||
if (value.getOwnershipKind() == OwnershipKind::Owned) {
|
||||
@@ -483,7 +490,7 @@ bool DCE::removeDead() {
|
||||
for (auto &BB : *F) {
|
||||
for (unsigned i = 0; i < BB.getArguments().size();) {
|
||||
auto *arg = BB.getArgument(i);
|
||||
if (LiveValues.count(arg)) {
|
||||
if (LiveArguments.count(arg)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
@@ -509,7 +516,7 @@ bool DCE::removeDead() {
|
||||
auto insertPt = getInsertAfterPoint(arg).getValue();
|
||||
SILBuilderWithScope builder(insertPt);
|
||||
auto *destroy = builder.createDestroyValue(insertPt->getLoc(), arg);
|
||||
LiveValues.insert(destroy->getRepresentativeSILNodeInObject());
|
||||
LiveInstructions.insert(destroy);
|
||||
}
|
||||
i++;
|
||||
Changed = true;
|
||||
@@ -534,7 +541,7 @@ bool DCE::removeDead() {
|
||||
for (auto I = BB.begin(), E = BB.end(); I != E; ) {
|
||||
auto *Inst = &*I;
|
||||
++I;
|
||||
if (LiveValues.count(Inst) || isa<BranchInst>(Inst))
|
||||
if (LiveInstructions.count(Inst) || isa<BranchInst>(Inst))
|
||||
continue;
|
||||
|
||||
// We want to replace dead terminators with unconditional branches to
|
||||
@@ -770,7 +777,7 @@ void DCE::markControllingTerminatorsLive(SILBasicBlock *Block) {
|
||||
collectControllingBlocks(Block, ControllingBlocks);
|
||||
|
||||
for (auto BB : ControllingBlocks)
|
||||
markValueLive(BB->getTerminator());
|
||||
markInstructionLive(BB->getTerminator());
|
||||
}
|
||||
|
||||
class DCEPass : public SILFunctionTransform {
|
||||
|
||||
@@ -663,15 +663,15 @@ void MemoryToRegisters::removeSingleBlockAllocation(AllocStackInst *ASI) {
|
||||
}
|
||||
|
||||
// Remove dead address instructions that may be uses of the allocation.
|
||||
SILNode *Node = Inst;
|
||||
while (isa<StructElementAddrInst>(Node) ||
|
||||
isa<TupleElementAddrInst>(Node) ||
|
||||
isa<UncheckedAddrCastInst>(Node)) {
|
||||
auto *I = cast<SingleValueInstruction>(Node);
|
||||
if (!I->use_empty()) break;
|
||||
Node = I->getOperand(0);
|
||||
I->eraseFromParent();
|
||||
auto *addrInst = dyn_cast<SingleValueInstruction>(Inst);
|
||||
while (addrInst && addrInst->use_empty() &&
|
||||
(isa<StructElementAddrInst>(addrInst) ||
|
||||
isa<TupleElementAddrInst>(addrInst) ||
|
||||
isa<UncheckedAddrCastInst>(addrInst))) {
|
||||
SILValue op = addrInst->getOperand(0);
|
||||
addrInst->eraseFromParent();
|
||||
++NumInstRemoved;
|
||||
addrInst = dyn_cast<SingleValueInstruction>(op);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user