浏览代码

Use opcode class to guide constant folding possibilities (#191)

This change modifies dxil constant folding to use the opcode class when
deciding if a dxil function can be constant folded. We now require a
DxilModule to be available when constant folding dxil functions.

To ensure that the dxil module is available we add a new pass that loads a
dxil module from metadata if it does not exist. We use the new pass in the
dxopt tests for constant folding.
David Peixotto 8 年之前
父节点
当前提交
b0fd2d3949

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

@@ -42,6 +42,7 @@ ModulePass *createDxilGenerationPass(bool NotOptimized, hlsl::HLSLExtensionsCode
 ModulePass *createHLEmitMetadataPass();
 ModulePass *createHLEnsureMetadataPass();
 ModulePass *createDxilEmitMetadataPass();
+ModulePass *createDxilLoadMetadataPass();
 ModulePass *createDxilPrecisePropagatePass();
 FunctionPass *createDxilLegalizeResourceUsePass();
 ModulePass *createDxilLegalizeStaticResourceUsePass();
@@ -53,6 +54,7 @@ void initializeDxilGenerationPassPass(llvm::PassRegistry&);
 void initializeHLEnsureMetadataPass(llvm::PassRegistry&);
 void initializeHLEmitMetadataPass(llvm::PassRegistry&);
 void initializeDxilEmitMetadataPass(llvm::PassRegistry&);
+void initializeDxilLoadMetadataPass(llvm::PassRegistry&);
 void initializeDxilPrecisePropagatePassPass(llvm::PassRegistry&);
 void initializeDxilLegalizeResourceUsePassPass(llvm::PassRegistry&);
 void initializeDxilLegalizeStaticResourceUsePassPass(llvm::PassRegistry&);

+ 23 - 17
lib/Analysis/DxilConstantFolding.cpp

@@ -544,25 +544,31 @@ Constant *hlsl::ConstantFoldScalarCall(StringRef Name, Type *Ty, ArrayRef<Consta
 // we only have the function value here instead of the call. We need the
 // actual call to get the opcode for the intrinsic.
 bool hlsl::CanConstantFoldCallTo(const Function *F) {
-  if (!OP::IsDxilOpFunc(F))
+  // Only constant fold dxil functions when we have a valid dxil module.
+  if (!F->getParent()->HasDxilModule()) {
+    assert(!OP::IsDxilOpFunc(F) && "dx.op function with no dxil module?");
     return false;
+  }
 
-  // Check match using startswith to get all overloads.
-  // We cannot use the opcode class here because constant folding
-  // may run without a DxilModule available.
-  StringRef Name = F->getName();
-  if (Name.startswith("dx.op.unary"))
-    return true;
-  else if (Name.startswith("dx.op.unaryBits"))
-    return true;
-  else if (Name.startswith("dx.op.binary"))
-    return true;
-  else if (Name.startswith("dx.op.tertiary"))
-    return true;
-  else if (Name.startswith("dx.op.quaternary"))
-    return true;
-  else if (Name.startswith("dx.op.dot"))
-    return true;
+  // Lookup opcode class in dxil module. Set default value to invalid class.
+  OP::OpCodeClass opClass = OP::OpCodeClass::NumOpClasses;
+  const bool found = F->getParent()->GetDxilModule().GetOP()->GetOpCodeClass(F, opClass);
+
+  // Return true for those dxil operation classes we can constant fold.
+  if (found) {
+    switch (opClass) {
+    default: break;
+    case OP::OpCodeClass::Unary:
+    case OP::OpCodeClass::UnaryBits:
+    case OP::OpCodeClass::Binary:
+    case OP::OpCodeClass::Tertiary:
+    case OP::OpCodeClass::Quaternary:
+    case OP::OpCodeClass::Dot2:
+    case OP::OpCodeClass::Dot3:
+    case OP::OpCodeClass::Dot4:
+      return true;
+    }
+  }
 
   return false;
 }

+ 1 - 0
lib/HLSL/DxcOptimizer.cpp

@@ -79,6 +79,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDxilLegalizeResourceUsePassPass(Registry);
     initializeDxilLegalizeSampleOffsetPassPass(Registry);
     initializeDxilLegalizeStaticResourceUsePassPass(Registry);
+    initializeDxilLoadMetadataPass(Registry);
     initializeDxilPrecisePropagatePassPass(Registry);
     initializeDynamicIndexingVectorToArrayPass(Registry);
     initializeEarlyCSELegacyPassPass(Registry);

+ 30 - 0
lib/HLSL/DxilGenerationPass.cpp

@@ -2761,6 +2761,36 @@ ModulePass *llvm::createHLEnsureMetadataPass() {
 
 INITIALIZE_PASS(HLEnsureMetadata, "hlsl-hlensure", "HLSL High-Level Metadata Ensure", false, false)
 
+///////////////////////////////////////////////////////////////////////////////
+
+namespace {
+class DxilLoadMetadata : public ModulePass {
+public:
+  static char ID; // Pass identification, replacement for typeid
+  explicit DxilLoadMetadata () : ModulePass(ID) {}
+
+  const char *getPassName() const override { return "HLSL load DxilModule from metadata"; }
+
+  bool runOnModule(Module &M) override {
+    if (!M.HasDxilModule()) {
+      (void)M.GetOrCreateDxilModule();
+      return true;
+    }
+
+    return false;
+  }
+};
+}
+
+char DxilLoadMetadata::ID = 0;
+
+ModulePass *llvm::createDxilLoadMetadataPass() {
+  return new DxilLoadMetadata();
+}
+
+INITIALIZE_PASS(DxilLoadMetadata, "hlsl-dxilload", "HLSL load DxilModule from metadata", false, false)
+
+
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace {

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

@@ -215,6 +215,7 @@ static void addHLSLPasses(bool HLSLHighLevel, bool NoOpt, hlsl::HLSLExtensionsCo
   MPM.add(createDxilLegalizeResourceUsePass());
   MPM.add(createDxilLegalizeStaticResourceUsePass());
   MPM.add(createDxilGenerationPass(NoOpt, ExtHelper));
+  MPM.add(createDxilLoadMetadataPass()); // Ensure DxilModule is loaded for optimizations.
 
   MPM.add(createSimplifyInstPass());
 

+ 1 - 1
tools/clang/test/HLSL/constprop/bfi.ll

@@ -1,4 +1,4 @@
-; RUN: %opt %s -sccp -S | FileCheck %s
+; RUN: %opt %s -hlsl-dxilload -sccp -S | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 target triple = "dxil-ms-dx"

+ 1 - 1
tools/clang/test/HLSL/constprop/ibfe.ll

@@ -1,4 +1,4 @@
-; RUN: %opt %s -sccp -S | FileCheck %s
+; RUN: %opt %s -hlsl-dxilload -sccp -S | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 target triple = "dxil-ms-dx"

+ 1 - 1
tools/clang/test/HLSL/constprop/ubfe.ll

@@ -1,4 +1,4 @@
-; RUN: %opt %s -sccp -S | FileCheck %s
+; RUN: %opt %s -hlsl-dxilload -sccp -S | FileCheck %s
 
 target datalayout = "e-m:e-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
 target triple = "dxil-ms-dx"

+ 1 - 0
utils/hct/hctdb.py

@@ -1218,6 +1218,7 @@ class db_dxil(object):
         add_pass('multi-dim-one-dim', 'MultiDimArrayToOneDimArray', 'Flatten multi-dim array into one-dim array', [])
         add_pass('hlsl-dxil-condense', 'DxilCondenseResources', 'DXIL Condense Resources', [])
         add_pass('hlsl-dxilemit', 'DxilEmitMetadata', 'HLSL DXIL Metadata Emit', [])
+        add_pass('hlsl-dxilload', 'DxilLoadMetadata', 'HLSL DXIL Metadata Load', [])
         add_pass('ipsccp', 'IPSCCP', 'Interprocedural Sparse Conditional Constant Propagation', [])
         add_pass('globalopt', 'GlobalOpt', 'Global Variable Optimizer', [])
         add_pass('deadargelim', 'DAE', 'Dead Argument Elimination', [])