|
@@ -44,94 +44,6 @@ static void RemoveIncomingValueFrom(BasicBlock *SuccBB, BasicBlock *BB) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-namespace {
|
|
|
-
|
|
|
-struct AllocaDeleter {
|
|
|
- SmallVector<Value *, 10> WorkList;
|
|
|
- std::unordered_set<Value *> Seen;
|
|
|
-
|
|
|
- void Add(Value *V) {
|
|
|
- if (!Seen.count(V)) {
|
|
|
- Seen.insert(V);
|
|
|
- WorkList.push_back(V);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- bool TryDeleteUnusedAlloca(AllocaInst *AI) {
|
|
|
- Seen.clear();
|
|
|
- WorkList.clear();
|
|
|
-
|
|
|
- Add(AI);
|
|
|
- while (WorkList.size()) {
|
|
|
- Value *V = WorkList.pop_back_val();
|
|
|
- // Keep adding users if we encounter one of these.
|
|
|
- // None of them imply the alloca is being read.
|
|
|
- if (isa<GEPOperator>(V) ||
|
|
|
- isa<BitCastOperator>(V) ||
|
|
|
- isa<AllocaInst>(V) ||
|
|
|
- isa<StoreInst>(V))
|
|
|
- {
|
|
|
- for (User *U : V->users())
|
|
|
- Add(U);
|
|
|
- }
|
|
|
- // If it's anything else, we'll assume it's reading the
|
|
|
- // alloca. Give up.
|
|
|
- else {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (!Seen.size())
|
|
|
- return false;
|
|
|
-
|
|
|
- // Delete all the instructions associated with the
|
|
|
- // alloca.
|
|
|
- for (Value *V : Seen) {
|
|
|
- Instruction *I = dyn_cast<Instruction>(V);
|
|
|
- if (I) {
|
|
|
- I->dropAllReferences();
|
|
|
- }
|
|
|
- }
|
|
|
- for (Value *V : Seen) {
|
|
|
- Instruction *I = dyn_cast<Instruction>(V);
|
|
|
- if (I) {
|
|
|
- I->eraseFromParent();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- return true;
|
|
|
- }
|
|
|
-};
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-// Finds all allocas that only have stores and delete them.
|
|
|
-// These allocas hold on to values that do not contribute to the
|
|
|
-// shader's results.
|
|
|
-static bool DeleteDeadAllocas(Function &F) {
|
|
|
- if (F.empty())
|
|
|
- return false;
|
|
|
-
|
|
|
- AllocaDeleter Deleter;
|
|
|
- BasicBlock &Entry = *F.begin();
|
|
|
- bool Changed = false;
|
|
|
-
|
|
|
- while (1) {
|
|
|
- bool LocalChanged = false;
|
|
|
- for (auto it = Entry.begin(), end = Entry.end(); it != end;) {
|
|
|
- AllocaInst *AI = dyn_cast<AllocaInst>(&*(it++));
|
|
|
- if (!AI)
|
|
|
- continue;
|
|
|
- LocalChanged |= Deleter.TryDeleteUnusedAlloca(AI);
|
|
|
- }
|
|
|
- Changed |= LocalChanged;
|
|
|
- if (!LocalChanged)
|
|
|
- break;
|
|
|
- }
|
|
|
-
|
|
|
- return Changed;
|
|
|
-}
|
|
|
-
|
|
|
struct DeadBlockDeleter {
|
|
|
bool Run(Function &F, DxilValueCache *DVC);
|
|
|
|
|
@@ -405,7 +317,7 @@ struct DxilRemoveDeadBlocks : public FunctionPass {
|
|
|
bool runOnFunction(Function &F) override {
|
|
|
DxilValueCache *DVC = &getAnalysis<DxilValueCache>();
|
|
|
bool Changed = false;
|
|
|
- Changed |= DeleteDeadAllocas(F);
|
|
|
+ Changed |= hlsl::dxilutil::DeleteDeadAllocas(F);
|
|
|
Changed |= DeleteDeadBlocks(F, DVC);
|
|
|
Changed |= DeleteNonContributingValues(F, DVC);
|
|
|
return Changed;
|