void DSEContext::processDebugValueAddrInst(SILInstruction *I, DSEKind Kind) { BlockState *S = getBlockState(I); SILValue Mem = cast<DebugValueAddrInst>(I)->getOperand(); // Are we building genset and killset. if (isBuildingGenKillSet(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBMaxStoreSet.test(i)) continue; if (AA->isNoAlias(Mem, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBGenSet, i); S->startTrackingLocation(S->BBKillSet, i); } return; } // Are we performing dead store elimination. if (isPerformingDSE(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->isTrackingLSLocation(S->BBWriteSetOut, i)) continue; if (AA->isNoAlias(Mem, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBWriteSetOut, i); } return; } llvm_unreachable("Unknown DSE compute kind"); }
void DSEContext::processUnknownReadInst(SILInstruction *I, DSEKind Kind) { BlockState *S = getBlockState(I); // Are we building genset and killset. if (isBuildingGenKillSet(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBMaxStoreSet.test(i)) continue; if (!AA->mayReadFromMemory(I, LocationVault[i].getBase())) continue; // Update the genset and kill set. S->startTrackingLocation(S->BBKillSet, i); S->stopTrackingLocation(S->BBGenSet, i); } return; } // Are we performing dead store elimination. if (isPerformingDSE(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->isTrackingLSLocation(S->BBWriteSetOut, i)) continue; if (!AA->mayReadFromMemory(I, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBWriteSetOut, i); } return; } llvm_unreachable("Unknown DSE compute kind"); }
void DSEContext::invalidateLSLocationBase(SILInstruction *I, DSEKind Kind) { // If this instruction defines the base of a location, then we need to // invalidate any locations with the same base. BlockState *S = getBlockState(I); // Are we building genset and killset. if (isBuildingGenKillSet(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (LocationVault[i].getBase().getDef() != I) continue; S->startTrackingLocation(S->BBKillSet, i); S->stopTrackingLocation(S->BBGenSet, i); } return; } // Are we performing dead store elimination. if (isPerformingDSE(Kind)) { for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBWriteSetOut.test(i)) continue; if (LocationVault[i].getBase().getDef() != I) continue; S->stopTrackingLocation(S->BBWriteSetOut, i); } return; } llvm_unreachable("Unknown DSE compute kind"); }
void DSEContext::invalidateLSLocationBaseForGenKillSet(SILInstruction *I) { BlockState *S = getBlockState(I); for (unsigned i = 0; i < S->LocationNum; ++i) { if (LocationVault[i].getBase() != I) continue; S->startTrackingLocation(S->BBKillSet, i); S->stopTrackingLocation(S->BBGenSet, i); } }
void DSEContext::processUnknownReadInstForDSE(SILInstruction *I) { BlockState *S = getBlockState(I); for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->isTrackingLocation(S->BBWriteSetMid, i)) continue; if (!AA->mayReadFromMemory(I, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBWriteSetMid, i); } }
void DSEContext::invalidateLSLocationBaseForDSE(SILInstruction *I) { BlockState *S = getBlockState(I); for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBWriteSetMid.test(i)) continue; if (LocationVault[i].getBase() != I) continue; S->stopTrackingLocation(S->BBWriteSetMid, i); } }
void DSEContext::processDebugValueAddrInstForDSE(SILInstruction *I) { BlockState *S = getBlockState(I); SILValue Mem = cast<DebugValueAddrInst>(I)->getOperand(); for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->isTrackingLocation(S->BBWriteSetMid, i)) continue; if (AA->isNoAlias(Mem, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBWriteSetMid, i); } }
void DSEContext::processDebugValueAddrInstForGenKillSet(SILInstruction *I) { BlockState *S = getBlockState(I); SILValue Mem = cast<DebugValueAddrInst>(I)->getOperand(); for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBMaxStoreSet.test(i)) continue; if (AA->isNoAlias(Mem, LocationVault[i].getBase())) continue; S->stopTrackingLocation(S->BBGenSet, i); S->startTrackingLocation(S->BBKillSet, i); } }
void DSEContext::processUnknownReadInstForGenKillSet(SILInstruction *I) { BlockState *S = getBlockState(I); for (unsigned i = 0; i < S->LocationNum; ++i) { if (!S->BBMaxStoreSet.test(i)) continue; if (!AA->mayReadFromMemory(I, LocationVault[i].getBase())) continue; // Update the genset and kill set. S->startTrackingLocation(S->BBKillSet, i); S->stopTrackingLocation(S->BBGenSet, i); } }
bool DSEContext::processBasicBlockWithGenKillSet(SILBasicBlock *BB) { // Compute the BBWriteSetOut at the end of the basic block. mergeSuccessorLiveIns(BB); // Compute the BBWriteSet at the beginning of the basic block. BlockState *S = getBlockState(BB); S->BBWriteSetMid = S->BBWriteSetOut; S->BBWriteSetMid.reset(S->BBKillSet); S->BBWriteSetMid |= S->BBGenSet; // If BBWriteSetIn changes, then keep iterating until reached a fixed point. return S->updateBBWriteSetIn(S->BBWriteSetMid); }
bool DSEContext::processBasicBlockWithGenKillSet(SILBasicBlock *BB) { // Compute the BBWriteSetOut at the end of the basic block. mergeSuccessorStates(BB); // Compute the BBWriteSetOut at the beginning of the basic block. BlockState *S = getBlockState(BB); llvm::BitVector T = S->BBKillSet; S->BBWriteSetOut &= T.flip(); S->BBWriteSetOut |= S->BBGenSet; // If BBWriteSetIn changes, then keep iterating until reached a fixed point. return S->updateBBWriteSetIn(); }
void DSEContext::mergeSuccessorStates(SILBasicBlock *BB) { // First, clear the BBWriteSetOut for the current basicblock. BlockState *C = getBlockState(BB); C->BBWriteSetOut.reset(); // If basic block has no successor, then all local writes can be considered // dead for block with no successor. if (BB->succ_empty()) { if (DisableLocalStoreDSE) return; for (unsigned i = 0; i < LocationVault.size(); ++i) { if (!LocationVault[i].isNonEscapingLocalLSLocation()) continue; C->startTrackingLocation(C->BBWriteSetOut, i); } return; } // Use the first successor as the base condition. auto Iter = BB->succ_begin(); C->BBWriteSetOut = getBlockState(*Iter)->BBWriteSetIn; /// Merge/intersection is very frequently performed, so it is important to make /// it as cheap as possible. /// /// To do so, we canonicalize LSLocations, i.e. traced back to the underlying /// object. Therefore, no need to do a O(N^2) comparison to figure out what is /// dead along all successors. /// /// NOTE: Canonicalization does not solve the problem entirely. i.e. it is /// still possible that 2 LSLocations with different bases that happen to be /// the same object and field. In such case, we would miss a dead store /// opportunity. But this happens less often with canonicalization. Iter = std::next(Iter); for (auto EndIter = BB->succ_end(); Iter != EndIter; ++Iter) { C->BBWriteSetOut &= getBlockState(*Iter)->BBWriteSetIn; } }