[Mesa-dev] [RFC] nir: Improve induction variables detection
Elie Tournier
tournier.elie at gmail.com
Fri Feb 24 12:17:02 UTC 2017
The actual code detect only basic induction variables (i = i +/- c).
I'm working on improve the detection in order to reconize derived induction varibles (j = c1 * i +/- c2).
I obtain the code below.
I'm not sure about the nir_derived_induction_var.
Should I replace "nir_loop_variable *def_outside_loop" by "nir_basic_indiction_var"?
Comments are welcome.
The goal is to implement a strength reduction algo.
Signed-off-by: Elie Tournier <tournier.elie at gmail.com>
---
src/compiler/nir/nir_loop_analyze.c | 46 ++++++++++++++++++++++++++++++++++++-
1 file changed, 45 insertions(+), 1 deletion(-)
diff --git a/src/compiler/nir/nir_loop_analyze.c b/src/compiler/nir/nir_loop_analyze.c
index 6afad9e603..587726914a 100644
--- a/src/compiler/nir/nir_loop_analyze.c
+++ b/src/compiler/nir/nir_loop_analyze.c
@@ -29,10 +29,12 @@ typedef enum {
undefined,
invariant,
not_invariant,
- basic_induction
+ basic_induction,
+ derived_induction
} nir_loop_variable_type;
struct nir_basic_induction_var;
+struct nir_derived_induction_var;
typedef struct {
/* A link for the work list */
@@ -49,6 +51,9 @@ typedef struct {
/* If this is of type basic_induction */
struct nir_basic_induction_var *ind;
+ /* If this is of type derived_induction */
+ struct nir_derived_induction_var *derived_ind;
+
/* True if variable is in an if branch or a nested loop */
bool in_control_flow;
@@ -61,6 +66,14 @@ typedef struct nir_basic_induction_var {
nir_loop_variable *def_outside_loop; /* The phi-src outside the loop */
} nir_basic_induction_var;
+typedef struct nir_derived_induction_var {
+ nir_op alu_op; /* The type of alu-operation */
+ nir_loop_variable *alu_def; /* The def of the alu-operation */
+ nir_loop_variable *invariant_0; /* The invariant alu-operand */
+ nir_loop_variable *invariant_1; /* The invariant alu-operand */
+ nir_loop_variable *def_outside_loop; /* The phi-src outside the loop */
+} nir_derived_induction_var;
+
typedef struct {
/* The loop we store information for */
nir_loop *loop;
@@ -227,6 +240,7 @@ compute_induction_information(loop_info_state *state)
nir_phi_instr *phi = nir_instr_as_phi(var->def->parent_instr);
nir_basic_induction_var *biv = rzalloc(state, nir_basic_induction_var);
+ nir_derived_induction_var *div = rzalloc(state, nir_derived_induction_var);
nir_foreach_phi_src(src, phi) {
nir_loop_variable *src_var = get_loop_var(src->src.ssa, state);
@@ -239,9 +253,11 @@ compute_induction_information(loop_info_state *state)
if (!src_var->in_loop) {
biv->def_outside_loop = src_var;
+ div->def_outside_loop = src_var;
} else if (is_var_alu(src_var)) {
nir_alu_instr *alu = nir_instr_as_alu(src_var->def->parent_instr);
+ /* basic induction variable (i = i +/- c) */
if (nir_op_infos[alu->op].num_inputs == 2) {
biv->alu_def = src_var;
biv->alu_op = alu->op;
@@ -253,6 +269,23 @@ compute_induction_information(loop_info_state *state)
biv->invariant = get_loop_var(alu->src[i].src.ssa, state);
}
}
+ /* derived induction variable (j = c1 * i +/- c2 ) */
+ if (nir_op_infos[alu->op].num_inputs == 3) {
+ div->alu_def = src_var;
+ div->alu_op = alu->op;
+
+ for (unsigned i = 0; i < 3; i++) {
+ /* Is one of the operands const, an other the induction var,
+ * and the last an other const
+ */
+ if (alu->src[i].src.ssa->parent_instr->type == nir_instr_type_load_const &&
+ alu->src[1-i].src.ssa == &phi->dest.ssa &&
+ alu->src[2-i].src.ssa->parent_instr->type == nir_instr_type_load_const) {
+ div->invariant_0 = get_loop_var(alu->src[i].src.ssa, state);
+ div->invariant_1 = get_loop_var(alu->src[2-i].src.ssa, state);
+ }
+ }
+ }
}
}
@@ -265,8 +298,19 @@ compute_induction_information(loop_info_state *state)
var->ind = biv;
found_induction_var = true;
+ } else if (div->alu_def && div->def_outside_loop && div->invariant_0 &&
+ div->invariant_1 && is_var_constant(div->def_outside_loop)) {
+ assert(is_var_constant(div->invariant_0));
+ assert(is_var_constant(div->invariant_1));
+ div->alu_def->type = derived_induction;
+ div->alu_def->derived_ind = div;
+ var->type = derived_induction;
+ var->derived_ind = div;
+
+ found_induction_var = true;
} else {
ralloc_free(biv);
+ ralloc_free(div);
}
}
return found_induction_var;
--
2.11.0
More information about the mesa-dev
mailing list