mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 05:10:05 +00:00
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:
parent
c9a881ecc6
commit
7505d24225
@ -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() {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user