Pārlūkot izejas kodu

Cleaning up unused alloca. (#2558)

* Cleaning up unused alloca

* Slight improvements

* Use single list. Added memcpy

* Made everything simpler
Adam Yang 5 gadi atpakaļ
vecāks
revīzija
3a870f2c08

+ 65 - 0
lib/Transforms/Scalar/DxilLoopUnroll.cpp

@@ -72,6 +72,7 @@
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IR/PredIteratorCache.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/ADT/SetVector.h"
@@ -1163,13 +1164,77 @@ public:
     return false;
   }
 
+  // Collect and remove all instructions that use AI, but
+  // give up if there are anything other than store, bitcast,
+  // memcpy, or GEP.
+  static bool TryRemoveUnusedAlloca(AllocaInst *AI) {
+    std::vector<Instruction *> WorkList;
+
+    WorkList.push_back(AI);
+
+    for (unsigned i = 0; i < WorkList.size(); i++) {
+      Instruction *I = WorkList[i];
+
+      for (User *U : I->users()) {
+        Instruction *UI = cast<Instruction>(U);
+
+        unsigned Opcode = UI->getOpcode();
+        if (Opcode == Instruction::BitCast ||
+          Opcode == Instruction::GetElementPtr ||
+          Opcode == Instruction::Store)
+        {
+          WorkList.push_back(UI);
+        }
+        else if (MemCpyInst *MC = dyn_cast<MemCpyInst>(UI)) {
+          if (MC->getSource() == I) { // MC reads from our alloca
+            return false;
+          }
+          WorkList.push_back(UI);
+        }
+        else { // Load? PHINode? Assume read.
+          return false;
+        }
+      }
+    }
+
+    // Remove all instructions
+    for (auto It = WorkList.rbegin(), E = WorkList.rend(); It != E; It++) {
+      Instruction *I = *It;
+      I->eraseFromParent();
+    }
+
+    return true;
+  }
+
+  static bool RemoveAllUnusedAllocas(Function &F) {
+    std::vector<AllocaInst *> Allocas;
+    BasicBlock &EntryBB = *F.begin();
+    for (auto It = EntryBB.begin(), E = EntryBB.end(); It != E;) {
+      Instruction &I = *(It++);
+      if (AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
+        Allocas.push_back(AI);
+      }
+    }
+
+    bool Changed = false;
+    for (AllocaInst *AI : Allocas) {
+      Changed |= TryRemoveUnusedAlloca(AI);
+    }
+
+    return Changed;
+  }
+
   bool runOnFunction(Function &F) {
+
+
     LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
     DominatorTree *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
     AssumptionCache *AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F);
 
     bool NeedPromote = false;
     bool Changed = false;
+    
+    Changed |= RemoveAllUnusedAllocas(F);
 
     if (NoOpt) {
       // If any of the functions are marked as full unroll.

+ 2 - 2
tools/clang/test/HLSLFileCheck/hlsl/types/boolean/bool_scalar_swizzle.hlsl

@@ -11,5 +11,5 @@ float main() : SV_Target
 {
     bool b = true;
     bool2 b2 = b.xx;
-    return 0;
-}
+    return b2.x && b2.y ? 1 : 0;
+}

+ 24 - 0
tools/clang/test/HLSLFileCheck/validation/unused_input.hlsl

@@ -0,0 +1,24 @@
+// RUN: %dxc -E main -T cs_6_0 -Od %s | FileCheck %s
+
+// Regression test for unused resource being cleaned up in Od build so
+// they don't fail validation (for not being mapped in root signature)
+
+// CHECK: @main
+
+RWTexture3D<unorm float> s_uav: register(u0);
+
+struct SOME_CONST_BUFFER { float m_someFloat; };
+
+ConstantBuffer<SOME_CONST_BUFFER> s_constBuffer: register(b0);
+
+float someFunction() { return s_constBuffer.m_someFloat; }
+
+static const float UNUSED_CONSTANT = someFunction();
+
+[RootSignature("DescriptorTable(UAV(u0, numDescriptors = 1, flags = DATA_STATIC_WHILE_SET_AT_EXECUTE), visibility = SHADER_VISIBILITY_ALL)")]
+[numthreads(32, 32, 1)]
+void main(uint3 dispatchThreadID : SV_DispatchThreadID)
+{ 
+    s_uav[dispatchThreadID] = 0;
+}
+