/* Compute different info about registers.
- Copyright (C) 1987-2016 Free Software Foundation, Inc.
+ Copyright (C) 1987-2019 Free Software Foundation, Inc.
This file is part of GCC.
#include "rtl.h"
#include "tree.h"
#include "df.h"
+#include "memmodel.h"
#include "tm_p.h"
#include "insn-config.h"
#include "regs.h"
}
COPY_HARD_REG_SET (call_fixed_reg_set, fixed_reg_set);
+ COPY_HARD_REG_SET (fixed_nonglobal_reg_set, fixed_reg_set);
/* Preserve global registers if called more than once. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
{
- HARD_REG_SET ok_regs;
+ HARD_REG_SET ok_regs, ok_regs2;
CLEAR_HARD_REG_SET (ok_regs);
+ CLEAR_HARD_REG_SET (ok_regs2);
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
- if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, (machine_mode) m))
- SET_HARD_REG_BIT (ok_regs, j);
+ if (!TEST_HARD_REG_BIT (fixed_nonglobal_reg_set, j)
+ && targetm.hard_regno_mode_ok (j, (machine_mode) m))
+ {
+ SET_HARD_REG_BIT (ok_regs, j);
+ if (!fixed_regs[j])
+ SET_HARD_REG_BIT (ok_regs2, j);
+ }
for (i = 0; i < N_REG_CLASSES; i++)
if ((targetm.class_max_nregs ((reg_class_t) i, (machine_mode) m)
<= reg_class_size[i])
&& hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
{
- contains_reg_of_mode [i][m] = 1;
- have_regs_of_mode [m] = 1;
+ contains_reg_of_mode[i][m] = 1;
+ if (hard_reg_set_intersect_p (ok_regs2, reg_class_contents[i]))
+ {
+ have_regs_of_mode[m] = 1;
+ contains_allocatable_reg_of_mode[i][m] = 1;
+ }
}
}
}
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
for (j = 0; j < MAX_MACHINE_MODE; j++)
- hard_regno_nregs[i][j] = HARD_REGNO_NREGS (i, (machine_mode)j);
+ this_target_regs->x_hard_regno_nregs[i][j]
+ = targetm.hard_regno_nregs (i, (machine_mode) j);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
if it is suitable, otherwise fall back on word_mode. */
if (reg_raw_mode[i] == VOIDmode)
{
- if (i > 0 && hard_regno_nregs[i][reg_raw_mode[i - 1]] == 1)
+ if (i > 0 && hard_regno_nregs (i, reg_raw_mode[i - 1]) == 1)
reg_raw_mode[i] = reg_raw_mode[i - 1];
else
reg_raw_mode[i] = word_mode;
/* We first look for the largest integer mode that can be validly
held in REGNO. If none, we look for the largest floating-point mode.
- If we still didn't find a valid mode, try CCmode. */
-
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if ((unsigned) hard_regno_nregs[regno][mode] == nregs
- && HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+ If we still didn't find a valid mode, try CCmode.
+
+ The tests use maybe_gt rather than known_gt because we want (for example)
+ N V4SFs to win over plain V4SF even though N might be 1. */
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_INT)
+ if (hard_regno_nregs (regno, mode) == nregs
+ && targetm.hard_regno_mode_ok (regno, mode)
+ && (!call_saved
+ || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+ && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
found_mode = mode;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if ((unsigned) hard_regno_nregs[regno][mode] == nregs
- && HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_FLOAT)
+ if (hard_regno_nregs (regno, mode) == nregs
+ && targetm.hard_regno_mode_ok (regno, mode)
+ && (!call_saved
+ || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+ && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
found_mode = mode;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if ((unsigned) hard_regno_nregs[regno][mode] == nregs
- && HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_FLOAT)
+ if (hard_regno_nregs (regno, mode) == nregs
+ && targetm.hard_regno_mode_ok (regno, mode)
+ && (!call_saved
+ || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+ && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
found_mode = mode;
- for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
- mode != VOIDmode;
- mode = GET_MODE_WIDER_MODE (mode))
- if ((unsigned) hard_regno_nregs[regno][mode] == nregs
- && HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode))
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (found_mode))
+ FOR_EACH_MODE_IN_CLASS (mode, MODE_VECTOR_INT)
+ if (hard_regno_nregs (regno, mode) == nregs
+ && targetm.hard_regno_mode_ok (regno, mode)
+ && (!call_saved
+ || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode))
+ && maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (found_mode)))
found_mode = mode;
if (found_mode != VOIDmode)
for (m = (unsigned int) CCmode; m < (unsigned int) NUM_MACHINE_MODES; ++m)
{
mode = (machine_mode) m;
- if ((unsigned) hard_regno_nregs[regno][mode] == nregs
- && HARD_REGNO_MODE_OK (regno, mode)
- && (! call_saved || ! HARD_REGNO_CALL_PART_CLOBBERED (regno, mode)))
+ if (hard_regno_nregs (regno, mode) == nregs
+ && targetm.hard_regno_mode_ok (regno, mode)
+ && (!call_saved
+ || !targetm.hard_regno_call_part_clobbered (NULL, regno, mode)))
return mode;
}
if (global_regs[i])
{
+ auto_diagnostic_group d;
warning_at (loc, 0,
"register of %qD used for multiple global register variables",
decl);
reg_scan_mark_refs (XEXP (XEXP (x, 0), 0), insn);
break;
+ case CLOBBER_HIGH:
+ gcc_assert (!(MEM_P (XEXP (x, 0))));
+ break;
+
case SET:
/* Count a set of the destination if it is a register. */
for (dest = SET_DEST (x);
if (REG_P (dest) && !REG_ATTRS (dest))
set_reg_attrs_from_value (dest, SET_SRC (x));
- /* ... fall through ... */
+ /* fall through */
default:
{
inline hashval_t
simplifiable_subregs_hasher::hash (const simplifiable_subreg *value)
{
- return value->shape.unique_id ();
+ inchash::hash h;
+ h.add_hwi (value->shape.unique_id ());
+ return h.end ();
}
inline bool
if (!this_target_hard_regs->x_simplifiable_subregs)
this_target_hard_regs->x_simplifiable_subregs
= new hash_table <simplifiable_subregs_hasher> (30);
+ inchash::hash h;
+ h.add_hwi (shape.unique_id ());
simplifiable_subreg **slot
= (this_target_hard_regs->x_simplifiable_subregs
- ->find_slot_with_hash (&shape, shape.unique_id (), INSERT));
+ ->find_slot_with_hash (&shape, h.end (), INSERT));
if (!*slot)
{
simplifiable_subreg *info = new simplifiable_subreg (shape);
for (unsigned int i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
- if (HARD_REGNO_MODE_OK (i, shape.inner_mode)
+ if (targetm.hard_regno_mode_ok (i, shape.inner_mode)
&& simplify_subreg_regno (i, shape.inner_mode, shape.offset,
shape.outer_mode) >= 0)
SET_HARD_REG_BIT (info->simplifiable_regs, i);
subregs will be invalid.
This relies on the fact that we've already been passed
- SUBREG with PARTIAL_DEF set to false. */
- unsigned int size = MAX (REGMODE_NATURAL_SIZE (shape.inner_mode),
- GET_MODE_SIZE (shape.outer_mode));
- gcc_checking_assert (size < GET_MODE_SIZE (shape.inner_mode));
- if (shape.offset >= size)
+ SUBREG with PARTIAL_DEF set to false.
+
+ The size of the outer mode must ordered wrt the size of the
+ inner mode's registers, since otherwise we wouldn't know at
+ compile time how many registers the outer mode occupies. */
+ poly_uint64 size = ordered_max (REGMODE_NATURAL_SIZE (shape.inner_mode),
+ GET_MODE_SIZE (shape.outer_mode));
+ gcc_checking_assert (known_lt (size, GET_MODE_SIZE (shape.inner_mode)));
+ if (known_ge (shape.offset, size))
shape.offset -= size;
else
shape.offset += size;
df_ref def;
FOR_EACH_INSN_DEF (def, insn)
if (DF_REF_FLAGS_IS_SET (def, DF_REF_PARTIAL)
- && df_read_modify_subreg_p (DF_REF_REG (def)))
+ && read_modify_subreg_p (DF_REF_REG (def)))
record_subregs_of_mode (DF_REF_REG (def), true);
}
}