This commit is contained in:
Tristan Labelle 2019-03-06 15:49:34 -08:00
Родитель 41a1ab10fc
Коммит 7c1f9f01e9
6 изменённых файлов: 44 добавлений и 20 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -447,6 +447,8 @@ public:
m_bIsLib = DM.GetShaderModel()->IsLib(); m_bIsLib = DM.GetShaderModel()->IsLib();
m_bLegalizationFailed = false; m_bLegalizationFailed = false;
FailOnPoisonResources();
bool bChanged = false; bool bChanged = false;
unsigned numResources = DM.GetCBuffers().size() + DM.GetUAVs().size() + unsigned numResources = DM.GetCBuffers().size() + DM.GetUAVs().size() +
DM.GetSRVs().size() + DM.GetSamplers().size(); DM.GetSRVs().size() + DM.GetSamplers().size();
@ -506,6 +508,7 @@ public:
} }
private: private:
void FailOnPoisonResources();
bool RemovePhiOnResource(); bool RemovePhiOnResource();
void UpdateResourceSymbols(); void UpdateResourceSymbols();
void TranslateDxilResourceUses(DxilResourceBase &res); void TranslateDxilResourceUses(DxilResourceBase &res);
@ -1690,6 +1693,23 @@ void UpdateStructTypeForLegacyLayoutOnDM(DxilModule &DM) {
} // namespace } // 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() { void DxilLowerCreateHandleForLib::UpdateStructTypeForLegacyLayout() {
UpdateStructTypeForLegacyLayoutOnDM(*m_DM); UpdateStructTypeForLegacyLayoutOnDM(*m_DM);
} }

Просмотреть файл

@ -36,40 +36,44 @@ using namespace llvm;
using namespace hlsl; using namespace hlsl;
namespace { namespace {
class FailUndefResource : public ModulePass { class PoisonUndefResources : public ModulePass {
public: public:
static char ID; static char ID;
explicit FailUndefResource() : ModulePass(ID) { explicit PoisonUndefResources() : ModulePass(ID) {
initializeScalarizerPass(*PassRegistry::getPassRegistry()); 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; 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) { bool PoisonUndefResources::runOnModule(Module &M) {
// Undef resources may be removed on simplify due to the interpretation // Undef resources typically indicate uninitialized locals being used
// of undef that any value could be substituted for identical meaning. // in some code path, which we should catch and report. However, some
// However, these likely indicate uninitialized locals being used in // code patterns in large shaders cause dead undef resources to momentarily,
// some code path, which we should catch and report. // 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()) { for (auto &F : M.functions()) {
if (GetHLOpcodeGroupByName(&F) == HLOpcodeGroup::HLCreateHandle) { if (GetHLOpcodeGroupByName(&F) == HLOpcodeGroup::HLCreateHandle) {
Type *ResTy = F.getFunctionType()->getParamType( Type *ResTy = F.getFunctionType()->getParamType(
HLOperandIndex::kCreateHandleResourceOpIdx); HLOperandIndex::kCreateHandleResourceOpIdx);
UndefValue *UndefRes = UndefValue::get(ResTy); UndefValue *UndefRes = UndefValue::get(ResTy);
for (auto U : UndefRes->users()) { if (!UndefRes->use_empty()) {
// Only report instruction users. Constant *PoisonRes = ConstantAggregateZero::get(ResTy);
if (Instruction *I = dyn_cast<Instruction>(U)) UndefRes->replaceAllUsesWith(PoisonRes);
dxilutil::EmitResMappingError(I);
} }
} }
} }

Просмотреть файл

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

Просмотреть файл

@ -1560,7 +1560,7 @@ class db_dxil(object):
add_pass('hlsl-dxil-legalize-eval-operations', 'DxilLegalizeEvalOperations', 'DXIL legalize eval operations', []) add_pass('hlsl-dxil-legalize-eval-operations', 'DxilLegalizeEvalOperations', 'DXIL legalize eval operations', [])
add_pass('dxilgen', 'DxilGenerationPass', 'HLSL DXIL Generation', [ add_pass('dxilgen', 'DxilGenerationPass', 'HLSL DXIL Generation', [
{'n':'NotOptimized','t':'bool','c':1}]) {'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('simplify-inst', 'SimplifyInst', 'Simplify Instructions', [])
add_pass('hlsl-dxil-precise', 'DxilPrecisePropagatePass', 'DXIL precise attribute propagate', []) add_pass('hlsl-dxil-precise', 'DxilPrecisePropagatePass', 'DXIL precise attribute propagate', [])
add_pass('dxil-legalize-sample-offset', 'DxilLegalizeSampleOffsetPass', 'DXIL legalize sample offset', []) add_pass('dxil-legalize-sample-offset', 'DxilLegalizeSampleOffsetPass', 'DXIL legalize sample offset', [])