[Mesa-dev] [RFC] nir: Improve induction variables detection
tournier.elie
tournier.elie at gmail.com
Mon Mar 6 18:03:42 UTC 2017
Any comments, tips before I go to deep in the code?
On 24 February 2017 at 12:17, Elie Tournier <tournier.elie at gmail.com> wrote:
> 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