diff options
author | Thomas Helland <[email protected]> | 2016-12-13 14:39:51 +1100 |
---|---|---|
committer | Timothy Arceri <[email protected]> | 2016-12-23 10:15:36 +1100 |
commit | 6772a17acc8ee90f9398348251a4455f988208fd (patch) | |
tree | e13a69b687b5e6d42a584d373aaeca41e9949daa /src/compiler/nir/nir.h | |
parent | eda3ec7957ec9324641ee75847b892885e77335f (diff) |
nir: Add a loop analysis pass
This pass detects induction variables and calculates the
trip count of loops to be used for loop unrolling.
V2: Rebase, adapt to removal of function overloads
V3: (Timothy Arceri)
- don't try to find trip count if loop terminator conditional is a phi
- fix trip count for do-while loops
- replace conditional type != alu assert with return
- disable unrolling of loops with continues
- multiple fixes to memory allocation, stop leaking and don't destroy
structs we want to use for unrolling.
- fix iteration count bugs when induction var not on RHS of condition
- add FIXME for && conditions
- calculate trip count for unsigned induction/limit vars
V4: (Timothy Arceri)
- count instructions in a loop
- set the limiting_terminator even if we can't find the trip count for
all terminators. This is needed for complex unrolling where we handle
2 terminators and the trip count is unknown for one of them.
- restruct structs so we don't keep information not required after
analysis and remove dead fields.
- force unrolling in some cases as per the rules in the GLSL IR pass
V5: (Timothy Arceri)
- fix metadata mask value 0x10 vs 0x16
V6: (Timothy Arceri)
- merge loop_variable and nir_loop_variable structs and lists suggested by Jason
- remove induction var hash table and store pointer to induction information in
the loop_variable suggested by Jason.
- use lowercase list_addtail() suggested by Jason.
- tidy up init_loop_block() as per Jasons suggestions.
- replace switch with nir_op_infos[alu->op].num_inputs == 2 in
is_var_basic_induction_var() as suggested by Jason.
- use nir_block_last_instr() in and rename foreach_cf_node_ex_loop() as suggested
by Jason.
- fix else check for is_trivial_loop_terminator() as per Connors suggetions.
- simplify offset for induction valiables incremented before the exit conditions is
checked.
- replace nir_op_isub check with assert() as it should have been lowered away.
V7: (Timothy Arceri)
- use rzalloc() on nir_loop struct creation. Worked previously because ralloc()
was broken and always zeroed the struct.
- fix cf_node_find_loop_jumps() to find jumps when loops contain
nested if statements. Code is tidier as a result.
V8: (Timothy Arceri)
- move is_trivial_loop_terminator() to nir.h so we can use it to assert is
the loop unroll pass
- fix analysis to not bail when looking for terminator when the break is in the else
rather then the if
- added new loop terminator fields: break_block, continue_from_block and
continue_from_then so we don't have to gather these when doing unrolling.
- get correct array length when forcing unrolling of variables
indexed arrays that are the same size as the iteration count
- add support for induction variables of type float
- update trival loop terminator check to allow an if containing
instructions as long as both branches contain only a single
block.
V9: (Timothy)
- bunch of tidy ups and simplifications suggested by Jason.
- rewrote trivial terminator detection, now the only restriction is there
must be no nested jumps, anything else goes.
- rewrote the iteration test to use nir_eval_const_opcode().
- count instruction properly even when forcing an unroll.
- bunch of other tidy ups and simplifications.
V10: (Timothy)
- some trivial tidy ups suggested by Jason.
- conditional fix for break inside continue branch by Jason.
Reviewed-by: Jason Ekstrand <[email protected]>
Diffstat (limited to 'src/compiler/nir/nir.h')
-rw-r--r-- | src/compiler/nir/nir.h | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 2c7237b4af2..c7da1e779db 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1506,9 +1506,41 @@ typedef struct nir_if { } nir_if; typedef struct { + nir_if *nif; + + nir_instr *conditional_instr; + + nir_block *break_block; + nir_block *continue_from_block; + + bool continue_from_then; + + struct list_head loop_terminator_link; +} nir_loop_terminator; + +typedef struct { + /* Number of instructions in the loop */ + unsigned num_instructions; + + /* How many times the loop is run (if known) */ + unsigned trip_count; + bool is_trip_count_known; + + /* Unroll the loop regardless of its size */ + bool force_unroll; + + nir_loop_terminator *limiting_terminator; + + /* A list of loop_terminators terminating this loop. */ + struct list_head loop_terminator_list; +} nir_loop_info; + +typedef struct { nir_cf_node cf_node; struct exec_list body; /** < list of nir_cf_node */ + + nir_loop_info *info; } nir_loop; /** @@ -1521,6 +1553,7 @@ typedef enum { nir_metadata_dominance = 0x2, nir_metadata_live_ssa_defs = 0x4, nir_metadata_not_properly_reset = 0x8, + nir_metadata_loop_analysis = 0x10, } nir_metadata; typedef struct { @@ -1749,6 +1782,8 @@ typedef struct nir_shader_compiler_options { * information must be inferred from the list of input nir_variables. */ bool use_interpolated_input_intrinsics; + + unsigned max_unroll_iterations; } nir_shader_compiler_options; typedef struct nir_shader { @@ -1859,7 +1894,7 @@ nir_loop *nir_loop_create(nir_shader *shader); nir_function_impl *nir_cf_node_get_function(nir_cf_node *node); /** requests that the given pieces of metadata be generated */ -void nir_metadata_require(nir_function_impl *impl, nir_metadata required); +void nir_metadata_require(nir_function_impl *impl, nir_metadata required, ...); /** dirties all but the preserved metadata */ void nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved); @@ -2479,6 +2514,10 @@ void nir_lower_double_pack(nir_shader *shader); bool nir_normalize_cubemap_coords(nir_shader *shader); void nir_live_ssa_defs_impl(nir_function_impl *impl); + +void nir_loop_analyze_impl(nir_function_impl *impl, + nir_variable_mode indirect_mask); + bool nir_ssa_defs_interfere(nir_ssa_def *a, nir_ssa_def *b); void nir_convert_to_ssa_impl(nir_function_impl *impl); |