Message ID | 87y3qdcaj9.fsf@linaro.org |
---|---|
State | Accepted |
Commit | 03a9562184454fe5395e30b8a3429c4570979d86 |
Headers | show |
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
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