Browse Source

Add HLDeadFunctionEliminationPass.

Xiang Li 8 năm trước cách đây
mục cha
commit
36ba7ac534

+ 2 - 0
include/dxc/HLSL/DxilGenerationPass.h

@@ -47,6 +47,7 @@ ModulePass *createDxilEmitMetadataPass();
 FunctionPass *createDxilExpandTrigIntrinsicsPass();
 ModulePass *createDxilLoadMetadataPass();
 ModulePass *createDxilDeadFunctionEliminationPass();
+ModulePass *createHLDeadFunctionEliminationPass();
 ModulePass *createDxilPrecisePropagatePass();
 FunctionPass *createDxilPreserveAllOutputsPass();
 FunctionPass *createDxilLegalizeResourceUsePass();
@@ -70,6 +71,7 @@ void initializeDxilEmitMetadataPass(llvm::PassRegistry&);
 void initializeDxilExpandTrigIntrinsicsPass(llvm::PassRegistry&);
 void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
 void initializeDxilDeadFunctionEliminationPass(llvm::PassRegistry&);
+void initializeHLDeadFunctionEliminationPass(llvm::PassRegistry&);
 void initializeDxilPrecisePropagatePassPass(llvm::PassRegistry&);
 void initializeDxilPreserveAllOutputsPass(llvm::PassRegistry&);
 void initializeDxilLegalizeResourceUsePassPass(llvm::PassRegistry&);

+ 4 - 0
include/dxc/HLSL/DxilUtil.h

@@ -14,6 +14,8 @@
 namespace llvm {
 class Type;
 class GlobalVariable;
+class Function;
+class Module;
 }
 
 namespace hlsl {
@@ -29,6 +31,8 @@ namespace dxilutil {
 
   bool IsStaticGlobal(llvm::GlobalVariable *GV);
   bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV);
+  bool RemoveUnusedFunctions(llvm::Module &M, llvm::Function *EntryFunc,
+                             llvm::Function *PatchConstantFunc, bool IsLib);
 }
 
 }

+ 1 - 0
include/dxc/HLSL/HLModule.h

@@ -86,6 +86,7 @@ public:
   void SetEntryFunction(llvm::Function *pEntryFunc);
   const std::string &GetEntryFunctionName() const;
   void SetEntryFunctionName(const std::string &name);
+  llvm::Function *GetPatchConstantFunction();
 
   // Resources.
   unsigned AddCBuffer(std::unique_ptr<DxilCBuffer> pCB);

+ 1 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -109,6 +109,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeGVNPass(Registry);
     initializeGlobalDCEPass(Registry);
     initializeGlobalOptPass(Registry);
+    initializeHLDeadFunctionEliminationPass(Registry);
     initializeHLEmitMetadataPass(Registry);
     initializeHLEnsureMetadataPass(Registry);
     initializeHLMatrixLowerPassPass(Registry);

+ 38 - 0
lib/HLSL/DxilGenerationPass.cpp

@@ -1440,6 +1440,44 @@ ModulePass *llvm::createDxilPrecisePropagatePass() {
 
 INITIALIZE_PASS(DxilPrecisePropagatePass, "hlsl-dxil-precise", "DXIL precise attribute propagate", false, false)
 
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+class HLDeadFunctionElimination : public ModulePass {
+public:
+  static char ID; // Pass identification, replacement for typeid
+  explicit HLDeadFunctionElimination () : ModulePass(ID) {}
+
+  const char *getPassName() const override { return "Remove all unused function except entry from HLModule"; }
+
+  bool runOnModule(Module &M) override {
+    if (M.HasHLModule()) {
+      HLModule &HLM = M.GetHLModule();
+
+      bool IsLib = HLM.GetShaderModel()->IsLib();
+      // Remove unused functions except entry and patch constant func.
+      // For library profile, only remove unused external functions.
+      Function *EntryFunc = HLM.GetEntryFunction();
+      Function *PatchConstantFunc = HLM.GetPatchConstantFunction();
+
+      return dxilutil::RemoveUnusedFunctions(M, EntryFunc, PatchConstantFunc,
+                                             IsLib);
+    }
+
+    return false;
+  }
+};
+}
+
+char HLDeadFunctionElimination::ID = 0;
+
+ModulePass *llvm::createHLDeadFunctionEliminationPass() {
+  return new HLDeadFunctionElimination();
+}
+
+INITIALIZE_PASS(HLDeadFunctionElimination, "hl-dfe", "Remove all unused function except entry from HLModule", false, false)
+
+
 ///////////////////////////////////////////////////////////////////////////////
 // Legalize resource use.
 // Map local or static global resource to global resource.

