aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-12-20 12:52:22 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-12-20 12:52:22 +0000
commit84bc717b510cc56f64120dd58c64e1f6ebfad5e3 (patch)
tree453653202c11c4dbbfe83c406937159f5b19a558 /gcc
parent37b2b8f95783b449aca30d32f4c97a4db3bd395e (diff)
downloadgcc-84bc717b510cc56f64120dd58c64e1f6ebfad5e3.zip
gcc-84bc717b510cc56f64120dd58c64e1f6ebfad5e3.tar.gz
gcc-84bc717b510cc56f64120dd58c64e1f6ebfad5e3.tar.bz2
poly_int: REG_OFFSET
This patch changes the type of the reg_attrs offset field from HOST_WIDE_INT to poly_int64 and updates uses accordingly. This includes changing reg_attr_hasher::hash to use inchash. (Doing this has no effect on code generation since the only use of the hasher is to avoid creating duplicate objects.) 2017-12-20 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * rtl.h (reg_attrs::offset): Change from HOST_WIDE_INT to poly_int64. (gen_rtx_REG_offset): Take the offset as a poly_int64. * inchash.h (inchash::hash::add_poly_hwi): New function. * gengtype.c (main): Register poly_int64. * emit-rtl.c (reg_attr_hasher::hash): Use inchash. Treat the offset as a poly_int. (reg_attr_hasher::equal): Use must_eq to compare offsets. (get_reg_attrs, update_reg_offset, gen_rtx_REG_offset): Take the offset as a poly_int64. (set_reg_attrs_from_value): Treat the offset as a poly_int64. * print-rtl.c (print_poly_int): New function. (rtx_writer::print_rtx_operand_code_r): Treat REG_OFFSET as a poly_int. * var-tracking.c (track_offset_p, get_tracked_reg_offset): New functions. (var_reg_set, var_reg_delete_and_set, var_reg_delete): Use them. (same_variable_part_p, track_loc_p): Take the offset as a poly_int64. (vt_get_decl_and_offset): Return the offset as a poly_int64. Enforce track_offset_p for parts of a PARALLEL. (vt_add_function_parameter): Use const_offset for the final offset to track. Use get_tracked_reg_offset for the parts of a PARALLEL. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r255867
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog27
-rw-r--r--gcc/emit-rtl.c20
-rw-r--r--gcc/gengtype.c1
-rw-r--r--gcc/inchash.h8
-rw-r--r--gcc/print-rtl.c25
-rw-r--r--gcc/rtl.h4
-rw-r--r--gcc/var-tracking.c82
7 files changed, 127 insertions, 40 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e99f20c..78cd21e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -2,6 +2,33 @@
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
+ * rtl.h (reg_attrs::offset): Change from HOST_WIDE_INT to poly_int64.
+ (gen_rtx_REG_offset): Take the offset as a poly_int64.
+ * inchash.h (inchash::hash::add_poly_hwi): New function.
+ * gengtype.c (main): Register poly_int64.
+ * emit-rtl.c (reg_attr_hasher::hash): Use inchash. Treat the
+ offset as a poly_int.
+ (reg_attr_hasher::equal): Use must_eq to compare offsets.
+ (get_reg_attrs, update_reg_offset, gen_rtx_REG_offset): Take the
+ offset as a poly_int64.
+ (set_reg_attrs_from_value): Treat the offset as a poly_int64.
+ * print-rtl.c (print_poly_int): New function.
+ (rtx_writer::print_rtx_operand_code_r): Treat REG_OFFSET as
+ a poly_int.
+ * var-tracking.c (track_offset_p, get_tracked_reg_offset): New
+ functions.
+ (var_reg_set, var_reg_delete_and_set, var_reg_delete): Use them.
+ (same_variable_part_p, track_loc_p): Take the offset as a poly_int64.
+ (vt_get_decl_and_offset): Return the offset as a poly_int64.
+ Enforce track_offset_p for parts of a PARALLEL.
+ (vt_add_function_parameter): Use const_offset for the final
+ offset to track. Use get_tracked_reg_offset for the parts
+ of a PARALLEL.
+
+2017-12-20 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
* target.def (truly_noop_truncation): Take poly_uint64s instead of
unsigned ints. Change default to hook_bool_puint64_puint64_true.
* doc/tm.texi: Regenerate.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 799b94a..ff3585e 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -196,7 +196,6 @@ static rtx lookup_const_wide_int (rtx);
#endif
static rtx lookup_const_double (rtx);
static rtx lookup_const_fixed (rtx);
-static reg_attrs *get_reg_attrs (tree, int);
static rtx gen_const_vector (machine_mode, int);
static void copy_rtx_if_shared_1 (rtx *orig);
@@ -393,7 +392,10 @@ reg_attr_hasher::hash (reg_attrs *x)
{
const reg_attrs *const p = x;
- return ((p->offset * 1000) ^ (intptr_t) p->decl);
+ inchash::hash h;
+ h.add_ptr (p->decl);
+ h.add_poly_hwi (p->offset);
+ return h.end ();
}
/* Returns nonzero if the value represented by X is the same as that given by
@@ -405,19 +407,19 @@ reg_attr_hasher::equal (reg_attrs *x, reg_attrs *y)
const reg_attrs *const p = x;
const reg_attrs *const q = y;
- return (p->decl == q->decl && p->offset == q->offset);
+ return (p->decl == q->decl && known_eq (p->offset, q->offset));
}
/* Allocate a new reg_attrs structure and insert it into the hash table if
one identical to it is not already in the table. We are doing this for
MEM of mode MODE. */
static reg_attrs *
-get_reg_attrs (tree decl, int offset)
+get_reg_attrs (tree decl, poly_int64 offset)
{
reg_attrs attrs;
/* If everything is the default, we can just return zero. */
- if (decl == 0 && offset == 0)
+ if (decl == 0 && known_eq (offset, 0))
return 0;
attrs.decl = decl;
@@ -1218,10 +1220,10 @@ reg_is_parm_p (rtx reg)
to the REG_OFFSET. */
static void
-update_reg_offset (rtx new_rtx, rtx reg, int offset)
+update_reg_offset (rtx new_rtx, rtx reg, poly_int64 offset)
{
REG_ATTRS (new_rtx) = get_reg_attrs (REG_EXPR (reg),
- REG_OFFSET (reg) + offset);
+ REG_OFFSET (reg) + offset);
}
/* Generate a register with same attributes as REG, but with OFFSET
@@ -1229,7 +1231,7 @@ update_reg_offset (rtx new_rtx, rtx reg, int offset)
rtx
gen_rtx_REG_offset (rtx reg, machine_mode mode, unsigned int regno,
- int offset)
+ poly_int64 offset)
{
rtx new_rtx = gen_rtx_REG (mode, regno);
@@ -1265,7 +1267,7 @@ adjust_reg_mode (rtx reg, machine_mode mode)
void
set_reg_attrs_from_value (rtx reg, rtx x)
{
- int offset;
+ poly_int64 offset;
bool can_be_reg_pointer = true;
/* Don't call mark_reg_pointer for incompatible pointer sign
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index eca6616..8be4130 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -5190,6 +5190,7 @@ main (int argc, char **argv)
POS_HERE (do_scalar_typedef ("offset_int", &pos));
POS_HERE (do_scalar_typedef ("widest_int", &pos));
POS_HERE (do_scalar_typedef ("int64_t", &pos));
+ POS_HERE (do_scalar_typedef ("poly_int64", &pos));
POS_HERE (do_scalar_typedef ("uint64_t", &pos));
POS_HERE (do_scalar_typedef ("uint8", &pos));
POS_HERE (do_scalar_typedef ("uintptr_t", &pos));
diff --git a/gcc/inchash.h b/gcc/inchash.h
index 73930c2..6144629 100644
--- a/gcc/inchash.h
+++ b/gcc/inchash.h
@@ -63,6 +63,14 @@ class hash
val = iterative_hash_host_wide_int (v, val);
}
+ /* Add polynomial value V, treating each element as a HOST_WIDE_INT. */
+ template<unsigned int N, typename T>
+ void add_poly_hwi (const poly_int_pod<N, T> &v)
+ {
+ for (unsigned int i = 0; i < N; ++i)
+ add_hwi (v.coeffs[i]);
+ }
+
/* Add wide_int-based value V. */
template<typename T>
void add_wide_int (const generic_wide_int<T> &x)
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 66dcf92..7e0a0a0 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -178,6 +178,23 @@ print_mem_expr (FILE *outfile, const_tree expr)
fputc (' ', outfile);
print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags);
}
+
+/* Print X to FILE. */
+
+static void
+print_poly_int (FILE *file, poly_int64 x)
+{
+ HOST_WIDE_INT const_x;
+ if (x.is_constant (&const_x))
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, const_x);
+ else
+ {
+ fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC, x.coeffs[0]);
+ for (int i = 1; i < NUM_POLY_INT_COEFFS; ++i)
+ fprintf (file, ", " HOST_WIDE_INT_PRINT_DEC, x.coeffs[i]);
+ fprintf (file, "]");
+ }
+}
#endif
/* Subroutine of print_rtx_operand for handling code '0'.
@@ -509,9 +526,11 @@ rtx_writer::print_rtx_operand_code_r (const_rtx in_rtx)
if (REG_EXPR (in_rtx))
print_mem_expr (m_outfile, REG_EXPR (in_rtx));
- if (REG_OFFSET (in_rtx))
- fprintf (m_outfile, "+" HOST_WIDE_INT_PRINT_DEC,
- REG_OFFSET (in_rtx));
+ if (maybe_ne (REG_OFFSET (in_rtx), 0))
+ {
+ fprintf (m_outfile, "+");
+ print_poly_int (m_outfile, REG_OFFSET (in_rtx));
+ }
fputs (" ]", m_outfile);
}
if (regno != ORIGINAL_REGNO (in_rtx))
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 7b2560d..ed944a4 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -187,7 +187,7 @@ struct GTY(()) mem_attrs
struct GTY((for_user)) reg_attrs {
tree decl; /* decl corresponding to REG. */
- HOST_WIDE_INT offset; /* Offset from start of DECL. */
+ poly_int64 offset; /* Offset from start of DECL. */
};
/* Common union for an element of an rtx. */
@@ -3023,7 +3023,7 @@ subreg_promoted_mode (rtx x)
extern rtvec gen_rtvec_v (int, rtx *);
extern rtvec gen_rtvec_v (int, rtx_insn **);
extern rtx gen_reg_rtx (machine_mode);
-extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, int);
+extern rtx gen_rtx_REG_offset (rtx, machine_mode, unsigned int, poly_int64);
extern rtx gen_reg_rtx_offset (rtx, machine_mode, int);
extern rtx gen_reg_rtx_and_attrs (rtx);
extern rtx_code_label *gen_label_rtx (void);
diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c
index 4a96a03..2f68298 100644
--- a/gcc/var-tracking.c
+++ b/gcc/var-tracking.c
@@ -673,7 +673,6 @@ static bool dataflow_set_different (dataflow_set *, dataflow_set *);
static void dataflow_set_destroy (dataflow_set *);
static bool track_expr_p (tree, bool);
-static bool same_variable_part_p (rtx, tree, HOST_WIDE_INT);
static void add_uses_1 (rtx *, void *);
static void add_stores (rtx, const_rtx, void *);
static bool compute_bb_dataflow (basic_block);
@@ -704,7 +703,6 @@ static void delete_variable_part (dataflow_set *, rtx,
static void emit_notes_in_bb (basic_block, dataflow_set *);
static void vt_emit_notes (void);
-static bool vt_get_decl_and_offset (rtx, tree *, HOST_WIDE_INT *);
static void vt_add_function_parameters (void);
static bool vt_initialize (void);
static void vt_finalize (void);
@@ -1850,6 +1848,32 @@ var_reg_decl_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
set_variable_part (set, loc, dv, offset, initialized, set_src, iopt);
}
+/* Return true if we should track a location that is OFFSET bytes from
+ a variable. Store the constant offset in *OFFSET_OUT if so. */
+
+static bool
+track_offset_p (poly_int64 offset, HOST_WIDE_INT *offset_out)
+{
+ HOST_WIDE_INT const_offset;
+ if (!offset.is_constant (&const_offset)
+ || !IN_RANGE (const_offset, 0, MAX_VAR_PARTS - 1))
+ return false;
+ *offset_out = const_offset;
+ return true;
+}
+
+/* Return the offset of a register that track_offset_p says we
+ should track. */
+
+static HOST_WIDE_INT
+get_tracked_reg_offset (rtx loc)
+{
+ HOST_WIDE_INT offset;
+ if (!track_offset_p (REG_OFFSET (loc), &offset))
+ gcc_unreachable ();
+ return offset;
+}
+
/* Set the register to contain REG_EXPR (LOC), REG_OFFSET (LOC). */
static void
@@ -1857,7 +1881,7 @@ var_reg_set (dataflow_set *set, rtx loc, enum var_init_status initialized,
rtx set_src)
{
tree decl = REG_EXPR (loc);
- HOST_WIDE_INT offset = REG_OFFSET (loc);
+ HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
var_reg_decl_set (set, loc, initialized,
dv_from_decl (decl), offset, set_src, INSERT);
@@ -1903,7 +1927,7 @@ var_reg_delete_and_set (dataflow_set *set, rtx loc, bool modify,
enum var_init_status initialized, rtx set_src)
{
tree decl = REG_EXPR (loc);
- HOST_WIDE_INT offset = REG_OFFSET (loc);
+ HOST_WIDE_INT offset = get_tracked_reg_offset (loc);
attrs *node, *next;
attrs **nextp;
@@ -1944,10 +1968,10 @@ var_reg_delete (dataflow_set *set, rtx loc, bool clobber)
attrs **nextp = &set->regs[REGNO (loc)];
attrs *node, *next;
- if (clobber)
+ HOST_WIDE_INT offset;
+ if (clobber && track_offset_p (REG_OFFSET (loc), &offset))
{
tree decl = REG_EXPR (loc);
- HOST_WIDE_INT offset = REG_OFFSET (loc);
decl = var_debug_decl (decl);
@@ -5245,10 +5269,10 @@ track_expr_p (tree expr, bool need_rtl)
EXPR+OFFSET. */
static bool
-same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
+same_variable_part_p (rtx loc, tree expr, poly_int64 offset)
{
tree expr2;
- HOST_WIDE_INT offset2;
+ poly_int64 offset2;
if (! DECL_P (expr))
return false;
@@ -5272,7 +5296,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
expr = var_debug_decl (expr);
expr2 = var_debug_decl (expr2);
- return (expr == expr2 && offset == offset2);
+ return (expr == expr2 && known_eq (offset, offset2));
}
/* LOC is a REG or MEM that we would like to track if possible.
@@ -5286,7 +5310,7 @@ same_variable_part_p (rtx loc, tree expr, HOST_WIDE_INT offset)
from EXPR in *OFFSET_OUT (if nonnull). */
static bool
-track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
+track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
machine_mode *mode_out, HOST_WIDE_INT *offset_out)
{
machine_mode mode;
@@ -5320,19 +5344,20 @@ track_loc_p (rtx loc, tree expr, HOST_WIDE_INT offset, bool store_reg_p,
|| (store_reg_p
&& !COMPLEX_MODE_P (DECL_MODE (expr))
&& hard_regno_nregs (REGNO (loc), DECL_MODE (expr)) == 1))
- && offset + byte_lowpart_offset (DECL_MODE (expr), mode) == 0)
+ && known_eq (offset + byte_lowpart_offset (DECL_MODE (expr), mode), 0))
{
mode = DECL_MODE (expr);
offset = 0;
}
- if (offset < 0 || offset >= MAX_VAR_PARTS)
+ HOST_WIDE_INT const_offset;
+ if (!track_offset_p (offset, &const_offset))
return false;
if (mode_out)
*mode_out = mode;
if (offset_out)
- *offset_out = offset;
+ *offset_out = const_offset;
return true;
}
@@ -9561,7 +9586,7 @@ vt_emit_notes (void)
assign declaration to *DECLP and offset to *OFFSETP, and return true. */
static bool
-vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
+vt_get_decl_and_offset (rtx rtl, tree *declp, poly_int64 *offsetp)
{
if (REG_P (rtl))
{
@@ -9587,8 +9612,10 @@ vt_get_decl_and_offset (rtx rtl, tree *declp, HOST_WIDE_INT *offsetp)
decl = REG_EXPR (reg);
if (REG_EXPR (reg) != decl)
break;
- if (REG_OFFSET (reg) < offset)
- offset = REG_OFFSET (reg);
+ HOST_WIDE_INT this_offset;
+ if (!track_offset_p (REG_OFFSET (reg), &this_offset))
+ break;
+ offset = MIN (offset, this_offset);
}
if (i == len)
@@ -9632,7 +9659,7 @@ vt_add_function_parameter (tree parm)
rtx incoming = DECL_INCOMING_RTL (parm);
tree decl;
machine_mode mode;
- HOST_WIDE_INT offset;
+ poly_int64 offset;
dataflow_set *out;
decl_or_value dv;
@@ -9755,7 +9782,8 @@ vt_add_function_parameter (tree parm)
offset = 0;
}
- if (!track_loc_p (incoming, parm, offset, false, &mode, &offset))
+ HOST_WIDE_INT const_offset;
+ if (!track_loc_p (incoming, parm, offset, false, &mode, &const_offset))
return;
out = &VTI (ENTRY_BLOCK_PTR_FOR_FN (cfun))->out;
@@ -9776,7 +9804,7 @@ vt_add_function_parameter (tree parm)
arguments passed by invisible reference aren't dealt with
above: incoming-rtl will have Pmode rather than the
expected mode for the type. */
- if (offset)
+ if (const_offset)
return;
lowpart = var_lowpart (mode, incoming);
@@ -9791,7 +9819,7 @@ vt_add_function_parameter (tree parm)
if (val)
{
preserve_value (val);
- set_variable_part (out, val->val_rtx, dv, offset,
+ set_variable_part (out, val->val_rtx, dv, const_offset,
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
dv = dv_from_value (val->val_rtx);
}
@@ -9812,9 +9840,9 @@ vt_add_function_parameter (tree parm)
{
incoming = var_lowpart (mode, incoming);
gcc_assert (REGNO (incoming) < FIRST_PSEUDO_REGISTER);
- attrs_list_insert (&out->regs[REGNO (incoming)], dv, offset,
+ attrs_list_insert (&out->regs[REGNO (incoming)], dv, const_offset,
incoming);
- set_variable_part (out, incoming, dv, offset,
+ set_variable_part (out, incoming, dv, const_offset,
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
if (dv_is_value_p (dv))
{
@@ -9845,17 +9873,19 @@ vt_add_function_parameter (tree parm)
for (i = 0; i < XVECLEN (incoming, 0); i++)
{
rtx reg = XEXP (XVECEXP (incoming, 0, i), 0);
- offset = REG_OFFSET (reg);
+ /* vt_get_decl_and_offset has already checked that the offset
+ is a valid variable part. */
+ const_offset = get_tracked_reg_offset (reg);
gcc_assert (REGNO (reg) < FIRST_PSEUDO_REGISTER);
- attrs_list_insert (&out->regs[REGNO (reg)], dv, offset, reg);
- set_variable_part (out, reg, dv, offset,
+ attrs_list_insert (&out->regs[REGNO (reg)], dv, const_offset, reg);
+ set_variable_part (out, reg, dv, const_offset,
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
}
}
else if (MEM_P (incoming))
{
incoming = var_lowpart (mode, incoming);
- set_variable_part (out, incoming, dv, offset,
+ set_variable_part (out, incoming, dv, const_offset,
VAR_INIT_STATUS_INITIALIZED, NULL, INSERT);
}
}