[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  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

	* 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 <scalar_int_mode> 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 <scalar_int_mode> 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
This commit is contained in:
Richard Sandiford 2017-08-30 11:13:59 +00:00
parent c7ad039d8d
commit 3d88d1cdf2
3 changed files with 85 additions and 95 deletions

View File

@ -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);

View File

@ -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<biv_entry_hasher> *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 <scalar_int_mode> (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 <scalar_int_mode> (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 <scalar_int_mode> (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 <scalar_int_mode> (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)

View File

@ -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 <scalar_int_mode> (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);