+ 2 - 13
lib/HLSL/DxilPreparePasses.cpp

@@ -112,19 +112,8 @@ public:
       Function *EntryFunc = DM.GetEntryFunction();
       Function *PatchConstantFunc = DM.GetPatchConstantFunction();
 
-      std::vector<Function *> deadList;
-      for (iplist<Function>::iterator F : M.getFunctionList()) {
-        if (&(*F) == EntryFunc || &(*F) == PatchConstantFunc)
-          continue;
-        if (F->isDeclaration() || !IsLib) {
-          if (F->user_empty())
-            deadList.emplace_back(F);
-        }
-      }
-      bool bUpdated = deadList.size();
-      for (Function *F : deadList)
-        F->eraseFromParent();
-      return bUpdated;
+      return dxilutil::RemoveUnusedFunctions(M, EntryFunc, PatchConstantFunc,
+                                             IsLib);
     }
 
     return false;

+ 17 - 0
lib/HLSL/DxilUtil.cpp

@@ -13,6 +13,7 @@
 #include "llvm/IR/GlobalVariable.h"
 #include "dxc/HLSL/DxilTypeSystem.h"
 #include "dxc/HLSL/DxilUtil.h"
+#include "llvm/IR/Module.h"
 
 using namespace llvm;
 using namespace hlsl;
@@ -80,6 +81,22 @@ bool IsSharedMemoryGlobal(llvm::GlobalVariable *GV) {
   return GV->getType()->getPointerAddressSpace() == DXIL::kTGSMAddrSpace;
 }
 
+bool RemoveUnusedFunctions(Module &M, Function *EntryFunc,
+                           Function *PatchConstantFunc, bool IsLib) {
+  std::vector<Function *> deadList;
+  for (auto &F : M.functions()) {
+    if (&F == EntryFunc || &F == PatchConstantFunc)
+      continue;
+    if (F.isDeclaration() || !IsLib) {
+      if (F.user_empty())
+        deadList.emplace_back(&F);
+    }
+  }
+  bool bUpdated = deadList.size();
+  for (Function *F : deadList)
+    F->eraseFromParent();
+  return bUpdated;
+}
 }
 
 }

+ 9 - 0
lib/HLSL/HLModule.cpp

@@ -128,6 +128,15 @@ Function *HLModule::GetEntryFunction() const {
   return m_pEntryFunc;
 }
 
+Function *HLModule::GetPatchConstantFunction() {
+  if (!m_pSM->IsHS())
+    return nullptr;
+  if (!m_pEntryFunc)
+    return nullptr;
+  DxilFunctionProps &funcProps = GetDxilFunctionProps(m_pEntryFunc);
+  return funcProps.ShaderProps.HS.patchConstantFunc;
+}
+
 void HLModule::SetEntryFunction(Function *pEntryFunc) {
   m_pEntryFunc = pEntryFunc;
 }

+ 1 - 1
lib/Transforms/IPO/PassManagerBuilder.cpp

@@ -211,7 +211,7 @@ static void addHLSLPasses(bool HLSLHighLevel, bool NoOpt, hlsl::HLSLExtensionsCo
   }
 
   if (!NoOpt) {
-    MPM.add(createDxilDeadFunctionEliminationPass());
+    MPM.add(createHLDeadFunctionEliminationPass());
   }
 
   // Split struct and array of parameter.

+ 1 - 0
utils/hct/hctdb.py

@@ -1286,6 +1286,7 @@ class db_dxil(object):
         add_pass('hlsl-dxilemit', 'DxilEmitMetadata', 'HLSL DXIL Metadata Emit', [])
         add_pass('hlsl-dxilload', 'DxilLoadMetadata', 'HLSL DXIL Metadata Load', [])
         add_pass('dxil-dfe', 'DxilDeadFunctionElimination', 'Remove all unused function except entry from DxilModule', [])
+        add_pass('hl-dfe', 'HLDeadFunctionElimination', 'Remove all unused function except entry from HLModule', [])
         add_pass('hlsl-dxil-expand-trig', 'DxilExpandTrigIntrinsics', 'DXIL expand trig intrinsics', [])
         add_pass('hlsl-hca', 'HoistConstantArray', 'HLSL constant array hoisting', [])
         add_pass('hlsl-dxil-preserve-all-outputs', 'DxilPreserveAllOutputs', 'DXIL write to all outputs in signature', [])