void BlockState::init(DSEContext &Ctx, bool Optimistic) { std::vector<LSLocation> &LV = Ctx.getLocationVault(); LocationNum = LV.size(); // For function that requires just 1 iteration of the data flow to converge // we set the initial state of BBWriteSetIn to 0. // // For other functions, the initial state of BBWriteSetIn should be all 1's. // Otherwise the dataflow solution could be too conservative. // // Consider this case, the dead store by var a = 10 before the loop will not // be eliminated if the BBWriteSetIn is set to 0 initially. // // var a = 10 // for _ in 0...1024 {} // a = 10 // // However, by doing so, we can only eliminate the dead stores after the // data flow stabilizes. // BBWriteSetIn.resize(LocationNum, Optimistic); BBWriteSetOut.resize(LocationNum, false); BBWriteSetMid.resize(LocationNum, false); // GenSet and KillSet initially empty. BBGenSet.resize(LocationNum, false); BBKillSet.resize(LocationNum, false); // MaxStoreSet is optimistically set to true initially. BBMaxStoreSet.resize(LocationNum, true); // DeallocateLocation initially empty. BBDeallocateLocation.resize(LocationNum, false); }
void BlockState::initStoreSetAtEndOfBlock(DSEContext &Ctx) { std::vector<LSLocation> &LocationVault = Ctx.getLocationVault(); // We set the store bit at the end of the basic block in which a stack // allocated location is deallocated. for (unsigned i = 0; i < LocationVault.size(); ++i) { // Turn on the store bit at the block which the stack slot is deallocated. if (auto *ASI = dyn_cast<AllocStackInst>(LocationVault[i].getBase())) { for (auto X : findDeallocStackInst(ASI)) { SILBasicBlock *DSIBB = X->getParent(); if (DSIBB != BB) continue; startTrackingLocation(BBDeallocateLocation, i); } } if (auto *ARI = dyn_cast<AllocRefInst>(LocationVault[i].getBase())) { if (!ARI->isAllocatingStack()) continue; for (auto X : findDeallocRefInst(ARI)) { SILBasicBlock *DSIBB = X->getParent(); if (DSIBB != BB) continue; startTrackingLocation(BBDeallocateLocation, i); } } } }