Tristan Labelle 6 years ago
parent
commit
7c1f9f01e9

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

@@ -67,7 +67,7 @@ ModulePass *createDxilLegalizeResources();
 ModulePass *createDxilLegalizeEvalOperationsPass();
 FunctionPass *createDxilLegalizeSampleOffsetPass();
 FunctionPass *createDxilSimpleGVNHoistPass();
-ModulePass *createFailUndefResourcePass();
+ModulePass *createPoisonUndefResourcesPass();
 FunctionPass *createSimplifyInstPass();
 ModulePass *createDxilTranslateRawBuffer();
 ModulePass *createNoPausePassesPass();
@@ -99,7 +99,7 @@ void initializeDxilLegalizeResourcesPass(llvm::PassRegistry&);
 void initializeDxilLegalizeEvalOperationsPass(llvm::PassRegistry&);
 void initializeDxilLegalizeSampleOffsetPassPass(llvm::PassRegistry&);
 void initializeDxilSimpleGVNHoistPass(llvm::PassRegistry&);
-void initializeFailUndefResourcePass(llvm::PassRegistry&);
+void initializePoisonUndefResourcesPass(llvm::PassRegistry&);
 void initializeSimplifyInstPass(llvm::PassRegistry&);
 void initializeDxilTranslateRawBufferPass(llvm::PassRegistry&);
 void initializeNoPausePassesPass(llvm::PassRegistry&);

+ 1 - 1
lib/HLSL/DxcOptimizer.cpp

@@ -110,7 +110,7 @@ HRESULT SetupRegistryPassForHLSL() {
     initializeDynamicIndexingVectorToArrayPass(Registry);
     initializeEarlyCSELegacyPassPass(Registry);
     initializeEliminateAvailableExternallyPass(Registry);
-    initializeFailUndefResourcePass(Registry);
+    initializePoisonUndefResourcesPass(Registry);
     initializeFloat2IntPass(Registry);
     initializeFunctionAttrsPass(Registry);
     initializeGVNPass(Registry);

+ 20 - 0
lib/HLSL/DxilCondenseResources.cpp

@@ -447,6 +447,8 @@ public:
     m_bIsLib = DM.GetShaderModel()->IsLib();
     m_bLegalizationFailed = false;
 
+    FailOnPoisonResources();
+
     bool bChanged = false;
     unsigned numResources = DM.GetCBuffers().size() + DM.GetUAVs().size() +
                             DM.GetSRVs().size() + DM.GetSamplers().size();
@@ -506,6 +508,7 @@ public:
   }
 
 private:
+  void FailOnPoisonResources();
   bool RemovePhiOnResource();
   void UpdateResourceSymbols();
   void TranslateDxilResourceUses(DxilResourceBase &res);
@@ -1690,6 +1693,23 @@ void UpdateStructTypeForLegacyLayoutOnDM(DxilModule &DM) {
 
 } // namespace
 
+void DxilLowerCreateHandleForLib::FailOnPoisonResources() {
+  // A previous pass replaced all undef resources with constant zero resources.
+  // If those made it here, the program is malformed.
+  for (Function &Func : this->m_DM->GetModule()->functions()) {
+    hlsl::OP::OpCodeClass OpcodeClass;
+    if (m_DM->GetOP()->GetOpCodeClass(&Func, OpcodeClass)
+      && OpcodeClass == OP::OpCodeClass::CreateHandleForLib) {
+      Type *ResTy = Func.getFunctionType()->getParamType(
+        DXIL::OperandIndex::kCreateHandleForLibResOpIdx);
+      Constant *PoisonRes = ConstantAggregateZero::get(ResTy);
+      for (User *PoisonUser : PoisonRes->users())
+        if (Instruction *PoisonUserInst = dyn_cast<Instruction>(PoisonUser))
+          dxilutil::EmitResMappingError(PoisonUserInst);
+    }
+  }
+}
+
 void DxilLowerCreateHandleForLib::UpdateStructTypeForLegacyLayout() {
   UpdateStructTypeForLegacyLayoutOnDM(*m_DM);
 }

+ 19 - 15
lib/HLSL/DxilPreparePasses.cpp

