diff options
author | Jason Ekstrand <[email protected]> | 2015-02-09 20:18:44 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-02-19 17:06:17 -0800 |
commit | c7002fad9062f54f7dfabe25dc14b7fb217e6adc (patch) | |
tree | 1b005dc21cc724b2476ddd849816267279520c12 /src/glsl | |
parent | 8dfe6f672f4f3e226089c6cc8d392fcd39dff5cb (diff) |
nir/GCM: Pull unpinned instructions out of blocks while pinning
This lets us be slightly more efficient by not walking the CFG extra times.
Also, it may make it easier to ensure that GVN happens on only unpinned
instructions.
Reviewed-by: Reviewed-by: Connor Abbott <[email protected]>
Diffstat (limited to 'src/glsl')
-rw-r--r-- | src/glsl/nir/nir_opt_gcm.c | 62 |
1 files changed, 25 insertions, 37 deletions
diff --git a/src/glsl/nir/nir_opt_gcm.c b/src/glsl/nir/nir_opt_gcm.c index 57328be00d0..bf565b96988 100644 --- a/src/glsl/nir/nir_opt_gcm.c +++ b/src/glsl/nir/nir_opt_gcm.c @@ -105,8 +105,10 @@ gcm_build_block_info(struct exec_list *cf_list, struct gcm_state *state, * to either GCM_INSTR_PINNED or 0. */ static bool -gcm_pin_instructions_block(nir_block *block, void *state) +gcm_pin_instructions_block(nir_block *block, void *void_state) { + struct gcm_state *state = void_state; + nir_foreach_instr_safe(block, instr) { switch (instr->type) { case nir_instr_type_alu: @@ -164,6 +166,22 @@ gcm_pin_instructions_block(nir_block *block, void *state) default: unreachable("Invalid instruction type in GCM"); } + + if (!(instr->pass_flags & GCM_INSTR_PINNED)) { + /* If this is an unpinned instruction, go ahead and pull it out of + * the program and put it on the instrs list. This has a couple + * of benifits. First, it makes the scheduling algorithm more + * efficient because we can avoid walking over basic blocks and + * pinned instructions. Second, it keeps us from causing linked + * list confusion when we're trying to put everything in its + * proper place at the end of the pass. + * + * Note that we don't use nir_instr_remove here because that also + * cleans up uses and defs and we want to keep that information. + */ + exec_node_remove(&instr->node); + exec_list_push_tail(&state->instrs, &instr->node); + } } return true; @@ -240,15 +258,6 @@ gcm_schedule_early_instr(nir_instr *instr, struct gcm_state *state) nir_foreach_src(instr, gcm_schedule_early_src, state); } -static bool -gcm_schedule_early_block(nir_block *block, void *state) -{ - nir_foreach_instr(block, instr) - gcm_schedule_early_instr(instr, state); - - return true; -} - static void gcm_schedule_late_instr(nir_instr *instr, struct gcm_state *state); @@ -358,31 +367,6 @@ gcm_schedule_late_instr(nir_instr *instr, struct gcm_state *state) nir_foreach_ssa_def(instr, gcm_schedule_late_def, state); } -static bool -gcm_schedule_late_block(nir_block *block, void *void_state) -{ - struct gcm_state *state = void_state; - - nir_foreach_instr_safe(block, instr) { - gcm_schedule_late_instr(instr, state); - - if (!(instr->pass_flags & GCM_INSTR_PINNED)) { - /* If this is an instruction we can move, go ahead and pull it out - * of the program and put it on the instrs list. This keeps us - * from causing linked list confusion when we're trying to put - * everything in its proper place. - * - * Note that we don't use nir_instr_remove here because that also - * cleans up uses and defs and we want to keep that information. - */ - exec_node_remove(&instr->node); - exec_list_push_tail(&state->instrs, &instr->node); - } - } - - return true; -} - static void gcm_place_instr(nir_instr *instr, struct gcm_state *state); @@ -482,8 +466,12 @@ opt_gcm_impl(nir_function_impl *impl) gcm_build_block_info(&impl->body, &state, 0); nir_foreach_block(impl, gcm_pin_instructions_block, &state); - nir_foreach_block(impl, gcm_schedule_early_block, &state); - nir_foreach_block(impl, gcm_schedule_late_block, &state); + + foreach_list_typed(nir_instr, instr, node, &state.instrs) + gcm_schedule_early_instr(instr, &state); + + foreach_list_typed(nir_instr, instr, node, &state.instrs) + gcm_schedule_late_instr(instr, &state); while (!exec_list_is_empty(&state.instrs)) { nir_instr *instr = exec_node_data(nir_instr, |