VK_KHR_shader_expect_assume.proposal
This document proposes adding support for expect/assume SPIR-V instructions to guide shader program optimizations.
Problem Statement
Shader writers or generators as well as other SPIR-V producers (e.g. Machine Learning compilers) often have access to information that could enable the SPIR-V consumers in Vulkan implementations to make better optimization decisions, such as knowledge of the likely value of objects or whether a given condition holds, but which they cannot communicate to a Vulkan SPIR-V consumer using existing features.
Solution Space
SPIR-V already provides some mechanisms for producers to give hints to consumers in a limited number of scenarios:
OpBranchConditional
can accept branch weights that enable producers to indicate the likelihood of each path. This does not however generalize toOpSwitch
constructs.- Various so called Loop Controls make it possible for producers to provide metadata about the iteration count of loops or desired unrolling behavior.
There is however no exposed generic mechanism for SPIR-V producers to communicate optimization information to consumers. SPIR-V does support dedicated instructions, introduced by the SPV_KHR_expect_assume extension, that make it possible for producers to communicate to consumers the likely value of an object or whether a given condition holds, but this extension is currently not exposed in Vulkan.
Proposal
Expose the SPV_KHR_expect_assume extension in Vulkan.
The SPV_KHR_expect_assume
extension introduces two new instructions:
OpExpectKHR
makes it possible to state the most probable value of its input.OpAssumeTrueKHR
enables the optimizer to assume that the provided condition is always true.
Examples
As an illustration, consider the following pseudocode example:
c = 20 d = 2 b = c / d
if (a - b > 0) { ... } else { ... }
The writer or producer may know that a > 10. This knowledge makes it possible
to completely remove the else
branch. In this case, the producer could perform
that optimization alone. However, if the producer only knows that a
is greater
than some value provided, say with a specialization constant, it can no longer
perform the optimization. Adding that information to the SPIR-V module would
enable the SPIR-V consumer to do it.
Another possible use could be to provide guarantees that a particular value is not NaN or infinite:
value = load(...) assume(!isnan(value))
Issues
1) What shader stages should the instructions introduced by this extension be allowed in?
PROPOSED: No restrictions are placed on the shader stages the instructions can be used in.