From 3d88d1cdf217be025628d77588e2d247feeebcb3 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 30 Aug 2017 11:13:59 +0000 Subject: [PATCH] [36/77] Use scalar_int_mode in the RTL iv routines This patch changes the iv modes in rtx_iv from machine_mode to scalar_int_mode. It also passes the mode of the iv down to subroutines; this avoids the previous situation in which the mode information was sometimes lost and had to be added by the caller on return. Some routines already took a mode argument, but the patch tries to standardise on passing it immediately before the argument it describes. gcc/ 2017-08-30 Richard Sandiford Alan Hayward David Sherwood * cfgloop.h (rtx_iv): Change type of extend_mode and mode to scalar_int_mode. (niter_desc): Likewise mode. (iv_analyze): Add a mode parameter. (biv_p): Likewise. (iv_analyze_expr): Pass the mode paraeter before the rtx it describes and change its type to scalar_int_mode. * loop-iv.c: Update commentary at head of file. (iv_constant): Pass the mode paraeter before the rtx it describes and change its type to scalar_int_mode. Remove VOIDmode handling. (iv_subreg): Change the type of the mode parameter to scalar_int_mode. (iv_extend): Likewise. (shorten_into_mode): Likewise. (iv_add): Use scalar_int_mode. (iv_mult): Likewise. (iv_shift): Likewise. (canonicalize_iv_subregs): Likewise. (get_biv_step_1): Pass the outer_mode parameter before the rtx it describes and change its mode to scalar_int_mode. Also change the type of the returned inner_mode to scalar_int_mode. (get_biv_step): Likewise, turning outer_mode from a pointer into a direct parameter. Update call to get_biv_step_1. (iv_analyze_biv): Add an outer_mode parameter. Update calls to iv_constant and get_biv_step. (iv_analyze_expr): Pass the mode parameter before the rtx it describes and change its type to scalar_int_mode. Don't initialise iv->mode to VOIDmode and remove later checks for its still being VOIDmode. Update calls to iv_analyze_op and iv_analyze_expr. Check is_a when changing the mode under consideration. (iv_analyze_def): Ignore registers that don't have a scalar_int_mode. Update call to iv_analyze_expr. (iv_analyze_op): Add a mode parameter. Reject subregs whose inner register is not also a scalar_int_mode. Update call to iv_analyze_biv. (iv_analyze): Add a mode parameter. Update call to iv_analyze_op. (biv_p): Add a mode parameter. Update call to iv_analyze_biv. (iv_number_of_iterations): Use is_a instead of separate mode class checks. Update calls to iv_analyze. Remove fix-up of VOIDmodes after iv_analyze_biv. * loop-unroll.c (analyze_iv_to_split_insn): Reject registers that don't have a scalar_int_mode. Update call to biv_p. From-SVN: r251488 --- gcc/cfgloop.h | 12 ++-- gcc/loop-iv.c | 163 +++++++++++++++++++++------------------------- gcc/loop-unroll.c | 5 +- 3 files changed, 85 insertions(+), 95 deletions(-) diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index e7ffa236437..fcf366745df 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -421,10 +421,10 @@ struct rtx_iv rtx delta, mult; /* The mode it is extended to. */ - machine_mode extend_mode; + scalar_int_mode extend_mode; /* The mode the variable iterates in. */ - machine_mode mode; + scalar_int_mode mode; /* Whether the first iteration needs to be handled specially. */ unsigned first_special : 1; @@ -465,19 +465,19 @@ struct GTY(()) niter_desc bool signed_p; /* The mode in that niter_expr should be computed. */ - machine_mode mode; + scalar_int_mode mode; /* The number of iterations of the loop. */ rtx niter_expr; }; extern void iv_analysis_loop_init (struct loop *); -extern bool iv_analyze (rtx_insn *, rtx, struct rtx_iv *); +extern bool iv_analyze (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); extern bool iv_analyze_result (rtx_insn *, rtx, struct rtx_iv *); -extern bool iv_analyze_expr (rtx_insn *, rtx, machine_mode, +extern bool iv_analyze_expr (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); extern rtx get_iv_value (struct rtx_iv *, rtx); -extern bool biv_p (rtx_insn *, rtx); +extern bool biv_p (rtx_insn *, scalar_int_mode, rtx); extern void find_simple_exit (struct loop *, struct niter_desc *); extern void iv_analysis_done (void); diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index 61074e3fb1a..1d0c66f2b2f 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -35,16 +35,17 @@ along with GCC; see the file COPYING3. If not see The available functions are: - iv_analyze (insn, reg, iv): Stores the description of the induction variable - corresponding to the use of register REG in INSN to IV. Returns true if - REG is an induction variable in INSN. false otherwise. - If use of REG is not found in INSN, following insns are scanned (so that - we may call this function on insn returned by get_condition). + iv_analyze (insn, mode, reg, iv): Stores the description of the induction + variable corresponding to the use of register REG in INSN to IV, given + that REG has mode MODE. Returns true if REG is an induction variable + in INSN. false otherwise. If a use of REG is not found in INSN, + the following insns are scanned (so that we may call this function + on insns returned by get_condition). iv_analyze_result (insn, def, iv): Stores to IV the description of the iv corresponding to DEF, which is a register defined in INSN. - iv_analyze_expr (insn, rhs, mode, iv): Stores to IV the description of iv + iv_analyze_expr (insn, mode, expr, iv): Stores to IV the description of iv corresponding to expression EXPR evaluated at INSN. All registers used bu - EXPR must also be used in INSN. + EXPR must also be used in INSN. MODE is the mode of EXPR. */ #include "config.h" @@ -133,7 +134,7 @@ biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r) static hash_table *bivs; -static bool iv_analyze_op (rtx_insn *, rtx, struct rtx_iv *); +static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, struct rtx_iv *); /* Return the RTX code corresponding to the IV extend code EXTEND. */ static inline enum rtx_code @@ -383,11 +384,8 @@ iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def) consistency with other iv manipulation functions that may fail). */ static bool -iv_constant (struct rtx_iv *iv, rtx cst, machine_mode mode) +iv_constant (struct rtx_iv *iv, scalar_int_mode mode, rtx cst) { - if (mode == VOIDmode) - mode = GET_MODE (cst); - iv->mode = mode; iv->base = cst; iv->step = const0_rtx; @@ -403,7 +401,7 @@ iv_constant (struct rtx_iv *iv, rtx cst, machine_mode mode) /* Evaluates application of subreg to MODE on IV. */ static bool -iv_subreg (struct rtx_iv *iv, machine_mode mode) +iv_subreg (struct rtx_iv *iv, scalar_int_mode mode) { /* If iv is invariant, just calculate the new value. */ if (iv->step == const0_rtx @@ -445,7 +443,7 @@ iv_subreg (struct rtx_iv *iv, machine_mode mode) /* Evaluates application of EXTEND to MODE on IV. */ static bool -iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, machine_mode mode) +iv_extend (struct rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode) { /* If iv is invariant, just calculate the new value. */ if (iv->step == const0_rtx @@ -508,7 +506,7 @@ iv_neg (struct rtx_iv *iv) static bool iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op) { - machine_mode mode; + scalar_int_mode mode; rtx arg; /* Extend the constant to extend_mode of the other operand if necessary. */ @@ -578,7 +576,7 @@ iv_add (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code op) static bool iv_mult (struct rtx_iv *iv, rtx mby) { - machine_mode mode = iv->extend_mode; + scalar_int_mode mode = iv->extend_mode; if (GET_MODE (mby) != VOIDmode && GET_MODE (mby) != mode) @@ -603,7 +601,7 @@ iv_mult (struct rtx_iv *iv, rtx mby) static bool iv_shift (struct rtx_iv *iv, rtx mby) { - machine_mode mode = iv->extend_mode; + scalar_int_mode mode = iv->extend_mode; if (GET_MODE (mby) != VOIDmode && GET_MODE (mby) != mode) @@ -628,9 +626,9 @@ iv_shift (struct rtx_iv *iv, rtx mby) at get_biv_step. */ static bool -get_biv_step_1 (df_ref def, rtx reg, - rtx *inner_step, machine_mode *inner_mode, - enum iv_extend_code *extend, machine_mode outer_mode, +get_biv_step_1 (df_ref def, scalar_int_mode outer_mode, rtx reg, + rtx *inner_step, scalar_int_mode *inner_mode, + enum iv_extend_code *extend, rtx *outer_step) { rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX; @@ -732,8 +730,8 @@ get_biv_step_1 (df_ref def, rtx reg, *inner_mode = outer_mode; *outer_step = const0_rtx; } - else if (!get_biv_step_1 (next_def, reg, - inner_step, inner_mode, extend, outer_mode, + else if (!get_biv_step_1 (next_def, outer_mode, reg, + inner_step, inner_mode, extend, outer_step)) return false; @@ -793,19 +791,17 @@ get_biv_step_1 (df_ref def, rtx reg, LAST_DEF is the definition of REG that dominates loop latch. */ static bool -get_biv_step (df_ref last_def, rtx reg, rtx *inner_step, - machine_mode *inner_mode, enum iv_extend_code *extend, - machine_mode *outer_mode, rtx *outer_step) +get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg, + rtx *inner_step, scalar_int_mode *inner_mode, + enum iv_extend_code *extend, rtx *outer_step) { - *outer_mode = GET_MODE (reg); - - if (!get_biv_step_1 (last_def, reg, - inner_step, inner_mode, extend, *outer_mode, + if (!get_biv_step_1 (last_def, outer_mode, reg, + inner_step, inner_mode, extend, outer_step)) return false; - gcc_assert ((*inner_mode == *outer_mode) != (*extend != IV_UNKNOWN_EXTEND)); - gcc_assert (*inner_mode != *outer_mode || *outer_step == const0_rtx); + gcc_assert ((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND)); + gcc_assert (*inner_mode != outer_mode || *outer_step == const0_rtx); return true; } @@ -850,13 +846,13 @@ record_biv (rtx def, struct rtx_iv *iv) } /* Determines whether DEF is a biv and if so, stores its description - to *IV. */ + to *IV. OUTER_MODE is the mode of DEF. */ static bool -iv_analyze_biv (rtx def, struct rtx_iv *iv) +iv_analyze_biv (scalar_int_mode outer_mode, rtx def, struct rtx_iv *iv) { rtx inner_step, outer_step; - machine_mode inner_mode, outer_mode; + scalar_int_mode inner_mode; enum iv_extend_code extend; df_ref last_def; @@ -872,7 +868,7 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv) if (!CONSTANT_P (def)) return false; - return iv_constant (iv, def, VOIDmode); + return iv_constant (iv, outer_mode, def); } if (!latch_dominating_def (def, &last_def)) @@ -883,7 +879,7 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv) } if (!last_def) - return iv_constant (iv, def, VOIDmode); + return iv_constant (iv, outer_mode, def); if (analyzed_for_bivness_p (def, iv)) { @@ -892,8 +888,8 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv) return iv->base != NULL_RTX; } - if (!get_biv_step (last_def, def, &inner_step, &inner_mode, &extend, - &outer_mode, &outer_step)) + if (!get_biv_step (last_def, outer_mode, def, &inner_step, &inner_mode, + &extend, &outer_step)) { iv->base = NULL_RTX; goto end; @@ -930,16 +926,15 @@ iv_analyze_biv (rtx def, struct rtx_iv *iv) The mode of the induction variable is MODE. */ bool -iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode, +iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs, struct rtx_iv *iv) { rtx mby = NULL_RTX; rtx op0 = NULL_RTX, op1 = NULL_RTX; struct rtx_iv iv0, iv1; enum rtx_code code = GET_CODE (rhs); - machine_mode omode = mode; + scalar_int_mode omode = mode; - iv->mode = VOIDmode; iv->base = NULL_RTX; iv->step = NULL_RTX; @@ -948,18 +943,7 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode, if (CONSTANT_P (rhs) || REG_P (rhs) || code == SUBREG) - { - if (!iv_analyze_op (insn, rhs, iv)) - return false; - - if (iv->mode == VOIDmode) - { - iv->mode = mode; - iv->extend_mode = mode; - } - - return true; - } + return iv_analyze_op (insn, mode, rhs, iv); switch (code) { @@ -971,7 +955,9 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode, case ZERO_EXTEND: case NEG: op0 = XEXP (rhs, 0); - omode = GET_MODE (op0); + /* We don't know how many bits there are in a sign-extended constant. */ + if (!is_a (GET_MODE (op0), &omode)) + return false; break; case PLUS: @@ -1001,11 +987,11 @@ iv_analyze_expr (rtx_insn *insn, rtx rhs, machine_mode mode, } if (op0 - && !iv_analyze_expr (insn, op0, omode, &iv0)) + && !iv_analyze_expr (insn, omode, op0, &iv0)) return false; if (op1 - && !iv_analyze_expr (insn, op1, omode, &iv1)) + && !iv_analyze_expr (insn, omode, op1, &iv1)) return false; switch (code) @@ -1075,11 +1061,11 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv) return iv->base != NULL_RTX; } - iv->mode = VOIDmode; iv->base = NULL_RTX; iv->step = NULL_RTX; - if (!REG_P (reg)) + scalar_int_mode mode; + if (!REG_P (reg) || !is_a (GET_MODE (reg), &mode)) return false; set = single_set (insn); @@ -1096,7 +1082,7 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv) else rhs = SET_SRC (set); - iv_analyze_expr (insn, rhs, GET_MODE (reg), iv); + iv_analyze_expr (insn, mode, rhs, iv); record_iv (def, iv); if (dump_file) @@ -1112,10 +1098,11 @@ iv_analyze_def (df_ref def, struct rtx_iv *iv) return iv->base != NULL_RTX; } -/* Analyzes operand OP of INSN and stores the result to *IV. */ +/* Analyzes operand OP of INSN and stores the result to *IV. MODE is the + mode of OP. */ static bool -iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv) +iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, struct rtx_iv *iv) { df_ref def = NULL; enum iv_grd_result res; @@ -1132,13 +1119,15 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv) res = GRD_INVARIANT; else if (GET_CODE (op) == SUBREG) { - if (!subreg_lowpart_p (op)) + scalar_int_mode inner_mode; + if (!subreg_lowpart_p (op) + || !is_a (GET_MODE (SUBREG_REG (op)), &inner_mode)) return false; - if (!iv_analyze_op (insn, SUBREG_REG (op), iv)) + if (!iv_analyze_op (insn, inner_mode, SUBREG_REG (op), iv)) return false; - return iv_subreg (iv, GET_MODE (op)); + return iv_subreg (iv, mode); } else { @@ -1153,7 +1142,7 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv) if (res == GRD_INVARIANT) { - iv_constant (iv, op, VOIDmode); + iv_constant (iv, mode, op); if (dump_file) { @@ -1165,15 +1154,16 @@ iv_analyze_op (rtx_insn *insn, rtx op, struct rtx_iv *iv) } if (res == GRD_MAYBE_BIV) - return iv_analyze_biv (op, iv); + return iv_analyze_biv (mode, op, iv); return iv_analyze_def (def, iv); } -/* Analyzes value VAL at INSN and stores the result to *IV. */ +/* Analyzes value VAL at INSN and stores the result to *IV. MODE is the + mode of VAL. */ bool -iv_analyze (rtx_insn *insn, rtx val, struct rtx_iv *iv) +iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, struct rtx_iv *iv) { rtx reg; @@ -1192,7 +1182,7 @@ iv_analyze (rtx_insn *insn, rtx val, struct rtx_iv *iv) insn = NEXT_INSN (insn); } - return iv_analyze_op (insn, val, iv); + return iv_analyze_op (insn, mode, val, iv); } /* Analyzes definition of DEF in INSN and stores the result to IV. */ @@ -1210,11 +1200,13 @@ iv_analyze_result (rtx_insn *insn, rtx def, struct rtx_iv *iv) } /* Checks whether definition of register REG in INSN is a basic induction - variable. IV analysis must have been initialized (via a call to + variable. MODE is the mode of REG. + + IV analysis must have been initialized (via a call to iv_analysis_loop_init) for this function to produce a result. */ bool -biv_p (rtx_insn *insn, rtx reg) +biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg) { struct rtx_iv iv; df_ref def, last_def; @@ -1229,7 +1221,7 @@ biv_p (rtx_insn *insn, rtx reg) if (last_def != def) return false; - if (!iv_analyze_biv (reg, &iv)) + if (!iv_analyze_biv (mode, reg, &iv)) return false; return iv.step != const0_rtx; @@ -2078,7 +2070,7 @@ simplify_using_initial_values (struct loop *loop, enum rtx_code op, rtx *expr) is SIGNED_P to DESC. */ static void -shorten_into_mode (struct rtx_iv *iv, machine_mode mode, +shorten_into_mode (struct rtx_iv *iv, scalar_int_mode mode, enum rtx_code cond, bool signed_p, struct niter_desc *desc) { rtx mmin, mmax, cond_over, cond_under; @@ -2140,7 +2132,7 @@ static bool canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1, enum rtx_code cond, struct niter_desc *desc) { - machine_mode comp_mode; + scalar_int_mode comp_mode; bool signed_p; /* If the ivs behave specially in the first iteration, or are @@ -2318,7 +2310,8 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition, struct rtx_iv iv0, iv1; rtx assumption, may_not_xform; enum rtx_code cond; - machine_mode mode, comp_mode; + machine_mode nonvoid_mode; + scalar_int_mode comp_mode; rtx mmin, mmax, mode_mmin, mode_mmax; uint64_t s, size, d, inv, max, up, down; int64_t inc, step_val; @@ -2343,28 +2336,24 @@ iv_number_of_iterations (struct loop *loop, rtx_insn *insn, rtx condition, cond = GET_CODE (condition); gcc_assert (COMPARISON_P (condition)); - mode = GET_MODE (XEXP (condition, 0)); - if (mode == VOIDmode) - mode = GET_MODE (XEXP (condition, 1)); + nonvoid_mode = GET_MODE (XEXP (condition, 0)); + if (nonvoid_mode == VOIDmode) + nonvoid_mode = GET_MODE (XEXP (condition, 1)); /* The constant comparisons should be folded. */ - gcc_assert (mode != VOIDmode); + gcc_assert (nonvoid_mode != VOIDmode); /* We only handle integers or pointers. */ - if (GET_MODE_CLASS (mode) != MODE_INT - && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT) + scalar_int_mode mode; + if (!is_a (nonvoid_mode, &mode)) goto fail; op0 = XEXP (condition, 0); - if (!iv_analyze (insn, op0, &iv0)) + if (!iv_analyze (insn, mode, op0, &iv0)) goto fail; - if (iv0.extend_mode == VOIDmode) - iv0.mode = iv0.extend_mode = mode; op1 = XEXP (condition, 1); - if (!iv_analyze (insn, op1, &iv1)) + if (!iv_analyze (insn, mode, op1, &iv1)) goto fail; - if (iv1.extend_mode == VOIDmode) - iv1.mode = iv1.extend_mode = mode; if (GET_MODE_BITSIZE (iv0.extend_mode) > HOST_BITS_PER_WIDE_INT || GET_MODE_BITSIZE (iv1.extend_mode) > HOST_BITS_PER_WIDE_INT) diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c index 84145bb4a4f..8cf305b24c5 100644 --- a/gcc/loop-unroll.c +++ b/gcc/loop-unroll.c @@ -1509,6 +1509,7 @@ analyze_iv_to_split_insn (rtx_insn *insn) rtx set, dest; struct rtx_iv iv; struct iv_to_split *ivts; + scalar_int_mode mode; bool ok; /* For now we just split the basic induction variables. Later this may be @@ -1518,10 +1519,10 @@ analyze_iv_to_split_insn (rtx_insn *insn) return NULL; dest = SET_DEST (set); - if (!REG_P (dest)) + if (!REG_P (dest) || !is_a (GET_MODE (dest), &mode)) return NULL; - if (!biv_p (insn, dest)) + if (!biv_p (insn, mode, dest)) return NULL; ok = iv_analyze_result (insn, dest, &iv); -- 2.30.2