+2017-08-22 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * rtl.h (paradoxical_subreg_p): Define inline, and add a version
+ that takes the outer and inner modes.
+ * doc/rtl.texi: Use paradoxical_subreg_p instead of a GET_MODE_SIZE
+ comparison as the canonical test for a paradoxical subreg.
+ * combine.c (simplify_set): Use paradoxical_subreg_p.
+ (make_extraction): Likewise.
+ (force_to_mode): Likewise.
+ (rtx_equal_for_field_assignment_p): Likewise.
+ (gen_lowpart_for_combine): Likewise.
+ (simplify_comparison): Likewise.
+ * cse.c (equiv_constant): Likewise.
+ * expmed.c (store_bit_field_1): Likewise.
+ * final.c (alter_subreg): Likewise.
+ * fwprop.c (propagate_rtx): Likewise.
+ (forward_propagate_subreg): Likewise.
+ * ira-conflicts.c (ira_build_conflicts): Likewise.
+ * lower-subreg.c (simplify_gen_subreg_concatn): Likewise.
+ * lra-constraints.c (curr_insn_transform): Likewise.
+ (split_reg): Likewise.
+ * lra-eliminations.c (move_plus_up): Likewise.
+ (lra_eliminate_regs_1): Likewise.
+ * recog.c (general_operand): Likewise.
+ * ree.c (combine_reaching_defs): Likewise.
+ * reload.c (push_reload): Likewise.
+ (find_reloads): Likewise.
+ * reload1.c (elimination_effects): Likewise.
+ (compute_reload_subreg_offset): Likewise.
+ (choose_reload_regs): Likewise.
+ * rtlanal.c (subreg_lsb_1): Likewise.
+ * simplify-rtx.c (simplify_unary_operation_1): Likewise.
+ (simplify_subreg): Likewise.
+ * var-tracking.c (track_loc_p): Likewise.
+ * emit-rtl.c (byte_lowpart_offset): Likewise.
+ (paradoxical_subreg_p): Delete out-of-line definition.
+
2017-08-22 Jeff Law <law@redhat.com>
PR tree-optimization/81741
/ UNITS_PER_WORD)
== ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))
+ (UNITS_PER_WORD - 1)) / UNITS_PER_WORD))
- && (WORD_REGISTER_OPERATIONS
- || (GET_MODE_SIZE (GET_MODE (src))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (src)))))
+ && (WORD_REGISTER_OPERATIONS || !paradoxical_subreg_p (src))
#ifdef CANNOT_CHANGE_MODE_CLASS
&& ! (REG_P (dest) && REGNO (dest) < FIRST_PSEUDO_REGISTER
&& REG_CANNOT_CHANGE_MODE_P (REGNO (dest),
: BITS_PER_UNIT)) == 0
/* We can't do this if we are widening INNER_MODE (it
may not be aligned, for one thing). */
- && GET_MODE_PRECISION (inner_mode) >= GET_MODE_PRECISION (tmode)
+ && !paradoxical_subreg_p (tmode, inner_mode)
&& (inner_mode == tmode
|| (! mode_dependent_address_p (XEXP (inner, 0),
MEM_ADDR_SPACE (inner))
/* If bytes are big endian and we had a paradoxical SUBREG, we must
adjust OFFSET to compensate. */
if (BYTES_BIG_ENDIAN
- && GET_MODE_SIZE (inner_mode) < GET_MODE_SIZE (is_mode))
+ && paradoxical_subreg_p (is_mode, inner_mode))
offset -= GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (inner_mode);
/* We can now move to the desired byte. */
/* If X is narrower than MODE and we want all the bits in X's mode, just
get X in the proper mode. */
- if (GET_MODE_SIZE (GET_MODE (x)) < GET_MODE_SIZE (mode)
+ if (paradoxical_subreg_p (mode, GET_MODE (x))
&& (GET_MODE_MASK (GET_MODE (x)) & ~mask) == 0)
return gen_lowpart (mode, x);
{
if (widen_x && GET_MODE (x) != GET_MODE (y))
{
- if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (GET_MODE (y)))
+ if (paradoxical_subreg_p (GET_MODE (x), GET_MODE (y)))
return 0;
if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN)
return 0;
/* If we want to refer to something bigger than the original memref,
generate a paradoxical subreg instead. That will force a reload
of the original memref X. */
- if (isize < osize)
+ if (paradoxical_subreg_p (omode, imode))
return gen_rtx_SUBREG (omode, x, 0);
if (WORDS_BIG_ENDIAN)
/* If the inner mode is narrower and we are extracting the low part,
we can treat the SUBREG as if it were a ZERO_EXTEND. */
- if (subreg_lowpart_p (op0)
- && GET_MODE_PRECISION (GET_MODE (SUBREG_REG (op0))) < mode_width)
+ if (paradoxical_subreg_p (op0))
;
else if (subreg_lowpart_p (op0)
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
the subreg. Note that the upper bits of paradoxical subregs
are undefined, so they cannot be said to equal anything. */
if (REG_P (SUBREG_REG (x))
- && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (imode)
+ && !paradoxical_subreg_p (x)
&& (new_rtx = equiv_constant (SUBREG_REG (x))) != 0)
return simplify_subreg (mode, new_rtx, imode, SUBREG_BYTE (x));
class of @code{subreg} is:
@smallexample
-GET_MODE_SIZE (@var{m1}) > GET_MODE_SIZE (@var{m2})
+paradoxical_subreg_p (@var{m1}, @var{m2})
@end smallexample
Paradoxical @code{subreg}s can be used as both lvalues and rvalues.
byte_lowpart_offset (machine_mode outer_mode,
machine_mode inner_mode)
{
- if (GET_MODE_SIZE (outer_mode) < GET_MODE_SIZE (inner_mode))
- return subreg_lowpart_offset (outer_mode, inner_mode);
- else
+ if (paradoxical_subreg_p (outer_mode, inner_mode))
return -subreg_lowpart_offset (inner_mode, outer_mode);
+ else
+ return subreg_lowpart_offset (outer_mode, inner_mode);
}
\f
/* Generate a REG rtx for a new pseudo register of mode MODE.
return (subreg_lowpart_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)))
== SUBREG_BYTE (x));
}
-
-/* Return true if X is a paradoxical subreg, false otherwise. */
-bool
-paradoxical_subreg_p (const_rtx x)
-{
- if (GET_CODE (x) != SUBREG)
- return false;
- return (GET_MODE_PRECISION (GET_MODE (x))
- > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (x))));
-}
\f
/* Return subword OFFSET of operand OP.
The word number, OFFSET, is interpreted as the word number starting
int byte_offset = 0;
/* Paradoxical subregs need special handling on big-endian machines. */
- if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
+ if (paradoxical_subreg_p (op0))
{
int difference = inner_mode_size - outer_mode_size;
/* For paradoxical subregs on big-endian machines, SUBREG_BYTE
contains 0 instead of the proper offset. See simplify_subreg. */
- if (offset == 0
- && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
+ if (paradoxical_subreg_p (x))
{
int difference = GET_MODE_SIZE (GET_MODE (y))
- GET_MODE_SIZE (GET_MODE (x));
|| CONSTANT_P (new_rtx)
|| (GET_CODE (new_rtx) == SUBREG
&& REG_P (SUBREG_REG (new_rtx))
- && (GET_MODE_SIZE (mode)
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (new_rtx))))))
+ && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (new_rtx)))))
flags |= PR_CAN_APPEAR;
if (!varying_mem_p (new_rtx))
flags |= PR_HANDLE_MEM;
|| !REG_P (SET_DEST (def_set)))
return false;
- /* If this is a paradoxical SUBREG... */
- if (GET_MODE_SIZE (use_mode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (use_reg))))
+ if (paradoxical_subreg_p (use_reg))
{
/* If this is a paradoxical SUBREG, we have no idea what value the
extra bits would have. However, if the operand is equivalent to
cannot be accessed in the widest mode. */
machine_mode outer_mode = ALLOCNO_WMODE (a);
machine_mode inner_mode = ALLOCNO_MODE (a);
- if (GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (inner_mode))
+ if (paradoxical_subreg_p (outer_mode, inner_mode))
{
enum reg_class aclass = ALLOCNO_CLASS (a);
for (int j = ira_class_hard_regs_num[aclass] - 1; j >= 0; --j)
if (op2 == NULL_RTX)
{
/* We don't handle paradoxical subregs here. */
- gcc_assert (GET_MODE_SIZE (outermode)
- <= GET_MODE_SIZE (GET_MODE (op)));
- gcc_assert (GET_MODE_SIZE (GET_MODE (op))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))));
+ gcc_assert (!paradoxical_subreg_p (outermode, GET_MODE (op)));
+ gcc_assert (!paradoxical_subreg_p (op));
op2 = simplify_subreg_concatn (outermode, SUBREG_REG (op),
byte + SUBREG_BYTE (op));
gcc_assert (op2 != NULL_RTX);
resolve_simple_move will ask for the high part of the paradoxical
subreg, which does not have a value. Just return a zero. */
if (ret == NULL_RTX
- && GET_CODE (op) == SUBREG
- && SUBREG_BYTE (op) == 0
- && (GET_MODE_SIZE (innermode)
- > GET_MODE_SIZE (GET_MODE (SUBREG_REG (op)))))
+ && paradoxical_subreg_p (op))
return CONST0_RTX (outermode);
gcc_assert (ret != NULL_RTX);
/* Strict_low_part requires reload the register not
the sub-register. */
&& (curr_static_id->operand[i].strict_low
- || (GET_MODE_SIZE (mode)
- <= GET_MODE_SIZE (GET_MODE (reg))
+ || (!paradoxical_subreg_p (mode, GET_MODE (reg))
&& (hard_regno
= get_try_hard_regno (REGNO (reg))) >= 0
&& (simplify_subreg_regno
mode was larger than a register, just use the reg_rtx. Otherwise,
limit the size to that of the biggest access in the function. */
if (mode == VOIDmode
- || GET_MODE_SIZE (mode) > GET_MODE_SIZE (reg_rtx_mode))
+ || paradoxical_subreg_p (mode, reg_rtx_mode))
{
original_reg = regno_reg_rtx[hard_regno];
mode = reg_rtx_mode;
subreg_reg = SUBREG_REG (x);
x_mode = GET_MODE (x);
subreg_reg_mode = GET_MODE (subreg_reg);
- if (GET_CODE (x) == SUBREG && GET_CODE (subreg_reg) == PLUS
- && GET_MODE_SIZE (x_mode) <= GET_MODE_SIZE (subreg_reg_mode)
+ if (!paradoxical_subreg_p (x)
+ && GET_CODE (subreg_reg) == PLUS
&& CONSTANT_P (XEXP (subreg_reg, 1))
&& GET_MODE_CLASS (x_mode) == MODE_INT
&& GET_MODE_CLASS (subreg_reg_mode) == MODE_INT)
if (new_rtx != SUBREG_REG (x))
{
- int x_size = GET_MODE_SIZE (GET_MODE (x));
- int new_size = GET_MODE_SIZE (GET_MODE (new_rtx));
-
- if (MEM_P (new_rtx) && x_size <= new_size)
+ if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
{
SUBREG_REG (x) = new_rtx;
alter_subreg (&x, false);
However, we must allow them after reload so that they can
get cleaned up by cleanup_subreg_operands. */
if (!reload_completed && MEM_P (sub)
- && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub)))
+ && paradoxical_subreg_p (op))
return 0;
#endif
/* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
size of floating point mode can be less than the integer
mode. */
&& ! lra_in_progress
- && GET_MODE_SIZE (GET_MODE (op)) > GET_MODE_SIZE (GET_MODE (sub)))
+ && paradoxical_subreg_p (op))
return 0;
op = sub;
return false;
for (df_link *use = uses; use; use = use->next)
- if (GET_MODE_PRECISION (GET_MODE (*DF_REF_LOC (use->ref))) > prec)
+ if (paradoxical_subreg_p (GET_MODE (*DF_REF_LOC (use->ref)),
+ GET_MODE (SET_DEST (*dest_sub_rtx))))
return false;
}
|| (((REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (in)))
- && ((GET_MODE_PRECISION (inmode)
- > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
+ && (paradoxical_subreg_p (inmode, GET_MODE (SUBREG_REG (in)))
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
<= UNITS_PER_WORD)
- && (GET_MODE_PRECISION (inmode)
- > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
+ && paradoxical_subreg_p (inmode,
+ GET_MODE (SUBREG_REG (in)))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
|| (WORD_REGISTER_OPERATIONS
|| (((REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER)
|| MEM_P (SUBREG_REG (out)))
- && ((GET_MODE_PRECISION (outmode)
- > GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
+ && (paradoxical_subreg_p (outmode, GET_MODE (SUBREG_REG (out)))
|| (WORD_REGISTER_OPERATIONS
&& (GET_MODE_PRECISION (outmode)
< GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
if (this_insn_is_asm)
{
machine_mode mode;
- if (GET_MODE_SIZE (inmode) > GET_MODE_SIZE (outmode))
+ if (paradoxical_subreg_p (inmode, outmode))
mode = inmode;
else
mode = outmode;
&& (WORD_REGISTER_OPERATIONS
|| ((GET_MODE_BITSIZE (GET_MODE (operand))
< BIGGEST_ALIGNMENT)
- && (GET_MODE_SIZE (operand_mode[i])
- > GET_MODE_SIZE (GET_MODE (operand))))
+ && paradoxical_subreg_p (operand_mode[i],
+ GET_MODE (operand)))
|| BYTES_BIG_ENDIAN
|| ((GET_MODE_SIZE (operand_mode[i])
<= UNITS_PER_WORD)
&& (GET_MODE_SIZE (GET_MODE (operand))
<= UNITS_PER_WORD)
- && (GET_MODE_SIZE (operand_mode[i])
- > GET_MODE_SIZE (GET_MODE (operand)))
+ && paradoxical_subreg_p (operand_mode[i],
+ GET_MODE (operand))
&& INTEGRAL_MODE_P (GET_MODE (operand))
&& LOAD_EXTEND_OP (GET_MODE (operand))
!= UNKNOWN)))
case SUBREG:
if (REG_P (SUBREG_REG (x))
- && (GET_MODE_SIZE (GET_MODE (x))
- <= GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))
+ && !paradoxical_subreg_p (x)
&& reg_equivs
&& reg_equiv_memory_loc (REGNO (SUBREG_REG (x))) != 0)
return;
/* If SUBREG is paradoxical then return the normal lowpart offset
for OUTERMODE and INNERMODE. Our caller has already checked
that OUTERMODE fits in INNERMODE. */
- if (outer_offset == 0
- && GET_MODE_SIZE (outermode) > GET_MODE_SIZE (middlemode))
+ if (paradoxical_subreg_p (outermode, middlemode))
return subreg_lowpart_offset (outermode, innermode);
/* SUBREG is normal, but may not be lowpart; return OUTER_OFFSET
&& rld[r].out)
/* Don't really use the inherited spill reg
if we need it wider than we've got it. */
- || (GET_MODE_SIZE (rld[r].mode)
- > GET_MODE_SIZE (mode))
+ || paradoxical_subreg_p (rld[r].mode, mode)
|| bad_for_class
/* If find_reloads chose reload_out as reload
/* In emit-rtl.c */
extern rtx operand_subword_force (rtx, unsigned int, machine_mode);
-extern bool paradoxical_subreg_p (const_rtx);
extern int subreg_lowpart_p (const_rtx);
extern unsigned int subreg_size_lowpart_offset (unsigned int, unsigned int);
+/* Return true if a subreg with the given outer and inner modes is
+ paradoxical. */
+
+inline bool
+paradoxical_subreg_p (machine_mode outermode, machine_mode innermode)
+{
+ return GET_MODE_PRECISION (outermode) > GET_MODE_PRECISION (innermode);
+}
+
+/* Return true if X is a paradoxical subreg, false otherwise. */
+
+inline bool
+paradoxical_subreg_p (const_rtx x)
+{
+ if (GET_CODE (x) != SUBREG)
+ return false;
+ return paradoxical_subreg_p (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
+}
+
/* Return the SUBREG_BYTE for an OUTERMODE lowpart of an INNERMODE value. */
inline unsigned int
unsigned int word;
/* A paradoxical subreg begins at bit position 0. */
- if (GET_MODE_PRECISION (outer_mode) > GET_MODE_PRECISION (inner_mode))
+ if (paradoxical_subreg_p (outer_mode, inner_mode))
return 0;
if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& SUBREG_PROMOTED_SIGNED_P (op)
- && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
{
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
if (GET_CODE (op) == SUBREG
&& SUBREG_PROMOTED_VAR_P (op)
&& SUBREG_PROMOTED_UNSIGNED_P (op)
- && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))
+ && !paradoxical_subreg_p (mode, GET_MODE (SUBREG_REG (op))))
{
temp = rtl_hooks.gen_lowpart_no_emit (mode, op);
if (temp)
}
/* See whether resulting subreg will be paradoxical. */
- if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode))
+ if (!paradoxical_subreg_p (outermode, innermostmode))
{
/* In nonparadoxical subregs we can't handle negative offsets. */
if (final_offset < 0)
machine_mode pseudo_mode;
pseudo_mode = PSEUDO_REGNO_MODE (ORIGINAL_REGNO (loc));
- if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (pseudo_mode))
+ if (paradoxical_subreg_p (mode, pseudo_mode))
{
offset += byte_lowpart_offset (pseudo_mode, mode);
mode = pseudo_mode;
because the real and imaginary parts are represented as separate
pseudo registers, even if the whole complex value fits into one
hard register. */
- if ((GET_MODE_SIZE (mode) > GET_MODE_SIZE (DECL_MODE (expr))
+ if ((paradoxical_subreg_p (mode, DECL_MODE (expr))
|| (store_reg_p
&& !COMPLEX_MODE_P (DECL_MODE (expr))
&& hard_regno_nregs[REGNO (loc)][DECL_MODE (expr)] == 1))