pub fn find_checked_indexes(
module: &Module,
function: &Function,
info: &FunctionInfo,
policies: BoundsCheckPolicies,
) -> BitSet
Expand description
Build a set of expressions used as indices, to cache in temporary variables when emitted.
Given the bounds-check policies policies
, construct a BitSet
containing the handle
indices of all the expressions in function
that are ever used as guarded indices
under the ReadZeroSkipWrite
policy. The module
argument must be the module to
which function
belongs, and info
should be that function’s analysis results.
Such index expressions will be used twice in the generated code: first for the comparison to see if the index is in bounds, and then for the access itself, should the comparison succeed. To avoid computing the expressions twice, the generated code should cache them in temporary variables.
Why do we need to build such a set in advance, instead of just processing access
expressions as we encounter them? Whether an expression needs to be cached depends on
whether it appears as something like the index
operand of an Access
expression
or the level
operand of an ImageLoad
expression, and on the index bounds check
policies that apply to those accesses. But Emit
statements just identify a range
of expressions by index; there’s no good way to tell what an expression is used
for. The only way to do it is to just iterate over all the expressions looking for
relevant Access
expressions — which is what this function does.
Simple expressions like variable loads and constants don’t make sense to cache: it’s
no better than just re-evaluating them. But constants are not covered by Emit
statements, and Load
s are always cached to ensure they occur at the right time, so
we don’t bother filtering them out from this set.
Fortunately, we don’t need to deal with ImageStore
statements here. When we emit
code for a statement, the writer isn’t in the middle of an expression, so we can just
emit declarations for temporaries, initialized appropriately.
None of these concerns apply for SPIR-V output, since it’s easy to just reuse an instruction ID in two places; that has the same semantics as a temporary variable, and it’s inherent in the design of SPIR-V. This function is more useful for text-based back ends.