Update the legalization passes.

Changes the set of optimizations done for legalization.  While doing
this, I added documentation to explain why we want each optimization.

A new option "--legalize-hlsl" is added so the legalization passes can
be easily run from the command line.
The legalize option implies skip-validation.
This commit is contained in:
Steven Perron 2017-12-19 15:08:54 -05:00 committed by David Neto
parent c9a881ecc6
commit 7505d24225
2 changed files with 62 additions and 14 deletions

View File

@ -66,19 +66,50 @@ Optimizer& Optimizer::RegisterPass(PassToken&& p) {
return *this;
}
// The legalization passes take a spir-v shader generated by an HLSL front-end
// and turn it into a valid vulkan spir-v shader. There are two ways in which
// the code will be invalid at the start:
//
// 1) There will be opaque objects, like images, which will be passed around
// in intermediate objects. Valid spir-v will have to replace the use of
// the opaque object with an intermediate object that is the result of the
// load of the global opaque object.
//
// 2) There will be variables that contain pointers to structured or uniform
// buffers. It be legal, the variables must be eliminated, and the
// references to the structured buffers must use the result of OpVariable
// in the Uniform storage class.
//
// Optimization in this list must accept shaders with these relaxation of the
// rules. There is not guarantee that this list of optimizations is able to
// legalize all inputs, but it is on a best effort basis.
//
// The legalization problem is essentially a very general copy propagation
// problem. The optimization we use are all used to either do copy propagation
// or enable more copy propagation.
Optimizer& Optimizer::RegisterLegalizationPasses() {
return RegisterPass(CreateInlineExhaustivePass())
.RegisterPass(CreateLocalAccessChainConvertPass())
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
.RegisterPass(CreateLocalSingleStoreElimPass())
.RegisterPass(CreateInsertExtractElimPass())
.RegisterPass(CreateAggressiveDCEPass())
.RegisterPass(CreateDeadBranchElimPass())
.RegisterPass(CreateCFGCleanupPass())
.RegisterPass(CreateBlockMergePass())
.RegisterPass(CreateLocalMultiStoreElimPass())
.RegisterPass(CreateInsertExtractElimPass())
.RegisterPass(CreateAggressiveDCEPass());
return
// Make sure uses and definitions are in the same function.
RegisterPass(CreateInlineExhaustivePass())
// Make private variable function scope
.RegisterPass(CreateEliminateDeadFunctionsPass())
.RegisterPass(CreatePrivateToLocalPass())
// Split up aggragates so they are easier to deal with.
.RegisterPass(CreateScalarReplacementPass())
// Remove loads and stores so everything is in intermediate values.
// Takes care of copy propagation of non-members.
.RegisterPass(CreateLocalMultiStoreElimPass())
// Copy propagate members. Cleans up code sequences generated by
// scalar replacement.
.RegisterPass(CreateInsertExtractElimPass())
// TODO: Add constant propagation here
// May need loop unrolling here see
// https://github.com/Microsoft/DirectXShaderCompiler/pull/930
.RegisterPass(CreateCFGCleanupPass())
// Get rid of unused code that leave traces of the illegal code.
.RegisterPass(CreateAggressiveDCEPass())
// TODO: Remove this once ADCE can do it.
.RegisterPass(CreateDeadVariableEliminationPass());
}
Optimizer& Optimizer::RegisterPerformancePasses() {

View File

@ -48,6 +48,12 @@ std::string GetListOfPassesAsString(const spvtools::Optimizer& optimizer) {
return ss.str();
}
std::string GetLegalizationPasses() {
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
optimizer.RegisterLegalizationPasses();
return GetListOfPassesAsString(optimizer);
}
std::string GetOptimizationPasses() {
spvtools::Optimizer optimizer(SPV_ENV_UNIVERSAL_1_2);
optimizer.RegisterPerformancePasses();
@ -140,6 +146,14 @@ Options (in lexicographical order):
Exhaustively inline all function calls in entry point call tree
functions. Currently does not inline calls to functions with
early return in a loop.
--legalize-hlsl
Runs a series of optimizations that attempts to take SPIR-V
generated by and HLSL front-end and generate legal Vulkan SPIR-V.
The optimizations are:
%s
Note this does not guarantee legal code. This option implies
--skip-validation.
--local-redundancy-elimination
Looks for instructions in the same basic block that compute the
same value, and deletes the redundant ones.
@ -234,8 +248,8 @@ Options (in lexicographical order):
--version
Display optimizer version information.
)",
program, program, GetOptimizationPasses().c_str(),
GetSizePasses().c_str());
program, program, GetLegalizationPasses().c_str(),
GetOptimizationPasses().c_str(), GetSizePasses().c_str());
}
// Reads command-line flags the file specified in |oconfig_flag|. This string
@ -421,6 +435,9 @@ OptStatus ParseFlags(int argc, const char** argv, Optimizer* optimizer,
optimizer->RegisterPerformancePasses();
} else if (0 == strcmp(cur_arg, "-Os")) {
optimizer->RegisterSizePasses();
} else if (0 == strcmp(cur_arg, "--legalize-hlsl")) {
*skip_validator = true;
optimizer->RegisterLegalizationPasses();
} else if (0 == strncmp(cur_arg, "-Oconfig=", sizeof("-Oconfig=") - 1)) {
OptStatus status =
ParseOconfigFlag(argv[0], cur_arg, optimizer, in_file, out_file);