@@ -36,40 +36,44 @@ using namespace llvm;
 using namespace hlsl;
 
 namespace {
-class FailUndefResource : public ModulePass {
+class PoisonUndefResources : public ModulePass {
 public:
   static char ID;
 
-  explicit FailUndefResource() : ModulePass(ID) {
+  explicit PoisonUndefResources() : ModulePass(ID) {
     initializeScalarizerPass(*PassRegistry::getPassRegistry());
   }
 
-  const char *getPassName() const override { return "Fail on undef resource use"; }
+  const char *getPassName() const override { return "Poison undef resources"; }
 
   bool runOnModule(Module &M) override;
 };
 }
 
-char FailUndefResource::ID = 0;
+char PoisonUndefResources::ID = 0;
 
-ModulePass *llvm::createFailUndefResourcePass() { return new FailUndefResource(); }
+ModulePass *llvm::createPoisonUndefResourcesPass() { return new PoisonUndefResources(); }
 
-INITIALIZE_PASS(FailUndefResource, "fail-undef-resource", "Fail on undef resource use", false, false)
+INITIALIZE_PASS(PoisonUndefResources, "poison-undef-resource", "Poison undef resources", false, false)
 
-bool FailUndefResource::runOnModule(Module &M) {
-  // Undef resources may be removed on simplify due to the interpretation
-  // of undef that any value could be substituted for identical meaning.
-  // However, these likely indicate uninitialized locals being used in
-  // some code path, which we should catch and report.
+bool PoisonUndefResources::runOnModule(Module &M) {
+  // Undef resources typically indicate uninitialized locals being used
+  // in some code path, which we should catch and report. However, some
+  // code patterns in large shaders cause dead undef resources to momentarily,
+  // which is not an error. We must wait until cleanup passes
+  // have run to know whether we must produce an error.
+  // However, we can't leave the undef values in because they could eliminated,
+  // such as by reading from resources seen in a code path that was not taken.
+  // We avoid the problem by replacing undef values by another poison
+  // value that we can identify later.
   for (auto &F : M.functions()) {
     if (GetHLOpcodeGroupByName(&F) == HLOpcodeGroup::HLCreateHandle) {
       Type *ResTy = F.getFunctionType()->getParamType(
         HLOperandIndex::kCreateHandleResourceOpIdx);
       UndefValue *UndefRes = UndefValue::get(ResTy);
-      for (auto U : UndefRes->users()) {
-        // Only report instruction users.
-        if (Instruction *I = dyn_cast<Instruction>(U))
-          dxilutil::EmitResMappingError(I);
+      if (!UndefRes->use_empty()) {
+        Constant *PoisonRes = ConstantAggregateZero::get(ResTy);
+        UndefRes->replaceAllUsesWith(PoisonRes);
       }
     }
   }

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

@@ -277,7 +277,7 @@ static void addHLSLPasses(bool HLSLHighLevel, unsigned OptLevel, hlsl::HLSLExten
   MPM.add(createDxilPromoteLocalResources());
   MPM.add(createDxilPromoteStaticResources());
   // Verify no undef resource again after promotion
-  MPM.add(createFailUndefResourcePass());
+  MPM.add(createPoisonUndefResourcesPass());
 
   MPM.add(createDxilGenerationPass(NoOpt, ExtHelper));
 

+ 1 - 1
utils/hct/hctdb.py

@@ -1560,7 +1560,7 @@ class db_dxil(object):
         add_pass('hlsl-dxil-legalize-eval-operations', 'DxilLegalizeEvalOperations', 'DXIL legalize eval operations', [])
         add_pass('dxilgen', 'DxilGenerationPass', 'HLSL DXIL Generation', [
             {'n':'NotOptimized','t':'bool','c':1}])
-        add_pass('fail-undef-resource', 'FailUndefResource', 'Fail on undef resource use', [])
+        add_pass('poison-undef-resource', 'PoisonUndefResources', 'Poison undef resources', [])
         add_pass('simplify-inst', 'SimplifyInst', 'Simplify Instructions', [])
         add_pass('hlsl-dxil-precise', 'DxilPrecisePropagatePass', 'DXIL precise attribute propagate', [])
         add_pass('dxil-legalize-sample-offset', 'DxilLegalizeSampleOffsetPass', 'DXIL legalize sample offset', [])