This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: Make more use of paradoxical_subreg_p
- From: Richard Biener <richard dot guenther at gmail dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, Richard Sandiford <richard dot sandiford at linaro dot org>
- Date: Tue, 22 Aug 2017 12:54:34 +0200
- Subject: Re: Make more use of paradoxical_subreg_p
- Authentication-results: sourceware.org; auth=none
- References: <87y3qdcaj9.fsf@linaro.org>
On Mon, Aug 21, 2017 at 3:31 PM, Richard Sandiford
<richard.sandiford@linaro.org> wrote:
> This patch makes more use of the existing paradoxical_subreg_p
> predicate and also adds a version that operates on outer and
> inner modes.
>
> Some of the affected tests were based on GET_MODE_SIZE rather than
> GET_MODE_PRECISION and so the patch could change the result for modes
> that have the same size but different precisions. I think in each
> case the change should be a no-op or more correct, since a mode with
> precision N bits can't be expected to hold all of a mode with precision
> M>N bits.
>
> The patch changes the branch taken in simplify_subreg for modes with
> equal precision, but the new form matches the commentary more closely.
> Both branches should be equally good in that situation.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu, and by checking that
> there were no changes in the testsuite assembly output for one target
> per CPU. OK to install?
Ok.
Thanks
Richard.
> Richard
>
>
> 2017-08-21 Richard Sandiford <richard.sandiford@linaro.org>
> Alan Hayward <alan.hayward@arm.com>
> David Sherwood <david.sherwood@arm.com>
>
> gcc/
> * 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.
>
> Index: gcc/rtl.h
> ===================================================================
> --- gcc/rtl.h 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/rtl.h 2017-08-21 14:20:43.099964655 +0100
> @@ -2784,10 +2784,28 @@ extern rtx operand_subword (rtx, unsigne
>
> /* 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
> Index: gcc/doc/rtl.texi
> ===================================================================
> --- gcc/doc/rtl.texi 2017-07-27 10:37:54.486030028 +0100
> +++ gcc/doc/rtl.texi 2017-08-21 14:20:43.094947435 +0100
> @@ -1872,7 +1872,7 @@ expression is called @dfn{paradoxical}.
> 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.
> Index: gcc/combine.c
> ===================================================================
> --- gcc/combine.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/combine.c 2017-08-21 14:20:43.092940547 +0100
> @@ -6809,9 +6809,7 @@ simplify_set (rtx x)
> / 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),
> @@ -7456,7 +7454,7 @@ make_extraction (machine_mode mode, rtx
> : 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))
> @@ -7669,7 +7667,7 @@ make_extraction (machine_mode mode, rtx
> /* 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. */
> @@ -8529,7 +8527,7 @@ force_to_mode (rtx x, machine_mode mode,
>
> /* 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);
>
> @@ -9408,7 +9406,7 @@ rtx_equal_for_field_assignment_p (rtx 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;
> @@ -11488,7 +11486,7 @@ gen_lowpart_for_combine (machine_mode om
> /* 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)
> @@ -12145,8 +12143,7 @@ simplify_comparison (enum rtx_code code,
>
> /* 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
> Index: gcc/cse.c
> ===================================================================
> --- gcc/cse.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/cse.c 2017-08-21 14:20:43.093943991 +0100
> @@ -3802,7 +3802,7 @@ equiv_constant (rtx x)
> 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));
>
> Index: gcc/expmed.c
> ===================================================================
> --- gcc/expmed.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/expmed.c 2017-08-21 14:20:43.095950879 +0100
> @@ -736,7 +736,7 @@ store_bit_field_1 (rtx str_rtx, unsigned
> 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;
>
> Index: gcc/final.c
> ===================================================================
> --- gcc/final.c 2017-08-21 12:09:48.440614101 +0100
> +++ gcc/final.c 2017-08-21 14:20:43.095950879 +0100
> @@ -3205,8 +3205,7 @@ alter_subreg (rtx *xp, bool final_p)
>
> /* 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));
> Index: gcc/fwprop.c
> ===================================================================
> --- gcc/fwprop.c 2017-07-13 09:25:12.152288651 +0100
> +++ gcc/fwprop.c 2017-08-21 14:20:43.095950879 +0100
> @@ -680,8 +680,7 @@ propagate_rtx (rtx x, machine_mode mode,
> || 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;
> @@ -1103,9 +1102,7 @@ forward_propagate_subreg (df_ref use, rt
> || !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
> Index: gcc/ira-conflicts.c
> ===================================================================
> --- gcc/ira-conflicts.c 2017-02-23 19:54:03.000000000 +0000
> +++ gcc/ira-conflicts.c 2017-08-21 14:20:43.095950879 +0100
> @@ -775,7 +775,7 @@ ira_build_conflicts (void)
> 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)
> Index: gcc/lower-subreg.c
> ===================================================================
> --- gcc/lower-subreg.c 2017-07-13 09:25:13.387236070 +0100
> +++ gcc/lower-subreg.c 2017-08-21 14:20:43.096954323 +0100
> @@ -661,10 +661,8 @@ simplify_gen_subreg_concatn (machine_mod
> 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);
> @@ -685,10 +683,7 @@ simplify_gen_subreg_concatn (machine_mod
> 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);
> Index: gcc/lra-constraints.c
> ===================================================================
> --- gcc/lra-constraints.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/lra-constraints.c 2017-08-21 14:20:43.096954323 +0100
> @@ -4225,8 +4225,7 @@ curr_insn_transform (bool check_only_p)
> /* 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
> @@ -5465,7 +5464,7 @@ split_reg (bool before_p, int original_r
> 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;
> Index: gcc/lra-eliminations.c
> ===================================================================
> --- gcc/lra-eliminations.c 2017-07-05 16:29:19.599861904 +0100
> +++ gcc/lra-eliminations.c 2017-08-21 14:20:43.097957767 +0100
> @@ -286,8 +286,8 @@ move_plus_up (rtx x)
> 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)
> @@ -605,10 +605,7 @@ lra_eliminate_regs_1 (rtx_insn *insn, rt
>
> 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);
> Index: gcc/recog.c
> ===================================================================
> --- gcc/recog.c 2017-07-13 09:25:12.152288651 +0100
> +++ gcc/recog.c 2017-08-21 14:20:43.097957767 +0100
> @@ -1002,7 +1002,7 @@ general_operand (rtx op, machine_mode mo
> 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
> @@ -1037,7 +1037,7 @@ general_operand (rtx op, machine_mode mo
> 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;
> Index: gcc/ree.c
> ===================================================================
> --- gcc/ree.c 2017-02-23 19:54:20.000000000 +0000
> +++ gcc/ree.c 2017-08-21 14:20:43.097957767 +0100
> @@ -869,7 +869,8 @@ combine_reaching_defs (ext_cand *cand, c
> 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;
> }
>
> Index: gcc/reload.c
> ===================================================================
> --- gcc/reload.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/reload.c 2017-08-21 14:20:43.098961211 +0100
> @@ -1062,13 +1062,12 @@ push_reload (rtx in, rtx out, rtx *inloc
> || (((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
> @@ -1170,8 +1169,7 @@ push_reload (rtx in, rtx out, rtx *inloc
> || (((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))))
> @@ -1299,7 +1297,7 @@ push_reload (rtx in, rtx out, rtx *inloc
> 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;
> @@ -3137,15 +3135,15 @@ find_reloads (rtx_insn *insn, int replac
> && (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)))
> Index: gcc/reload1.c
> ===================================================================
> --- gcc/reload1.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/reload1.c 2017-08-21 14:20:43.099964655 +0100
> @@ -3042,8 +3042,7 @@ elimination_effects (rtx x, machine_mode
>
> 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;
> @@ -6373,8 +6372,7 @@ compute_reload_subreg_offset (machine_mo
> /* 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
> @@ -6664,8 +6662,7 @@ choose_reload_regs (struct insn_chain *c
> && 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
> Index: gcc/rtlanal.c
> ===================================================================
> --- gcc/rtlanal.c 2017-07-13 09:25:13.516230596 +0100
> +++ gcc/rtlanal.c 2017-08-21 14:20:43.101971543 +0100
> @@ -3530,7 +3530,7 @@ subreg_lsb_1 (machine_mode outer_mode,
> 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)
> Index: gcc/simplify-rtx.c
> ===================================================================
> --- gcc/simplify-rtx.c 2017-08-21 10:42:34.185530464 +0100
> +++ gcc/simplify-rtx.c 2017-08-21 14:20:43.102974987 +0100
> @@ -1465,7 +1465,7 @@ simplify_unary_operation_1 (enum rtx_cod
> 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)
> @@ -1547,7 +1547,7 @@ simplify_unary_operation_1 (enum rtx_cod
> 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)
> @@ -6080,7 +6080,7 @@ simplify_subreg (machine_mode outermode,
> }
>
> /* 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)
> Index: gcc/var-tracking.c
> ===================================================================
> --- gcc/var-tracking.c 2017-07-13 09:25:13.516230596 +0100
> +++ gcc/var-tracking.c 2017-08-21 14:20:43.105985318 +0100
> @@ -5295,7 +5295,7 @@ track_loc_p (rtx loc, tree expr, HOST_WI
> 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;
> @@ -5309,7 +5309,7 @@ track_loc_p (rtx loc, tree expr, HOST_WI
> 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))
> Index: gcc/emit-rtl.c
> ===================================================================
> --- gcc/emit-rtl.c 2017-08-03 10:40:55.518043414 +0100
> +++ gcc/emit-rtl.c 2017-08-21 14:20:43.094947435 +0100
> @@ -1008,10 +1008,10 @@ gen_rtvec_v (int n, rtx_insn **argp)
> 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);
> }
>
> /* Generate a REG rtx for a new pseudo register of mode MODE.
> @@ -1552,16 +1552,6 @@ subreg_lowpart_p (const_rtx x)
> 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))));
> -}
>
> /* Return subword OFFSET of operand OP.
> The word number, OFFSET, is interpreted as the word number starting