poly_int: SUBREG_BYTE
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 20 Dec 2017 12:54:28 +0000 (12:54 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 20 Dec 2017 12:54:28 +0000 (12:54 +0000)
This patch changes SUBREG_BYTE from an int to a poly_int.
Since valid SUBREG_BYTEs must be contained within the mode of the
SUBREG_REG, the required range is the same as for GET_MODE_SIZE,
i.e. unsigned short.  The patch therefore uses poly_uint16(_pod)
for the SUBREG_BYTE.

Using poly_uint16_pod rtx fields requires a new field code ('p').
Since there are no other uses of 'p' besides SUBREG_BYTE, the patch
doesn't add an XPOLY or whatever; all uses should go via SUBREG_BYTE
instead.

The patch doesn't bother implementing 'p' support for legacy
define_peepholes, since none of the remaining ones have subregs
in their patterns.

As it happened, the rtl documentation used SUBREG as an example of a
code with mixed field types, accessed via XEXP (x, 0) and XINT (x, 1).
Since there's no direct replacement for XINT, and since people should
never use it even if there were, the patch changes the example to use
INT_LIST instead.

The patch also changes subreg-related helper functions so that they too
take and return polynomial offsets.  This makes the patch quite big, but
it's mostly mechanical.  The patch generally sticks to existing choices
wrt signedness.

2017-12-20  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* doc/rtl.texi: Update documentation of SUBREG_BYTE.  Document the
'p' format code.  Use INT_LIST rather than SUBREG as the example of
a code with an XINT and an XEXP.  Remove the implication that
accessing an rtx field using XINT is expected to work.
* rtl.def (SUBREG): Change format from "ei" to "ep".
* rtl.h (rtunion::rt_subreg): New field.
(XCSUBREG): New macro.
(SUBREG_BYTE): Use it.
(subreg_shape): Change offset from an unsigned int to a poly_uint16.
Update constructor accordingly.
(subreg_shape::operator ==): Update accordingly.
(subreg_shape::unique_id): Return an unsigned HOST_WIDE_INT rather
than an unsigned int.
(subreg_lsb, subreg_lowpart_offset, subreg_highpart_offset): Return
a poly_uint64 rather than an unsigned int.
(subreg_lsb_1): Likewise.  Take the offset as a poly_uint64 rather
than an unsigned int.
(subreg_size_offset_from_lsb, subreg_size_lowpart_offset)
(subreg_size_highpart_offset): Return a poly_uint64 rather than
an unsigned int.  Take the sizes as poly_uint64s.
(subreg_offset_from_lsb): Return a poly_uint64 rather than
an unsigned int.  Take the shift as a poly_uint64 rather than
an unsigned int.
(subreg_regno_offset, subreg_offset_representable_p): Take the offset
as a poly_uint64 rather than an unsigned int.
(simplify_subreg_regno): Likewise.
(byte_lowpart_offset): Return the memory offset as a poly_int64
rather than an int.
(subreg_memory_offset): Likewise.  Take the subreg offset as a
poly_uint64 rather than an unsigned int.
(simplify_subreg, simplify_gen_subreg, subreg_get_info)
(gen_rtx_SUBREG, validate_subreg): Take the subreg offset as a
poly_uint64 rather than an unsigned int.
* rtl.c (rtx_format): Describe 'p' in comment.
(copy_rtx, rtx_equal_p_cb, rtx_equal_p): Handle 'p'.
* emit-rtl.c (validate_subreg, gen_rtx_SUBREG): Take the subreg
offset as a poly_uint64 rather than an unsigned int.
(byte_lowpart_offset): Return the memory offset as a poly_int64
rather than an int.
(subreg_memory_offset): Likewise.  Take the subreg offset as a
poly_uint64 rather than an unsigned int.
(subreg_size_lowpart_offset, subreg_size_highpart_offset): Take the
mode sizes as poly_uint64s rather than unsigned ints.  Return a
poly_uint64 rather than an unsigned int.
(subreg_lowpart_p): Treat subreg offsets as poly_ints.
(copy_insn_1): Handle 'p'.
* rtlanal.c (set_noop_p): Treat subregs offsets as poly_uint64s.
(subreg_lsb_1): Take the subreg offset as a poly_uint64 rather than
an unsigned int.  Return the shift in the same way.
(subreg_lsb): Return the shift as a poly_uint64 rather than an
unsigned int.
(subreg_size_offset_from_lsb): Take the sizes and shift as
poly_uint64s rather than unsigned ints.  Return the offset as
a poly_uint64.
(subreg_get_info, subreg_regno_offset, subreg_offset_representable_p)
(simplify_subreg_regno): Take the offset as a poly_uint64 rather than
an unsigned int.
* rtlhash.c (add_rtx): Handle 'p'.
* genemit.c (gen_exp): Likewise.
* gengenrtl.c (type_from_format, gendef): Likewise.
* gensupport.c (subst_pattern_match, get_alternatives_number)
(collect_insn_data, alter_predicate_for_insn, alter_constraints)
(subst_dup): Likewise.
* gengtype.c (adjust_field_rtx_def): Likewise.
* genrecog.c (find_operand, find_matching_operand, validate_pattern)
(match_pattern_2): Likewise.
(rtx_test::SUBREG_FIELD): New rtx_test::kind_enum.
(rtx_test::subreg_field): New function.
(operator ==, safe_to_hoist_p, transition_parameter_type)
(print_nonbool_test, print_test): Handle SUBREG_FIELD.
* genattrtab.c (attr_rtx_1): Say that 'p' is deliberately not handled.
* genpeep.c (match_rtx): Likewise.
* print-rtl.c (print_poly_int): Include if GENERATOR_FILE too.
(rtx_writer::print_rtx_operand): Handle 'p'.
(print_value): Handle SUBREG.
* read-rtl.c (apply_int_iterator): Likewise.
(rtx_reader::read_rtx_operand): Handle 'p'.
* alias.c (rtx_equal_for_memref_p): Likewise.
* cselib.c (rtx_equal_for_cselib_1, cselib_hash_rtx): Likewise.
* caller-save.c (replace_reg_with_saved_mem): Treat subreg offsets
as poly_ints.
* calls.c (expand_call): Likewise.
* combine.c (combine_simplify_rtx, expand_field_assignment): Likewise.
(make_extraction, gen_lowpart_for_combine): Likewise.
* loop-invariant.c (hash_invariant_expr_1, invariant_expr_equal_p):
Likewise.
* cse.c (remove_invalid_subreg_refs): Take the offset as a poly_uint64
rather than an unsigned int.  Treat subreg offsets as poly_ints.
(exp_equiv_p): Handle 'p'.
(hash_rtx_cb): Likewise.  Treat subreg offsets as poly_ints.
(equiv_constant, cse_insn): Treat subreg offsets as poly_ints.
* dse.c (find_shift_sequence): Likewise.
* dwarf2out.c (rtl_for_decl_location): Likewise.
* expmed.c (extract_low_bits): Likewise.
* expr.c (emit_group_store, undefined_operand_subword_p): Likewise.
(expand_expr_real_2): Likewise.
* final.c (alter_subreg): Likewise.
(leaf_renumber_regs_insn): Handle 'p'.
* function.c (assign_parm_find_stack_rtl, assign_parm_setup_stack):
Treat subreg offsets as poly_ints.
* fwprop.c (forward_propagate_and_simplify): Likewise.
* ifcvt.c (noce_emit_move_insn, noce_emit_cmove): Likewise.
* ira.c (get_subreg_tracking_sizes): Likewise.
* ira-conflicts.c (go_through_subreg): Likewise.
* ira-lives.c (process_single_reg_class_operands): Likewise.
* jump.c (rtx_renumbered_equal_p): Likewise.  Handle 'p'.
* lower-subreg.c (simplify_subreg_concatn): Take the subreg offset
as a poly_uint64 rather than an unsigned int.
(simplify_gen_subreg_concatn, resolve_simple_move): Treat
subreg offsets as poly_ints.
* lra-constraints.c (operands_match_p): Handle 'p'.
(match_reload, curr_insn_transform): Treat subreg offsets as poly_ints.
* lra-spills.c (assign_mem_slot): Likewise.
* postreload.c (move2add_valid_value_p): Likewise.
* recog.c (general_operand, indirect_operand): Likewise.
* regcprop.c (copy_value, maybe_mode_change): Likewise.
(copyprop_hardreg_forward_1): Likewise.
* reginfo.c (simplifiable_subregs_hasher::hash, simplifiable_subregs)
(record_subregs_of_mode): Likewise.
* rtlhooks.c (gen_lowpart_general, gen_lowpart_if_possible): Likewise.
* reload.c (operands_match_p): Handle 'p'.
(find_reloads_subreg_address): Treat subreg offsets as poly_ints.
* reload1.c (alter_reg, choose_reload_regs): Likewise.
(compute_reload_subreg_offset): Likewise, and return an poly_int64.
* simplify-rtx.c (simplify_truncation, simplify_binary_operation_1):
(test_vector_ops_duplicate): Treat subreg offsets as poly_ints.
(simplify_const_poly_int_tests<N>::run): Likewise.
(simplify_subreg, simplify_gen_subreg): Take the subreg offset as
a poly_uint64 rather than an unsigned int.
* valtrack.c (debug_lowpart_subreg): Likewise.
* var-tracking.c (var_lowpart): Likewise.
(loc_cmp): Handle 'p'.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r255882

49 files changed:
gcc/ChangeLog
gcc/alias.c
gcc/caller-save.c
gcc/calls.c
gcc/combine.c
gcc/cse.c
gcc/cselib.c
gcc/doc/rtl.texi
gcc/dse.c
gcc/dwarf2out.c
gcc/emit-rtl.c
gcc/expmed.c
gcc/expr.c
gcc/final.c
gcc/function.c
gcc/fwprop.c
gcc/genattrtab.c
gcc/genemit.c
gcc/gengenrtl.c
gcc/gengtype.c
gcc/genpeep.c
gcc/genrecog.c
gcc/gensupport.c
gcc/ifcvt.c
gcc/ira-conflicts.c
gcc/ira-lives.c
gcc/ira.c
gcc/jump.c
gcc/loop-invariant.c
gcc/lower-subreg.c
gcc/lra-constraints.c
gcc/lra-spills.c
gcc/postreload.c
gcc/print-rtl.c
gcc/read-rtl.c
gcc/recog.c
gcc/regcprop.c
gcc/reginfo.c
gcc/reload.c
gcc/reload1.c
gcc/rtl.c
gcc/rtl.def
gcc/rtl.h
gcc/rtlanal.c
gcc/rtlhash.c
gcc/rtlhooks.c
gcc/simplify-rtx.c
gcc/valtrack.c
gcc/var-tracking.c

index 91f1927ff69d7ee462a657ce1ef3ff731ac81f94..ad7ee7e6ca303599bfc1fa2a38a73ddb29569100 100644 (file)
@@ -1,3 +1,140 @@
+2017-12-20  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * doc/rtl.texi: Update documentation of SUBREG_BYTE.  Document the
+       'p' format code.  Use INT_LIST rather than SUBREG as the example of
+       a code with an XINT and an XEXP.  Remove the implication that
+       accessing an rtx field using XINT is expected to work.
+       * rtl.def (SUBREG): Change format from "ei" to "ep".
+       * rtl.h (rtunion::rt_subreg): New field.
+       (XCSUBREG): New macro.
+       (SUBREG_BYTE): Use it.
+       (subreg_shape): Change offset from an unsigned int to a poly_uint16.
+       Update constructor accordingly.
+       (subreg_shape::operator ==): Update accordingly.
+       (subreg_shape::unique_id): Return an unsigned HOST_WIDE_INT rather
+       than an unsigned int.
+       (subreg_lsb, subreg_lowpart_offset, subreg_highpart_offset): Return
+       a poly_uint64 rather than an unsigned int.
+       (subreg_lsb_1): Likewise.  Take the offset as a poly_uint64 rather
+       than an unsigned int.
+       (subreg_size_offset_from_lsb, subreg_size_lowpart_offset)
+       (subreg_size_highpart_offset): Return a poly_uint64 rather than
+       an unsigned int.  Take the sizes as poly_uint64s.
+       (subreg_offset_from_lsb): Return a poly_uint64 rather than
+       an unsigned int.  Take the shift as a poly_uint64 rather than
+       an unsigned int.
+       (subreg_regno_offset, subreg_offset_representable_p): Take the offset
+       as a poly_uint64 rather than an unsigned int.
+       (simplify_subreg_regno): Likewise.
+       (byte_lowpart_offset): Return the memory offset as a poly_int64
+       rather than an int.
+       (subreg_memory_offset): Likewise.  Take the subreg offset as a
+       poly_uint64 rather than an unsigned int.
+       (simplify_subreg, simplify_gen_subreg, subreg_get_info)
+       (gen_rtx_SUBREG, validate_subreg): Take the subreg offset as a
+       poly_uint64 rather than an unsigned int.
+       * rtl.c (rtx_format): Describe 'p' in comment.
+       (copy_rtx, rtx_equal_p_cb, rtx_equal_p): Handle 'p'.
+       * emit-rtl.c (validate_subreg, gen_rtx_SUBREG): Take the subreg
+       offset as a poly_uint64 rather than an unsigned int.
+       (byte_lowpart_offset): Return the memory offset as a poly_int64
+       rather than an int.
+       (subreg_memory_offset): Likewise.  Take the subreg offset as a
+       poly_uint64 rather than an unsigned int.
+       (subreg_size_lowpart_offset, subreg_size_highpart_offset): Take the
+       mode sizes as poly_uint64s rather than unsigned ints.  Return a
+       poly_uint64 rather than an unsigned int.
+       (subreg_lowpart_p): Treat subreg offsets as poly_ints.
+       (copy_insn_1): Handle 'p'.
+       * rtlanal.c (set_noop_p): Treat subregs offsets as poly_uint64s.
+       (subreg_lsb_1): Take the subreg offset as a poly_uint64 rather than
+       an unsigned int.  Return the shift in the same way.
+       (subreg_lsb): Return the shift as a poly_uint64 rather than an
+       unsigned int.
+       (subreg_size_offset_from_lsb): Take the sizes and shift as
+       poly_uint64s rather than unsigned ints.  Return the offset as
+       a poly_uint64.
+       (subreg_get_info, subreg_regno_offset, subreg_offset_representable_p)
+       (simplify_subreg_regno): Take the offset as a poly_uint64 rather than
+       an unsigned int.
+       * rtlhash.c (add_rtx): Handle 'p'.
+       * genemit.c (gen_exp): Likewise.
+       * gengenrtl.c (type_from_format, gendef): Likewise.
+       * gensupport.c (subst_pattern_match, get_alternatives_number)
+       (collect_insn_data, alter_predicate_for_insn, alter_constraints)
+       (subst_dup): Likewise.
+       * gengtype.c (adjust_field_rtx_def): Likewise.
+       * genrecog.c (find_operand, find_matching_operand, validate_pattern)
+       (match_pattern_2): Likewise.
+       (rtx_test::SUBREG_FIELD): New rtx_test::kind_enum.
+       (rtx_test::subreg_field): New function.
+       (operator ==, safe_to_hoist_p, transition_parameter_type)
+       (print_nonbool_test, print_test): Handle SUBREG_FIELD.
+       * genattrtab.c (attr_rtx_1): Say that 'p' is deliberately not handled.
+       * genpeep.c (match_rtx): Likewise.
+       * print-rtl.c (print_poly_int): Include if GENERATOR_FILE too.
+       (rtx_writer::print_rtx_operand): Handle 'p'.
+       (print_value): Handle SUBREG.
+       * read-rtl.c (apply_int_iterator): Likewise.
+       (rtx_reader::read_rtx_operand): Handle 'p'.
+       * alias.c (rtx_equal_for_memref_p): Likewise.
+       * cselib.c (rtx_equal_for_cselib_1, cselib_hash_rtx): Likewise.
+       * caller-save.c (replace_reg_with_saved_mem): Treat subreg offsets
+       as poly_ints.
+       * calls.c (expand_call): Likewise.
+       * combine.c (combine_simplify_rtx, expand_field_assignment): Likewise.
+       (make_extraction, gen_lowpart_for_combine): Likewise.
+       * loop-invariant.c (hash_invariant_expr_1, invariant_expr_equal_p):
+       Likewise.
+       * cse.c (remove_invalid_subreg_refs): Take the offset as a poly_uint64
+       rather than an unsigned int.  Treat subreg offsets as poly_ints.
+       (exp_equiv_p): Handle 'p'.
+       (hash_rtx_cb): Likewise.  Treat subreg offsets as poly_ints.
+       (equiv_constant, cse_insn): Treat subreg offsets as poly_ints.
+       * dse.c (find_shift_sequence): Likewise.
+       * dwarf2out.c (rtl_for_decl_location): Likewise.
+       * expmed.c (extract_low_bits): Likewise.
+       * expr.c (emit_group_store, undefined_operand_subword_p): Likewise.
+       (expand_expr_real_2): Likewise.
+       * final.c (alter_subreg): Likewise.
+       (leaf_renumber_regs_insn): Handle 'p'.
+       * function.c (assign_parm_find_stack_rtl, assign_parm_setup_stack):
+       Treat subreg offsets as poly_ints.
+       * fwprop.c (forward_propagate_and_simplify): Likewise.
+       * ifcvt.c (noce_emit_move_insn, noce_emit_cmove): Likewise.
+       * ira.c (get_subreg_tracking_sizes): Likewise.
+       * ira-conflicts.c (go_through_subreg): Likewise.
+       * ira-lives.c (process_single_reg_class_operands): Likewise.
+       * jump.c (rtx_renumbered_equal_p): Likewise.  Handle 'p'.
+       * lower-subreg.c (simplify_subreg_concatn): Take the subreg offset
+       as a poly_uint64 rather than an unsigned int.
+       (simplify_gen_subreg_concatn, resolve_simple_move): Treat
+       subreg offsets as poly_ints.
+       * lra-constraints.c (operands_match_p): Handle 'p'.
+       (match_reload, curr_insn_transform): Treat subreg offsets as poly_ints.
+       * lra-spills.c (assign_mem_slot): Likewise.
+       * postreload.c (move2add_valid_value_p): Likewise.
+       * recog.c (general_operand, indirect_operand): Likewise.
+       * regcprop.c (copy_value, maybe_mode_change): Likewise.
+       (copyprop_hardreg_forward_1): Likewise.
+       * reginfo.c (simplifiable_subregs_hasher::hash, simplifiable_subregs)
+       (record_subregs_of_mode): Likewise.
+       * rtlhooks.c (gen_lowpart_general, gen_lowpart_if_possible): Likewise.
+       * reload.c (operands_match_p): Handle 'p'.
+       (find_reloads_subreg_address): Treat subreg offsets as poly_ints.
+       * reload1.c (alter_reg, choose_reload_regs): Likewise.
+       (compute_reload_subreg_offset): Likewise, and return an poly_int64.
+       * simplify-rtx.c (simplify_truncation, simplify_binary_operation_1):
+       (test_vector_ops_duplicate): Treat subreg offsets as poly_ints.
+       (simplify_const_poly_int_tests<N>::run): Likewise.
+       (simplify_subreg, simplify_gen_subreg): Take the subreg offset as
+       a poly_uint64 rather than an unsigned int.
+       * valtrack.c (debug_lowpart_subreg): Likewise.
+       * var-tracking.c (var_lowpart): Likewise.
+       (loc_cmp): Handle 'p'.
+
 2017-12-20  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 072fba207e78a1014741cc5ac14d8713f633d740..16f82240174e787d0fbac512556ec8d9cc79215e 100644 (file)
@@ -1833,6 +1833,11 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
            return 0;
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'E':
          /* Two vectors must have the same length.  */
          if (XVECLEN (x, i) != XVECLEN (y, i))
index 576a023b8a376a421880391b2fce2874270d4927..da49efeda55f49a46dc576df6cba77b7549fa0ad 100644 (file)
@@ -1129,7 +1129,7 @@ replace_reg_with_saved_mem (rtx *loc,
        {
          /* This is gen_lowpart_if_possible(), but without validating
             the newly-formed address.  */
-         HOST_WIDE_INT offset = byte_lowpart_offset (mode, GET_MODE (mem));
+         poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (mem));
          mem = adjust_address_nv (mem, mode, offset);
        }
     }
index 537b34818a6c6a57af9fbeb13f035368b9135cda..5feab3ac1d0b578b17220bf44fec5f45e6b2e6e2 100644 (file)
@@ -4315,8 +4315,8 @@ expand_call (tree exp, rtx target, int ignore)
                                         funtype, 1);
          gcc_assert (GET_MODE (target) == pmode);
 
-         unsigned int offset = subreg_lowpart_offset (TYPE_MODE (type),
-                                                      GET_MODE (target));
+         poly_uint64 offset = subreg_lowpart_offset (TYPE_MODE (type),
+                                                     GET_MODE (target));
          target = gen_rtx_SUBREG (TYPE_MODE (type), target, offset);
          SUBREG_PROMOTED_VAR_P (target) = 1;
          SUBREG_PROMOTED_SET (target, unsignedp);
index 72dc7a5ec45a329cd5197b974feb8c1f1d7c67c8..9f19ee43c74109b0a95a4d4848de6cb09eaf0a81 100644 (file)
@@ -5857,7 +5857,7 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
 
       /* See if this can be moved to simplify_subreg.  */
       if (CONSTANT_P (SUBREG_REG (x))
-         && subreg_lowpart_offset (mode, op0_mode) == SUBREG_BYTE (x)
+         && known_eq (subreg_lowpart_offset (mode, op0_mode), SUBREG_BYTE (x))
             /* Don't call gen_lowpart if the inner mode
                is VOIDmode and we cannot simplify it, as SUBREG without
                inner mode is invalid.  */
@@ -5881,8 +5881,8 @@ combine_simplify_rtx (rtx x, machine_mode op0_mode, int in_dest,
            && is_a <scalar_int_mode> (op0_mode, &int_op0_mode)
            && (GET_MODE_PRECISION (int_mode)
                < GET_MODE_PRECISION (int_op0_mode))
-           && (subreg_lowpart_offset (int_mode, int_op0_mode)
-               == SUBREG_BYTE (x))
+           && known_eq (subreg_lowpart_offset (int_mode, int_op0_mode),
+                        SUBREG_BYTE (x))
            && HWI_COMPUTABLE_MODE_P (int_op0_mode)
            && (nonzero_bits (SUBREG_REG (x), int_op0_mode)
                & GET_MODE_MASK (int_mode)) == 0)
@@ -7357,7 +7357,8 @@ expand_field_assignment (const_rtx x)
        {
          inner = SUBREG_REG (XEXP (SET_DEST (x), 0));
          len = GET_MODE_PRECISION (GET_MODE (XEXP (SET_DEST (x), 0)));
-         pos = GEN_INT (subreg_lsb (XEXP (SET_DEST (x), 0)));
+         pos = gen_int_mode (subreg_lsb (XEXP (SET_DEST (x), 0)),
+                             MAX_MODE_INT);
        }
       else if (GET_CODE (SET_DEST (x)) == ZERO_EXTRACT
               && CONST_INT_P (XEXP (SET_DEST (x), 1)))
@@ -7606,7 +7607,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
                 return a new hard register.  */
              if (pos || in_dest)
                {
-                 unsigned int offset
+                 poly_uint64 offset
                    = subreg_offset_from_lsb (tmode, inner_mode, pos);
 
                  /* Avoid creating invalid subregs, for example when
@@ -11663,7 +11664,7 @@ gen_lowpart_for_combine (machine_mode omode, rtx x)
       if (paradoxical_subreg_p (omode, imode))
        return gen_rtx_SUBREG (omode, x, 0);
 
-      HOST_WIDE_INT offset = byte_lowpart_offset (omode, imode);
+      poly_int64 offset = byte_lowpart_offset (omode, imode);
       return adjust_address_nv (x, omode, offset);
     }
 
index a8da7d4703125aed3210b28616db24d46be23ae8..708c3a02bda6031970be1e63c49d6dbb0a70187a 100644 (file)
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -561,7 +561,7 @@ static struct table_elt *insert (rtx, struct table_elt *, unsigned,
 static void merge_equiv_classes (struct table_elt *, struct table_elt *);
 static void invalidate (rtx, machine_mode);
 static void remove_invalid_refs (unsigned int);
-static void remove_invalid_subreg_refs (unsigned int, unsigned int,
+static void remove_invalid_subreg_refs (unsigned int, poly_uint64,
                                        machine_mode);
 static void rehash_using_reg (rtx);
 static void invalidate_memory (void);
@@ -1994,12 +1994,11 @@ remove_invalid_refs (unsigned int regno)
 /* Likewise for a subreg with subreg_reg REGNO, subreg_byte OFFSET,
    and mode MODE.  */
 static void
-remove_invalid_subreg_refs (unsigned int regno, unsigned int offset,
+remove_invalid_subreg_refs (unsigned int regno, poly_uint64 offset,
                            machine_mode mode)
 {
   unsigned int i;
   struct table_elt *p, *next;
-  unsigned int end = offset + (GET_MODE_SIZE (mode) - 1);
 
   for (i = 0; i < HASH_SIZE; i++)
     for (p = table[i]; p; p = next)
@@ -2011,9 +2010,9 @@ remove_invalid_subreg_refs (unsigned int regno, unsigned int offset,
            && (GET_CODE (exp) != SUBREG
                || !REG_P (SUBREG_REG (exp))
                || REGNO (SUBREG_REG (exp)) != regno
-               || (((SUBREG_BYTE (exp)
-                     + (GET_MODE_SIZE (GET_MODE (exp)) - 1)) >= offset)
-                   && SUBREG_BYTE (exp) <= end))
+               || ranges_maybe_overlap_p (SUBREG_BYTE (exp),
+                                          GET_MODE_SIZE (GET_MODE (exp)),
+                                          offset, GET_MODE_SIZE (mode)))
            && refers_to_regno_p (regno, p->exp))
          remove_from_table (p, i);
       }
@@ -2307,7 +2306,8 @@ hash_rtx_cb (const_rtx x, machine_mode mode,
          {
            hash += (((unsigned int) SUBREG << 7)
                     + REGNO (SUBREG_REG (x))
-                    + (SUBREG_BYTE (x) / UNITS_PER_WORD));
+                    + (constant_lower_bound (SUBREG_BYTE (x))
+                       / UNITS_PER_WORD));
            return hash;
          }
        break;
@@ -2526,6 +2526,10 @@ hash_rtx_cb (const_rtx x, machine_mode mode,
          hash += (unsigned int) XINT (x, i);
          break;
 
+       case 'p':
+         hash += constant_lower_bound (SUBREG_BYTE (x));
+         break;
+
        case '0': case 't':
          /* Unused.  */
          break;
@@ -2776,6 +2780,11 @@ exp_equiv_p (const_rtx x, const_rtx y, int validate, bool for_gcse)
            return 0;
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case '0':
        case 't':
          break;
@@ -3801,8 +3810,9 @@ equiv_constant (rtx x)
       if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode)
          && GET_MODE_SIZE (word_mode) < GET_MODE_SIZE (imode))
        {
-         int byte = SUBREG_BYTE (x) - subreg_lowpart_offset (mode, word_mode);
-         if (byte >= 0 && (byte % UNITS_PER_WORD) == 0)
+         poly_int64 byte = (SUBREG_BYTE (x)
+                            - subreg_lowpart_offset (mode, word_mode));
+         if (known_ge (byte, 0) && multiple_p (byte, UNITS_PER_WORD))
            {
              rtx y = gen_rtx_SUBREG (word_mode, SUBREG_REG (x), byte);
              new_rtx = lookup_as_function (y, CONST_INT);
@@ -6002,7 +6012,7 @@ cse_insn (rtx_insn *insn)
                  new_src = elt->exp;
                else
                  {
-                   unsigned int byte
+                   poly_uint64 byte
                      = subreg_lowpart_offset (new_mode, GET_MODE (dest));
                    new_src = simplify_gen_subreg (new_mode, elt->exp,
                                                   GET_MODE (dest), byte);
index 21a690cd36160b89814986d6cd9a7191db31cf72..5a1da98c1fe1e55bc55462d0e2f81fd0e1b20f74 100644 (file)
@@ -987,6 +987,11 @@ rtx_equal_for_cselib_1 (rtx x, rtx y, machine_mode memmode, int depth)
            return 0;
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
@@ -1278,6 +1283,10 @@ cselib_hash_rtx (rtx x, int create, machine_mode memmode)
          hash += XINT (x, i);
          break;
 
+       case 'p':
+         hash += constant_lower_bound (SUBREG_BYTE (x));
+         break;
+
        case '0':
        case 't':
          /* unused */
index 888bbc964d19079e4c54feee19b8c535bbf0109d..badaae707e4588ff917e6c07aea12057d29e9ccb 100644 (file)
@@ -109,10 +109,10 @@ and what kinds of objects they are.  In RTL, unlike Lisp, you cannot tell
 by looking at an operand what kind of object it is.  Instead, you must know
 from its context---from the expression code of the containing expression.
 For example, in an expression of code @code{subreg}, the first operand is
-to be regarded as an expression and the second operand as an integer.  In
-an expression of code @code{plus}, there are two operands, both of which
-are to be regarded as expressions.  In a @code{symbol_ref} expression,
-there is one operand, which is to be regarded as a string.
+to be regarded as an expression and the second operand as a polynomial
+integer.  In an expression of code @code{plus}, there are two operands,
+both of which are to be regarded as expressions.  In a @code{symbol_ref}
+expression, there is one operand, which is to be regarded as a string.
 
 Expressions are written as parentheses containing the name of the
 expression type, its flags and machine mode if any, and then the operands
@@ -209,7 +209,7 @@ chain, such as @code{NOTE}, @code{BARRIER}, and @code{CODE_LABEL}.
 For each expression code, @file{rtl.def} specifies the number of
 contained objects and their kinds using a sequence of characters
 called the @dfn{format} of the expression code.  For example,
-the format of @code{subreg} is @samp{ei}.
+the format of @code{subreg} is @samp{ep}.
 
 @cindex RTL format characters
 These are the most commonly used format characters:
@@ -258,6 +258,9 @@ An omitted vector is effectively the same as a vector of no elements.
 @item B
 @samp{B} indicates a pointer to basic block structure.
 
+@item p
+A polynomial integer.  At present this is used only for @code{SUBREG_BYTE}.
+
 @item 0
 @samp{0} means a slot whose contents do not fit any normal category.
 @samp{0} slots are not printed at all in dumps, and are often used in
@@ -340,16 +343,13 @@ stored in the operand.  You would do this based on the expression code of
 the containing expression.  That is also how you would know how many
 operands there are.
 
-For example, if @var{x} is a @code{subreg} expression, you know that it has
-two operands which can be correctly accessed as @code{XEXP (@var{x}, 0)}
-and @code{XINT (@var{x}, 1)}.  If you did @code{XINT (@var{x}, 0)}, you
-would get the address of the expression operand but cast as an integer;
-that might occasionally be useful, but it would be cleaner to write
-@code{(int) XEXP (@var{x}, 0)}.  @code{XEXP (@var{x}, 1)} would also
-compile without error, and would return the second, integer operand cast as
-an expression pointer, which would probably result in a crash when
-accessed.  Nothing stops you from writing @code{XEXP (@var{x}, 28)} either,
-but this will access memory past the end of the expression with
+For example, if @var{x} is an @code{int_list} expression, you know that it has
+two operands which can be correctly accessed as @code{XINT (@var{x}, 0)}
+and @code{XEXP (@var{x}, 1)}.  Incorrect accesses like
+@code{XEXP (@var{x}, 0)} and @code{XINT (@var{x}, 1)} would compile,
+but would trigger an internal compiler error when rtl checking is enabled.
+Nothing stops you from writing @code{XEXP (@var{x}, 28)} either, but
+this will access memory past the end of the expression with
 unpredictable results.
 
 Access to operands which are vectors is more complicated.  You can use the
@@ -2020,6 +2020,13 @@ on a @code{BYTES_BIG_ENDIAN}, @samp{UNITS_PER_WORD == 4} target is the same as
 on a little-endian, @samp{UNITS_PER_WORD == 4} target.  Both
 @code{subreg}s access the lower two bytes of register @var{x}.
 
+Note that the byte offset is a polynomial integer; it may not be a
+compile-time constant on targets with variable-sized modes.  However,
+the restrictions above mean that there are only a certain set of
+acceptable offsets for a given combination of @var{m1} and @var{m2}.
+The compiler can always tell which blocks a valid subreg occupies, and
+whether the subreg is a lowpart of a block.
+
 @end table
 
 A @code{MODE_PARTIAL_INT} mode behaves as if it were as wide as the
index 3e0a4168fd2f546fcdace35ffd432a8a0bbb484d..3740c5b7de0f7c6d9fc4093be3eb50666e37f22d 100644 (file)
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -1709,7 +1709,7 @@ find_shift_sequence (poly_int64 access_size,
         e.g. at -Os, even when no actual shift will be needed.  */
       if (store_info->const_rhs)
        {
-         unsigned int byte = subreg_lowpart_offset (new_mode, store_mode);
+         poly_uint64 byte = subreg_lowpart_offset (new_mode, store_mode);
          rtx ret = simplify_subreg (new_mode, store_info->const_rhs,
                                     store_mode, byte);
          if (ret && CONSTANT_P (ret))
index ed79fd019d4999bd9a30ed533acf882e2443bf4e..88c947f14e787a9def7689bc4460acc5a2ca8daf 100644 (file)
@@ -19226,8 +19226,8 @@ rtl_for_decl_location (tree decl)
           && GET_MODE (rtl) != TYPE_MODE (TREE_TYPE (decl)))
     {
       machine_mode addr_mode = get_address_mode (rtl);
-      HOST_WIDE_INT offset = byte_lowpart_offset (TYPE_MODE (TREE_TYPE (decl)),
-                                                 GET_MODE (rtl));
+      poly_int64 offset = byte_lowpart_offset (TYPE_MODE (TREE_TYPE (decl)),
+                                              GET_MODE (rtl));
 
       /* If a variable is declared "register" yet is smaller than
         a register, then if we store the variable to memory, it
@@ -19235,7 +19235,7 @@ rtl_for_decl_location (tree decl)
         fact we are not.  We need to adjust the offset of the
         storage location to reflect the actual value's bytes,
         else gdb will not be able to display it.  */
-      if (offset != 0)
+      if (maybe_ne (offset, 0))
        rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (decl)),
                           plus_constant (addr_mode, XEXP (rtl, 0), offset));
     }
index e1ed2b0b336644dd45d4b8220abf1cffe9cc3126..f8d2f55e05264470848bc30ec314a20a934f4188 100644 (file)
@@ -891,17 +891,17 @@ gen_tmp_stack_mem (machine_mode mode, rtx addr)
 
 bool
 validate_subreg (machine_mode omode, machine_mode imode,
-                const_rtx reg, unsigned int offset)
+                const_rtx reg, poly_uint64 offset)
 {
   unsigned int isize = GET_MODE_SIZE (imode);
   unsigned int osize = GET_MODE_SIZE (omode);
 
   /* All subregs must be aligned.  */
-  if (offset % osize != 0)
+  if (!multiple_p (offset, osize))
     return false;
 
   /* The subreg offset cannot be outside the inner object.  */
-  if (offset >= isize)
+  if (maybe_ge (offset, isize))
     return false;
 
   unsigned int regsize = REGMODE_NATURAL_SIZE (imode);
@@ -946,7 +946,7 @@ validate_subreg (machine_mode omode, machine_mode imode,
 
   /* Paradoxical subregs must have offset zero.  */
   if (osize > isize)
-    return offset == 0;
+    return known_eq (offset, 0U);
 
   /* This is a normal subreg.  Verify that the offset is representable.  */
 
@@ -978,18 +978,20 @@ validate_subreg (machine_mode omode, machine_mode imode,
   if (osize < regsize
       && ! (lra_in_progress && (FLOAT_MODE_P (imode) || FLOAT_MODE_P (omode))))
     {
-      unsigned int block_size = MIN (isize, regsize);
-      unsigned int offset_within_block = offset % block_size;
-      if (BYTES_BIG_ENDIAN
-         ? offset_within_block != block_size - osize
-         : offset_within_block != 0)
+      poly_uint64 block_size = MIN (isize, regsize);
+      unsigned int start_reg;
+      poly_uint64 offset_within_reg;
+      if (!can_div_trunc_p (offset, block_size, &start_reg, &offset_within_reg)
+         || (BYTES_BIG_ENDIAN
+             ? maybe_ne (offset_within_reg, block_size - osize)
+             : maybe_ne (offset_within_reg, 0U)))
        return false;
     }
   return true;
 }
 
 rtx
-gen_rtx_SUBREG (machine_mode mode, rtx reg, int offset)
+gen_rtx_SUBREG (machine_mode mode, rtx reg, poly_uint64 offset)
 {
   gcc_assert (validate_subreg (mode, GET_MODE (reg), reg, offset));
   return gen_rtx_raw_SUBREG (mode, reg, offset);
@@ -1090,7 +1092,7 @@ gen_rtvec_v (int n, rtx_insn **argp)
    paradoxical lowpart, in which case the offset will be negative
    on big-endian targets.  */
 
-int
+poly_int64
 byte_lowpart_offset (machine_mode outer_mode,
                     machine_mode inner_mode)
 {
@@ -1104,13 +1106,13 @@ byte_lowpart_offset (machine_mode outer_mode,
    from address X.  For paradoxical big-endian subregs this is a
    negative value, otherwise it's the same as OFFSET.  */
 
-int
+poly_int64
 subreg_memory_offset (machine_mode outer_mode, machine_mode inner_mode,
-                     unsigned int offset)
+                     poly_uint64 offset)
 {
   if (paradoxical_subreg_p (outer_mode, inner_mode))
     {
-      gcc_assert (offset == 0);
+      gcc_assert (known_eq (offset, 0U));
       return -subreg_lowpart_offset (inner_mode, outer_mode);
     }
   return offset;
@@ -1120,7 +1122,7 @@ subreg_memory_offset (machine_mode outer_mode, machine_mode inner_mode,
    if SUBREG_REG (X) were stored in memory.  The only significant thing
    about the current SUBREG_REG is its mode.  */
 
-int
+poly_int64
 subreg_memory_offset (const_rtx x)
 {
   return subreg_memory_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
@@ -1626,10 +1628,11 @@ gen_highpart_mode (machine_mode outermode, machine_mode innermode, rtx exp)
 /* Return the SUBREG_BYTE for a lowpart subreg whose outer mode has
    OUTER_BYTES bytes and whose inner mode has INNER_BYTES bytes.  */
 
-unsigned int
-subreg_size_lowpart_offset (unsigned int outer_bytes, unsigned int inner_bytes)
+poly_uint64
+subreg_size_lowpart_offset (poly_uint64 outer_bytes, poly_uint64 inner_bytes)
 {
-  if (outer_bytes > inner_bytes)
+  gcc_checking_assert (ordered_p (outer_bytes, inner_bytes));
+  if (maybe_gt (outer_bytes, inner_bytes))
     /* Paradoxical subregs always have a SUBREG_BYTE of 0.  */
     return 0;
 
@@ -1644,11 +1647,10 @@ subreg_size_lowpart_offset (unsigned int outer_bytes, unsigned int inner_bytes)
 /* Return the SUBREG_BYTE for a highpart subreg whose outer mode has
    OUTER_BYTES bytes and whose inner mode has INNER_BYTES bytes.  */
 
-unsigned int
-subreg_size_highpart_offset (unsigned int outer_bytes,
-                            unsigned int inner_bytes)
+poly_uint64
+subreg_size_highpart_offset (poly_uint64 outer_bytes, poly_uint64 inner_bytes)
 {
-  gcc_assert (inner_bytes >= outer_bytes);
+  gcc_assert (known_ge (inner_bytes, outer_bytes));
 
   if (BYTES_BIG_ENDIAN && WORDS_BIG_ENDIAN)
     return 0;
@@ -1672,8 +1674,9 @@ subreg_lowpart_p (const_rtx x)
   else if (GET_MODE (SUBREG_REG (x)) == VOIDmode)
     return 0;
 
-  return (subreg_lowpart_offset (GET_MODE (x), GET_MODE (SUBREG_REG (x)))
-         == SUBREG_BYTE (x));
+  return known_eq (subreg_lowpart_offset (GET_MODE (x),
+                                         GET_MODE (SUBREG_REG (x))),
+                  SUBREG_BYTE (x));
 }
 \f
 /* Return subword OFFSET of operand OP.
@@ -5732,6 +5735,7 @@ copy_insn_1 (rtx orig)
       case 't':
       case 'w':
       case 'i':
+      case 'p':
       case 's':
       case 'S':
       case 'u':
index 3a6a9ba0643eef9c9736790785d61708d6352b3b..6b22946f69a100a3910d88980adbcb67337a1c38 100644 (file)
@@ -2345,7 +2345,7 @@ extract_low_bits (machine_mode mode, machine_mode src_mode, rtx src)
       /* simplify_gen_subreg can't be used here, as if simplify_subreg
         fails, it will happily create (subreg (symbol_ref)) or similar
         invalid SUBREGs.  */
-      unsigned int byte = subreg_lowpart_offset (mode, src_mode);
+      poly_uint64 byte = subreg_lowpart_offset (mode, src_mode);
       rtx ret = simplify_subreg (mode, src, src_mode, byte);
       if (ret)
        return ret;
index 14348e31fb252822c7304a9cf4caec0c1dd22838..9020327984a01c7845b6ba570b32e3a7886bdba5 100644 (file)
@@ -2446,7 +2446,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
     {
       machine_mode outer = GET_MODE (dst);
       machine_mode inner;
-      HOST_WIDE_INT bytepos;
+      poly_int64 bytepos;
       bool done = false;
       rtx temp;
 
@@ -2461,7 +2461,7 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
        {
          inner = GET_MODE (tmps[start]);
          bytepos = subreg_lowpart_offset (inner, outer);
-         if (INTVAL (XEXP (XVECEXP (src, 0, start), 1)) == bytepos)
+         if (known_eq (INTVAL (XEXP (XVECEXP (src, 0, start), 1)), bytepos))
            {
              temp = simplify_gen_subreg (outer, tmps[start],
                                          inner, 0);
@@ -2480,7 +2480,8 @@ emit_group_store (rtx orig_dst, rtx src, tree type ATTRIBUTE_UNUSED, int ssize)
        {
          inner = GET_MODE (tmps[finish - 1]);
          bytepos = subreg_lowpart_offset (inner, outer);
-         if (INTVAL (XEXP (XVECEXP (src, 0, finish - 1), 1)) == bytepos)
+         if (known_eq (INTVAL (XEXP (XVECEXP (src, 0, finish - 1), 1)),
+                       bytepos))
            {
              temp = simplify_gen_subreg (outer, tmps[finish - 1],
                                          inner, 0);
@@ -3545,9 +3546,9 @@ undefined_operand_subword_p (const_rtx op, int i)
   if (GET_CODE (op) != SUBREG)
     return false;
   machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
-  HOST_WIDE_INT offset = i * UNITS_PER_WORD + subreg_memory_offset (op);
-  return (offset >= GET_MODE_SIZE (innermostmode)
-         || offset <= -UNITS_PER_WORD);
+  poly_int64 offset = i * UNITS_PER_WORD + subreg_memory_offset (op);
+  return (known_ge (offset, GET_MODE_SIZE (innermostmode))
+         || known_le (offset, -UNITS_PER_WORD));
 }
 
 /* A subroutine of emit_move_insn_1.  Generate a move from Y into X.
@@ -9247,8 +9248,8 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
                        >= GET_MODE_BITSIZE (word_mode)))
                  {
                    rtx_insn *seq, *seq_old;
-                   unsigned int high_off = subreg_highpart_offset (word_mode,
-                                                                   int_mode);
+                   poly_uint64 high_off = subreg_highpart_offset (word_mode,
+                                                                  int_mode);
                    bool extend_unsigned
                      = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (def)));
                    rtx low = lowpart_subreg (word_mode, op0, int_mode);
index e8954914e165f7efb003091054fe160f7297667f..29a5c1e824ba85a6d170a559ec731d8cd8965f86 100644 (file)
@@ -3251,7 +3251,7 @@ alter_subreg (rtx *xp, bool final_p)
      We are required to.  */
   if (MEM_P (y))
     {
-      int offset = SUBREG_BYTE (x);
+      poly_int64 offset = SUBREG_BYTE (x);
 
       /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
         contains 0 instead of the proper offset.  See simplify_subreg.  */
@@ -3274,7 +3274,7 @@ alter_subreg (rtx *xp, bool final_p)
        {
          /* Simplify_subreg can't handle some REG cases, but we have to.  */
          unsigned int regno;
-         HOST_WIDE_INT offset;
+         poly_int64 offset;
 
          regno = subreg_regno (x);
          if (subreg_lowpart_p (x))
@@ -4523,6 +4523,7 @@ leaf_renumber_regs_insn (rtx in_rtx)
       case '0':
       case 'i':
       case 'w':
+      case 'p':
       case 'n':
       case 'u':
        break;
index cdb2fc8a557b4e7220d496a50bcf0416066abd42..3d270154631e986bfcb98edd564da8d292f4988f 100644 (file)
@@ -2705,9 +2705,9 @@ assign_parm_find_stack_rtl (tree parm, struct assign_parm_data_one *data)
          set_mem_size (stack_parm, GET_MODE_SIZE (data->promoted_mode));
          if (MEM_EXPR (stack_parm) && MEM_OFFSET_KNOWN_P (stack_parm))
            {
-             int offset = subreg_lowpart_offset (DECL_MODE (parm),
-                                                 data->promoted_mode);
-             if (offset)
+             poly_int64 offset = subreg_lowpart_offset (DECL_MODE (parm),
+                                                        data->promoted_mode);
+             if (maybe_ne (offset, 0))
                set_mem_offset (stack_parm, MEM_OFFSET (stack_parm) - offset);
            }
        }
@@ -3431,12 +3431,13 @@ assign_parm_setup_stack (struct assign_parm_data_all *all, tree parm,
 
       if (data->stack_parm)
        {
-         int offset = subreg_lowpart_offset (data->nominal_mode,
-                                             GET_MODE (data->stack_parm));
+         poly_int64 offset
+           = subreg_lowpart_offset (data->nominal_mode,
+                                    GET_MODE (data->stack_parm));
          /* ??? This may need a big-endian conversion on sparc64.  */
          data->stack_parm
            = adjust_address (data->stack_parm, data->nominal_mode, 0);
-         if (offset && MEM_OFFSET_KNOWN_P (data->stack_parm))
+         if (maybe_ne (offset, 0) && MEM_OFFSET_KNOWN_P (data->stack_parm))
            set_mem_offset (data->stack_parm,
                            MEM_OFFSET (data->stack_parm) + offset);
        }
index b77006b48019d87a229a80fff819e75338d27aa3..764b5392c4e82dafc65ba9f9ee410e54e9ea1151 100644 (file)
@@ -1263,7 +1263,7 @@ forward_propagate_and_simplify (df_ref use, rtx_insn *def_insn, rtx def_set)
   reg = DF_REF_REG (use);
   if (GET_CODE (reg) == SUBREG && GET_CODE (SET_DEST (def_set)) == SUBREG)
     {
-      if (SUBREG_BYTE (SET_DEST (def_set)) != SUBREG_BYTE (reg))
+      if (maybe_ne (SUBREG_BYTE (SET_DEST (def_set)), SUBREG_BYTE (reg)))
        return false;
     }
   /* Check if the def had a subreg, but the use has the whole reg.  */
index a2a66e3e06f0c3f8899ecd216e3944e56c527c48..463782411de9576ad7b3f5b2db91c13c1dc20514 100644 (file)
@@ -563,6 +563,7 @@ attr_rtx_1 (enum rtx_code code, va_list p)
              break;
 
            default:
+             /* Don't need to handle 'p' for attributes.  */
              gcc_unreachable ();
            }
        }
index 059fdb60c9d2aa880ab833ba4639aff4555f4327..708da27221546c406030e88a4b07a51fb9df4a14 100644 (file)
@@ -235,6 +235,12 @@ gen_exp (rtx x, enum rtx_code subroutine_type, char *used)
          printf ("%u", REGNO (x));
          break;
 
+       case 'p':
+         /* We don't have a way of parsing polynomial offsets yet,
+            and hopefully never will.  */
+         printf ("%d", SUBREG_BYTE (x).to_constant ());
+         break;
+
        case 's':
          printf ("\"%s\"", XSTR (x, i));
          break;
index ee90c688c9c5deb704374b888298475572674709..d988ddb6f5f0f3fafa790a0ff16a4b0ea3c05e2f 100644 (file)
@@ -54,6 +54,9 @@ type_from_format (int c)
     case 'w':
       return "HOST_WIDE_INT ";
 
+    case 'p':
+      return "poly_uint16 ";
+
     case 's':
       return "const char *";
 
@@ -256,10 +259,12 @@ gendef (const char *format)
   puts ("  PUT_MODE_RAW (rt, mode);");
 
   for (p = format, i = j = 0; *p ; ++p, ++i)
-    if (*p != '0')
-      printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
-    else
+    if (*p == '0')
       printf ("  X0EXP (rt, %d) = NULL_RTX;\n", i);
+    else if (*p == 'p')
+      printf ("  SUBREG_BYTE (rt) = arg%d;\n", j++);
+    else
+      printf ("  %s (rt, %d) = arg%d;\n", accessor_from_format (*p), i, j++);
 
   puts ("\n  return rt;\n}\n");
   printf ("#define gen_rtx_fmt_%s(c, m", format);
index 8be413070f0f87db1c4d4ec0403164ef38c0e1cb..64190ed69e0fd24b58e48c86d63b907d26255908 100644 (file)
@@ -1241,6 +1241,11 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
              subname = "rt_int";
              break;
 
+           case 'p':
+             t = scalar_tp;
+             subname = "rt_subreg";
+             break;
+
            case '0':
              if (i == MEM && aindex == 1)
                t = mem_attrs_tp, subname = "rt_mem";
index 4b9c5379be329a852ae510b480cc13568c57162c..20239544bdb717ee6b9b6bcf0bce8a4ff5a9cfaa 100644 (file)
@@ -306,6 +306,9 @@ match_rtx (rtx x, struct link *path, int fail_label)
          printf ("  if (strcmp (XSTR (x, %d), \"%s\")) goto L%d;\n",
                  i, XSTR (x, i), fail_label);
        }
+      else if (fmt[i] == 'p')
+       /* Not going to support subregs for legacy define_peeholes.  */
+       gcc_unreachable ();
     }
 }
 
index 275168d60707be5146f3e4d7e05aa3ac71310c23..ce2f26272afdb62936de9ef1eec28df4e00c3972 100644 (file)
@@ -388,7 +388,7 @@ find_operand (rtx pattern, int n, rtx stop)
              return r;
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -439,7 +439,7 @@ find_matching_operand (rtx pattern, int n)
              return r;
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -797,7 +797,7 @@ validate_pattern (rtx pattern, md_rtx_info *info, rtx set, int set_code)
            validate_pattern (XVECEXP (pattern, i, j), info, NULL_RTX, 0);
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -1119,6 +1119,9 @@ struct rtx_test
     /* Check REGNO (X) == LABEL.  */
     REGNO_FIELD,
 
+    /* Check known_eq (SUBREG_BYTE (X), LABEL).  */
+    SUBREG_FIELD,
+
     /* Check XINT (X, u.opno) == LABEL.  */
     INT_FIELD,
 
@@ -1199,6 +1202,7 @@ struct rtx_test
   static rtx_test code (position *);
   static rtx_test mode (position *);
   static rtx_test regno_field (position *);
+  static rtx_test subreg_field (position *);
   static rtx_test int_field (position *, int);
   static rtx_test wide_int_field (position *, int);
   static rtx_test veclen (position *);
@@ -1243,6 +1247,13 @@ rtx_test::regno_field (position *pos)
   return res;
 }
 
+rtx_test
+rtx_test::subreg_field (position *pos)
+{
+  rtx_test res (pos, rtx_test::SUBREG_FIELD);
+  return res;
+}
+
 rtx_test
 rtx_test::int_field (position *pos, int opno)
 {
@@ -1364,6 +1375,7 @@ operator == (const rtx_test &a, const rtx_test &b)
     case rtx_test::CODE:
     case rtx_test::MODE:
     case rtx_test::REGNO_FIELD:
+    case rtx_test::SUBREG_FIELD:
     case rtx_test::VECLEN:
     case rtx_test::HAVE_NUM_CLOBBERS:
       return true;
@@ -1821,6 +1833,7 @@ safe_to_hoist_p (decision *d, const rtx_test &test, known_conditions *kc)
       gcc_unreachable ();
 
     case rtx_test::REGNO_FIELD:
+    case rtx_test::SUBREG_FIELD:
     case rtx_test::INT_FIELD:
     case rtx_test::WIDE_INT_FIELD:
     case rtx_test::VECLEN:
@@ -2028,6 +2041,7 @@ transition_parameter_type (rtx_test::kind_enum kind)
       return parameter::MODE;
 
     case rtx_test::REGNO_FIELD:
+    case rtx_test::SUBREG_FIELD:
       return parameter::UINT;
 
     case rtx_test::INT_FIELD:
@@ -4039,6 +4053,14 @@ match_pattern_2 (state *s, md_rtx_info *info, position *pos, rtx pattern)
                                      XWINT (pattern, 0), false);
                    break;
 
+                 case 'p':
+                   /* We don't have a way of parsing polynomial offsets yet,
+                      and hopefully never will.  */
+                   s = add_decision (s, rtx_test::subreg_field (pos),
+                                     SUBREG_BYTE (pattern).to_constant (),
+                                     false);
+                   break;
+
                  case '0':
                    break;
 
@@ -4571,6 +4593,12 @@ print_nonbool_test (output_state *os, const rtx_test &test)
       printf (")");
       break;
 
+    case rtx_test::SUBREG_FIELD:
+      printf ("SUBREG_BYTE (");
+      print_test_rtx (os, test);
+      printf (")");
+      break;
+
     case rtx_test::WIDE_INT_FIELD:
       printf ("XWINT (");
       print_test_rtx (os, test);
@@ -4653,6 +4681,14 @@ print_test (output_state *os, const rtx_test &test, bool is_param,
       print_label_value (test, is_param, value);
       break;
 
+    case rtx_test::SUBREG_FIELD:
+      printf ("%s (", invert_p ? "maybe_ne" : "known_eq");
+      print_nonbool_test (os, test);
+      printf (", ");
+      print_label_value (test, is_param, value);
+      printf (")");
+      break;
+
     case rtx_test::SAVED_CONST_INT:
       gcc_assert (!is_param && value == 1);
       print_test_rtx (os, test);
index c79feb48ad15d619cf4e8fde2a65995a42b4ddf4..e7662b08247ba264bcf4d277ae3e0175904ef91b 100644 (file)
@@ -883,7 +883,7 @@ subst_pattern_match (rtx x, rtx pt, file_location loc)
 
       switch (fmt[i])
        {
-       case 'i': case 'r': case 'w': case 's':
+       case 'r': case 'p': case 'i': case 'w': case 's':
          continue;
 
        case 'e': case 'u':
@@ -1047,7 +1047,8 @@ get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
              return 0;
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
@@ -1106,7 +1107,8 @@ collect_insn_data (rtx pattern, int *palt, int *pmax)
            collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
@@ -1190,7 +1192,7 @@ alter_predicate_for_insn (rtx pattern, int alt, int max_op,
            }
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -1248,7 +1250,7 @@ alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
            }
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -2164,7 +2166,8 @@ subst_dup (rtx pattern, int n_alt, int n_subst_alt)
                                                   n_alt, n_subst_alt);
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
index eb3da68d1e834e19d5283ae9f6303f34c639b0fb..591105176d1eabf9a241100432f41def323df07a 100644 (file)
@@ -894,7 +894,7 @@ noce_emit_move_insn (rtx x, rtx y)
 {
   machine_mode outmode;
   rtx outer, inner;
-  int bitpos;
+  poly_int64 bitpos;
 
   if (GET_CODE (x) != STRICT_LOW_PART)
     {
@@ -1724,12 +1724,12 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, enum rtx_code code,
     {
       rtx reg_vtrue = SUBREG_REG (vtrue);
       rtx reg_vfalse = SUBREG_REG (vfalse);
-      unsigned int byte_vtrue = SUBREG_BYTE (vtrue);
-      unsigned int byte_vfalse = SUBREG_BYTE (vfalse);
+      poly_uint64 byte_vtrue = SUBREG_BYTE (vtrue);
+      poly_uint64 byte_vfalse = SUBREG_BYTE (vfalse);
       rtx promoted_target;
 
       if (GET_MODE (reg_vtrue) != GET_MODE (reg_vfalse)
-         || byte_vtrue != byte_vfalse
+         || maybe_ne (byte_vtrue, byte_vfalse)
          || (SUBREG_PROMOTED_VAR_P (vtrue)
              != SUBREG_PROMOTED_VAR_P (vfalse))
          || (SUBREG_PROMOTED_GET (vtrue)
index 50069c1d10574fc6257c0b0b4198c26bf7b76f57..61c03e2ddfdc16118e1f73e06fd23214a8f203e7 100644 (file)
@@ -226,8 +226,11 @@ go_through_subreg (rtx x, int *offset)
   if (REGNO (reg) < FIRST_PSEUDO_REGISTER)
     *offset = subreg_regno_offset (REGNO (reg), GET_MODE (reg),
                                   SUBREG_BYTE (x), GET_MODE (x));
-  else
-    *offset = (SUBREG_BYTE (x) / REGMODE_NATURAL_SIZE (GET_MODE (x)));
+  else if (!can_div_trunc_p (SUBREG_BYTE (x),
+                            REGMODE_NATURAL_SIZE (GET_MODE (x)), offset))
+    /* Checked by validate_subreg.  We must know at compile time which
+       inner hard registers are being accessed.  */
+    gcc_unreachable ();
   return reg;
 }
 
index 0dff248ed4810c18876efbd5c8a90ee2d86b2981..d70868d50de0254d03991a82b0c86ffe33f3f885 100644 (file)
@@ -919,7 +919,7 @@ process_single_reg_class_operands (bool in_p, int freq)
                    (subreg:YMODE (reg:XMODE XREGNO) OFFSET).  */
              machine_mode ymode, xmode;
              int xregno, yregno;
-             HOST_WIDE_INT offset;
+             poly_int64 offset;
 
              xmode = recog_data.operand_mode[i];
              xregno = ira_class_singleton[cl][xmode];
index 13972540a9cfa45f9fbe3662e7edd3ca7d6b1b90..765a1d01a5d2e23756e8758d7e82bb7ce25255b5 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -4048,8 +4048,7 @@ get_subreg_tracking_sizes (rtx x, HOST_WIDE_INT *outer_size,
   rtx reg = regno_reg_rtx[REGNO (SUBREG_REG (x))];
   *outer_size = GET_MODE_SIZE (GET_MODE (x));
   *inner_size = GET_MODE_SIZE (GET_MODE (reg));
-  *start = SUBREG_BYTE (x);
-  return true;
+  return SUBREG_BYTE (x).is_constant (start);
 }
 
 /* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] for
index e60a6c6f8e6663bf9e080300c31c8aeee5cfef17..8ee05129bafb518826c7507f5d6d6223c191668f 100644 (file)
@@ -1724,7 +1724,7 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
                                  && REG_P (SUBREG_REG (y)))))
     {
       int reg_x = -1, reg_y = -1;
-      int byte_x = 0, byte_y = 0;
+      poly_int64 byte_x = 0, byte_y = 0;
       struct subreg_info info;
 
       if (GET_MODE (x) != GET_MODE (y))
@@ -1781,7 +1781,7 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
            reg_y = reg_renumber[reg_y];
        }
 
-      return reg_x >= 0 && reg_x == reg_y && byte_x == byte_y;
+      return reg_x >= 0 && reg_x == reg_y && known_eq (byte_x, byte_y);
     }
 
   /* Now we have disposed of all the cases
@@ -1873,6 +1873,11 @@ rtx_renumbered_equal_p (const_rtx x, const_rtx y)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 't':
          if (XTREE (x, i) != XTREE (y, i))
            return 0;
index 1cdb5cbf5854ea738d2f50e4c1d128fc39df2b55..ed491697f3246e953bbb3d985bd60ed46b16a55f 100644 (file)
@@ -335,6 +335,8 @@ hash_invariant_expr_1 (rtx_insn *insn, rtx x)
        }
       else if (fmt[i] == 'i' || fmt[i] == 'n')
        val ^= XINT (x, i);
+      else if (fmt[i] == 'p')
+       val ^= constant_lower_bound (SUBREG_BYTE (x));
     }
 
   return val;
@@ -420,6 +422,11 @@ invariant_expr_equal_p (rtx_insn *insn1, rtx e1, rtx_insn *insn2, rtx e2)
          if (XINT (e1, i) != XINT (e2, i))
            return false;
        }
+      else if (fmt[i] == 'p')
+       {
+         if (maybe_ne (SUBREG_BYTE (e1), SUBREG_BYTE (e2)))
+           return false;
+       }
       /* Unhandled type of subexpression, we fail conservatively.  */
       else
        return false;
index b54e0703d097a572d9da108ddfa725d23c461eaa..e10844cda7694217e2fc2f2529051d9066111bbf 100644 (file)
@@ -609,19 +609,21 @@ decompose_register (unsigned int regno)
 /* Get a SUBREG of a CONCATN.  */
 
 static rtx
-simplify_subreg_concatn (machine_mode outermode, rtx op,
-                        unsigned int byte)
+simplify_subreg_concatn (machine_mode outermode, rtx op, poly_uint64 orig_byte)
 {
   unsigned int outer_size, outer_words, inner_size, inner_words;
   machine_mode innermode, partmode;
   rtx part;
   unsigned int final_offset;
+  unsigned int byte;
 
   innermode = GET_MODE (op);
   if (!interesting_mode_p (outermode, &outer_size, &outer_words)
       || !interesting_mode_p (innermode, &inner_size, &inner_words))
     gcc_unreachable ();
 
+  /* Must be constant if interesting_mode_p passes.  */
+  byte = orig_byte.to_constant ();
   gcc_assert (GET_CODE (op) == CONCATN);
   gcc_assert (byte % outer_size == 0);
 
@@ -667,7 +669,7 @@ simplify_gen_subreg_concatn (machine_mode outermode, rtx op,
 
       if ((GET_MODE_SIZE (GET_MODE (op))
           == GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
-         && SUBREG_BYTE (op) == 0)
+         && known_eq (SUBREG_BYTE (op), 0))
        return simplify_gen_subreg_concatn (outermode, SUBREG_REG (op),
                                            GET_MODE (SUBREG_REG (op)), byte);
 
@@ -866,7 +868,7 @@ resolve_simple_move (rtx set, rtx_insn *insn)
 
   if (GET_CODE (src) == SUBREG
       && resolve_reg_p (SUBREG_REG (src))
-      && (SUBREG_BYTE (src) != 0
+      && (maybe_ne (SUBREG_BYTE (src), 0)
          || (GET_MODE_SIZE (orig_mode)
              != GET_MODE_SIZE (GET_MODE (SUBREG_REG (src))))))
     {
@@ -881,7 +883,7 @@ resolve_simple_move (rtx set, rtx_insn *insn)
 
   if (GET_CODE (dest) == SUBREG
       && resolve_reg_p (SUBREG_REG (dest))
-      && (SUBREG_BYTE (dest) != 0
+      && (maybe_ne (SUBREG_BYTE (dest), 0)
          || (GET_MODE_SIZE (orig_mode)
              != GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest))))))
     {
index 0681a4c188d3958e6519bc7708a0b2eafe7c9b18..5162183f913a7952de7d61e09448bd72e23f0686 100644 (file)
@@ -786,6 +786,11 @@ operands_match_p (rtx x, rtx y, int y_hard_regno)
            return false;
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return false;
+         break;
+
        case 'e':
          val = operands_match_p (XEXP (x, i), XEXP (y, i), -1);
          if (val == 0)
@@ -974,7 +979,7 @@ match_reload (signed char out, signed char *ins, signed char *outs,
              if (REG_P (subreg_reg)
                  && (int) REGNO (subreg_reg) < lra_new_regno_start
                  && GET_MODE (subreg_reg) == outmode
-                 && SUBREG_BYTE (in_rtx) == SUBREG_BYTE (new_in_reg)
+                 && known_eq (SUBREG_BYTE (in_rtx), SUBREG_BYTE (new_in_reg))
                  && find_regno_note (curr_insn, REG_DEAD, REGNO (subreg_reg))
                  && (! early_clobber_p
                      || check_conflict_input_operands (REGNO (subreg_reg),
@@ -4205,7 +4210,7 @@ curr_insn_transform (bool check_only_p)
        {
          machine_mode mode;
          rtx reg, *loc;
-         int hard_regno, byte;
+         int hard_regno;
          enum op_type type = curr_static_id->operand[i].type;
 
          loc = curr_id->operand_loc[i];
@@ -4213,7 +4218,7 @@ curr_insn_transform (bool check_only_p)
          if (GET_CODE (*loc) == SUBREG)
            {
              reg = SUBREG_REG (*loc);
-             byte = SUBREG_BYTE (*loc);
+             poly_int64 byte = SUBREG_BYTE (*loc);
              if (REG_P (reg)
                  /* Strict_low_part requires reloading the register and not
                     just the subreg.  Likewise for a strict subreg no wider
index 9abcda4467c2f7e7ffbf2c09e22cdf2f309090c8..60117f5600ee628e49378b8a6e3a17ba0709ac10 100644 (file)
@@ -136,7 +136,7 @@ assign_mem_slot (int i)
   machine_mode wider_mode
     = wider_subreg_mode (mode, lra_reg_info[i].biggest_mode);
   HOST_WIDE_INT total_size = GET_MODE_SIZE (wider_mode);
-  HOST_WIDE_INT adjust = 0;
+  poly_int64 adjust = 0;
 
   lra_assert (regno_reg_rtx[i] != NULL_RTX && REG_P (regno_reg_rtx[i])
              && lra_reg_info[i].nrefs != 0 && reg_renumber[i] < 0);
index 8e4a81903f5ea3617d346c03baed41b914ae3999..ced8ec9823e3a0161781d10f889687dfa61ee71f 100644 (file)
@@ -1704,9 +1704,9 @@ move2add_valid_value_p (int regno, scalar_int_mode mode)
         mode after truncation only if (REG:mode regno) is the lowpart of
         (REG:reg_mode[regno] regno).  Now, for big endian, the starting
         regno of the lowpart might be different.  */
-      int s_off = subreg_lowpart_offset (mode, old_mode);
+      poly_int64 s_off = subreg_lowpart_offset (mode, old_mode);
       s_off = subreg_regno_offset (regno, old_mode, s_off, mode);
-      if (s_off != 0)
+      if (maybe_ne (s_off, 0))
        /* We could in principle adjust regno, check reg_mode[regno] to be
           BLKmode, and return s_off to the caller (vs. -1 for failure),
           but we currently have no callers that could make use of this
index 1cf2604a8672d2bd0d752041a63b4a8f1a1d8dc8..379ff0071cfcdf02f71d8ef81edc1dba7f5f9e6b 100644 (file)
@@ -178,6 +178,7 @@ print_mem_expr (FILE *outfile, const_tree expr)
   fputc (' ', outfile);
   print_generic_expr (outfile, CONST_CAST_TREE (expr), dump_flags);
 }
+#endif
 
 /* Print X to FILE.  */
 
@@ -195,7 +196,6 @@ print_poly_int (FILE *file, poly_int64 x)
       fprintf (file, "]");
     }
 }
-#endif
 
 /* Subroutine of print_rtx_operand for handling code '0'.
    0 indicates a field for internal use that should not be printed.
@@ -638,6 +638,11 @@ rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
       print_rtx_operand_code_i (in_rtx, idx);
       break;
 
+    case 'p':
+      fprintf (m_outfile, " ");
+      print_poly_int (m_outfile, SUBREG_BYTE (in_rtx));
+      break;
+
     case 'r':
       print_rtx_operand_code_r (in_rtx);
       break;
@@ -1688,7 +1693,8 @@ print_value (pretty_printer *pp, const_rtx x, int verbose)
       break;
     case SUBREG:
       print_value (pp, SUBREG_REG (x), verbose);
-      pp_printf (pp, "#%d", SUBREG_BYTE (x));
+      pp_printf (pp, "#");
+      pp_wide_integer (pp, SUBREG_BYTE (x));
       break;
     case SCRATCH:
     case CC0:
index b1ef52b9a3d50d5a187eb0a117401e684124c45c..7e7dd0088d759cb6da53f35bb6d76d9344ed4362 100644 (file)
@@ -222,7 +222,10 @@ find_int (const char *name)
 static void
 apply_int_iterator (rtx x, unsigned int index, int value)
 {
-  XINT (x, index) = value;
+  if (GET_CODE (x) == SUBREG)
+    SUBREG_BYTE (x) = value;
+  else
+    XINT (x, index) = value;
 }
 
 #ifdef GENERATOR_FILE
@@ -1608,6 +1611,7 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx)
 
     case 'i':
     case 'n':
+    case 'p':
       /* Can be an iterator or an integer constant.  */
       read_name (&name);
       record_potential_iterator_use (&ints, return_rtx, idx, name.string);
index 3da6e5b827c85dad49ba13062bed347164016807..8e1218b519d80fceefcf558d88d77e7d44fbef7c 100644 (file)
@@ -1006,7 +1006,8 @@ general_operand (rtx op, machine_mode mode)
         might be called from cleanup_subreg_operands.
 
         ??? This is a kludge.  */
-      if (!reload_completed && SUBREG_BYTE (op) != 0
+      if (!reload_completed
+         && maybe_ne (SUBREG_BYTE (op), 0)
          && MEM_P (sub))
        return 0;
 
@@ -1368,9 +1369,6 @@ indirect_operand (rtx op, machine_mode mode)
   if (! reload_completed
       && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
     {
-      int offset = SUBREG_BYTE (op);
-      rtx inner = SUBREG_REG (op);
-
       if (mode != VOIDmode && GET_MODE (op) != mode)
        return 0;
 
@@ -1378,12 +1376,10 @@ indirect_operand (rtx op, machine_mode mode)
         address is if OFFSET is zero and the address already is an operand
         or if the address is (plus Y (const_int -OFFSET)) and Y is an
         operand.  */
-
-      return ((offset == 0 && general_operand (XEXP (inner, 0), Pmode))
-             || (GET_CODE (XEXP (inner, 0)) == PLUS
-                 && CONST_INT_P (XEXP (XEXP (inner, 0), 1))
-                 && INTVAL (XEXP (XEXP (inner, 0), 1)) == -offset
-                 && general_operand (XEXP (XEXP (inner, 0), 0), Pmode)));
+      poly_int64 offset;
+      rtx addr = strip_offset (XEXP (SUBREG_REG (op), 0), &offset);
+      return (known_eq (offset + SUBREG_BYTE (op), 0)
+             && general_operand (addr, Pmode));
     }
 
   return (MEM_P (op)
index 33e6e62a4c267b2aee80a1e946226574f5a3fc09..10d8395050609aba11c27ea7e7847f99b7959893 100644 (file)
@@ -345,7 +345,8 @@ copy_value (rtx dest, rtx src, struct value_data *vd)
      We can't properly represent the latter case in our tables, so don't
      record anything then.  */
   else if (sn < hard_regno_nregs (sr, vd->e[sr].mode)
-          && subreg_lowpart_offset (GET_MODE (dest), vd->e[sr].mode) != 0)
+          && maybe_ne (subreg_lowpart_offset (GET_MODE (dest),
+                                              vd->e[sr].mode), 0U))
     return;
 
   /* If SRC had been assigned a mode narrower than the copy, we can't
@@ -407,7 +408,7 @@ maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
       int use_nregs = hard_regno_nregs (copy_regno, new_mode);
       int copy_offset
        = GET_MODE_SIZE (copy_mode) / copy_nregs * (copy_nregs - use_nregs);
-      unsigned int offset
+      poly_uint64 offset
        = subreg_size_lowpart_offset (GET_MODE_SIZE (new_mode) + copy_offset,
                                      GET_MODE_SIZE (orig_mode));
       regno += subreg_regno_offset (regno, orig_mode, offset, new_mode);
@@ -868,7 +869,8 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
              /* And likewise, if we are narrowing on big endian the transformation
                 is also invalid.  */
              if (REG_NREGS (src) < hard_regno_nregs (regno, vd->e[regno].mode)
-                 && subreg_lowpart_offset (mode, vd->e[regno].mode) != 0)
+                 && maybe_ne (subreg_lowpart_offset (mode,
+                                                     vd->e[regno].mode), 0U))
                goto no_move_special_case;
            }
 
index 4061736f537efeb6227ebe9df907a43db0b40c08..3d1c2ed51664f56dea5d9ad7f00914184f70abac 100644 (file)
@@ -1206,7 +1206,9 @@ reg_classes_intersect_p (reg_class_t c1, reg_class_t c2)
 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
@@ -1231,9 +1233,11 @@ simplifiable_subregs (const subreg_shape &shape)
   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)
     {
@@ -1294,7 +1298,7 @@ record_subregs_of_mode (rtx subreg, bool partial_def)
       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)
+      if (known_ge (shape.offset, size))
        shape.offset -= size;
       else
        shape.offset += size;
index c6664955fe9374ab1c8bdbf78dc8f788b5915d0d..59b0326a46022825b170b3429ed069f866a9dccf 100644 (file)
@@ -2307,6 +2307,11 @@ operands_match_p (rtx x, rtx y)
            return 0;
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'e':
          val = operands_match_p (XEXP (x, i), XEXP (y, i));
          if (val == 0)
@@ -6095,7 +6100,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
   int regno = REGNO (SUBREG_REG (x));
   int reloaded = 0;
   rtx tem, orig;
-  int offset;
+  poly_int64 offset;
 
   gcc_assert (reg_equiv_memory_loc (regno) != 0);
 
@@ -6142,7 +6147,7 @@ find_reloads_subreg_address (rtx x, int opnum, enum reload_type type,
                                   XEXP (tem, 0), &XEXP (tem, 0),
                                   opnum, type, ind_levels, insn);
   /* ??? Do we need to handle nonzero offsets somehow?  */
-  if (!offset && !rtx_equal_p (tem, orig))
+  if (known_eq (offset, 0) && !rtx_equal_p (tem, orig))
     push_reg_equiv_alt_mem (regno, tem);
 
   /* For some processors an address may be valid in the original mode but
index 1c94f303d05dbcbc43af1074c5edd89b987ce8a6..f17edda9721a10cf021d397c56d1ee49cd71d105 100644 (file)
@@ -2140,12 +2140,12 @@ alter_reg (int i, int from_reg, bool dont_share_p)
     {
       rtx x = NULL_RTX;
       machine_mode mode = GET_MODE (regno_reg_rtx[i]);
-      unsigned int inherent_size = PSEUDO_REGNO_BYTES (i);
+      unsigned HOST_WIDE_INT inherent_size = PSEUDO_REGNO_BYTES (i);
       unsigned int inherent_align = GET_MODE_ALIGNMENT (mode);
       machine_mode wider_mode = wider_subreg_mode (mode, reg_max_ref_mode[i]);
-      unsigned int total_size = GET_MODE_SIZE (wider_mode);
+      unsigned HOST_WIDE_INT total_size = GET_MODE_SIZE (wider_mode);
       unsigned int min_align = GET_MODE_BITSIZE (reg_max_ref_mode[i]);
-      int adjust = 0;
+      poly_int64 adjust = 0;
 
       something_was_spilled = true;
 
@@ -2185,7 +2185,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
          if (BYTES_BIG_ENDIAN)
            {
              adjust = inherent_size - total_size;
-             if (adjust)
+             if (maybe_ne (adjust, 0))
                {
                  unsigned int total_bits = total_size * BITS_PER_UNIT;
                  machine_mode mem_mode
@@ -2237,7 +2237,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
          if (BYTES_BIG_ENDIAN)
            {
              adjust = GET_MODE_SIZE (mode) - total_size;
-             if (adjust)
+             if (maybe_ne (adjust, 0))
                {
                  unsigned int total_bits = total_size * BITS_PER_UNIT;
                  machine_mode mem_mode
@@ -6347,12 +6347,12 @@ replaced_subreg (rtx x)
    SUBREG is non-NULL if the pseudo is a subreg whose reg is a pseudo,
    otherwise it is NULL.  */
 
-static int
+static poly_int64
 compute_reload_subreg_offset (machine_mode outermode,
                              rtx subreg,
                              machine_mode innermode)
 {
-  int outer_offset;
+  poly_int64 outer_offset;
   machine_mode middlemode;
 
   if (!subreg)
@@ -6506,7 +6506,7 @@ choose_reload_regs (struct insn_chain *chain)
 
          if (inheritance)
            {
-             int byte = 0;
+             poly_int64 byte = 0;
              int regno = -1;
              machine_mode mode = VOIDmode;
              rtx subreg = NULL_RTX;
@@ -6556,8 +6556,9 @@ choose_reload_regs (struct insn_chain *chain)
 
              if (regno >= 0
                  && reg_last_reload_reg[regno] != 0
-                 && (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno]))
-                     >= GET_MODE_SIZE (mode) + byte)
+                 && (known_ge
+                     (GET_MODE_SIZE (GET_MODE (reg_last_reload_reg[regno])),
+                      GET_MODE_SIZE (mode) + byte))
                  /* Verify that the register it's in can be used in
                     mode MODE.  */
                  && (REG_CAN_CHANGE_MODE_P
index c51b4feb3d4e8e8a179e16cc672b5466eea52dfe..4d037816c974da083576cb51db8ca7eb5b6e4a66 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -89,7 +89,8 @@ const char * const rtx_format[NUM_RTX_CODE] = {
      "b" is a pointer to a bitmap header.
      "B" is a basic block pointer.
      "t" is a tree pointer.
-     "r" a register.  */
+     "r" a register.
+     "p" is a poly_uint16 offset.  */
 
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   FORMAT ,
 #include "rtl.def"             /* rtl expressions are defined here */
@@ -346,6 +347,7 @@ copy_rtx (rtx orig)
       case 't':
       case 'w':
       case 'i':
+      case 'p':
       case 's':
       case 'S':
       case 'T':
@@ -500,6 +502,11 @@ rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
@@ -637,6 +644,11 @@ rtx_equal_p (const_rtx x, const_rtx y)
            }
          break;
 
+       case 'p':
+         if (maybe_ne (SUBREG_BYTE (x), SUBREG_BYTE (y)))
+           return 0;
+         break;
+
        case 'V':
        case 'E':
          /* Two vectors must have the same length.  */
index 01399440b7ce2eea6d9c812f0444a4359e3d6d02..ea08f7caf070a39b7e988ee16b0b07fd81958657 100644 (file)
@@ -394,7 +394,7 @@ DEF_RTL_EXPR(SCRATCH, "scratch", "", RTX_OBJ)
 
 /* A reference to a part of another value.  The first operand is the
    complete value and the second is the byte offset of the selected part.   */
-DEF_RTL_EXPR(SUBREG, "subreg", "ei", RTX_EXTRA)
+DEF_RTL_EXPR(SUBREG, "subreg", "ep", RTX_EXTRA)
 
 /* This one-argument rtx is used for move instructions
    that are guaranteed to alter only the low part of a destination.
index f09a9f468755382538dbc88b238c3dcda8fa100d..df410789d2b4528496db3c84d3be759a7b9048d3 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -198,6 +198,7 @@ union rtunion
 {
   int rt_int;
   unsigned int rt_uint;
+  poly_uint16_pod rt_subreg;
   const char *rt_str;
   rtx rt_rtx;
   rtvec rt_rtvec;
@@ -1335,6 +1336,7 @@ extern void rtl_check_failed_flag (const char *, const_rtx, const char *,
 
 #define XCINT(RTX, N, C)      (RTL_CHECKC1 (RTX, N, C).rt_int)
 #define XCUINT(RTX, N, C)     (RTL_CHECKC1 (RTX, N, C).rt_uint)
+#define XCSUBREG(RTX, N, C)   (RTL_CHECKC1 (RTX, N, C).rt_subreg)
 #define XCSTR(RTX, N, C)      (RTL_CHECKC1 (RTX, N, C).rt_str)
 #define XCEXP(RTX, N, C)      (RTL_CHECKC1 (RTX, N, C).rt_rtx)
 #define XCVEC(RTX, N, C)      (RTL_CHECKC1 (RTX, N, C).rt_rtvec)
@@ -1963,7 +1965,7 @@ set_regno_raw (rtx x, unsigned int regno, unsigned int nregs)
    SUBREG_BYTE extracts the byte-number.  */
 
 #define SUBREG_REG(RTX) XCEXP (RTX, 0, SUBREG)
-#define SUBREG_BYTE(RTX) XCUINT (RTX, 1, SUBREG)
+#define SUBREG_BYTE(RTX) XCSUBREG (RTX, 1, SUBREG)
 
 /* in rtlanal.c */
 /* Return the right cost to give to an operation
@@ -2036,19 +2038,19 @@ costs_add_n_insns (struct full_rtx_costs *c, int n)
    offset     == the SUBREG_BYTE
    outer_mode == the mode of the SUBREG itself.  */
 struct subreg_shape {
-  subreg_shape (machine_mode, unsigned int, machine_mode);
+  subreg_shape (machine_mode, poly_uint16, machine_mode);
   bool operator == (const subreg_shape &) const;
   bool operator != (const subreg_shape &) const;
-  unsigned int unique_id () const;
+  unsigned HOST_WIDE_INT unique_id () const;
 
   machine_mode inner_mode;
-  unsigned int offset;
+  poly_uint16 offset;
   machine_mode outer_mode;
 };
 
 inline
 subreg_shape::subreg_shape (machine_mode inner_mode_in,
-                           unsigned int offset_in,
+                           poly_uint16 offset_in,
                            machine_mode outer_mode_in)
   : inner_mode (inner_mode_in), offset (offset_in), outer_mode (outer_mode_in)
 {}
@@ -2057,7 +2059,7 @@ inline bool
 subreg_shape::operator == (const subreg_shape &other) const
 {
   return (inner_mode == other.inner_mode
-         && offset == other.offset
+         && known_eq (offset, other.offset)
          && outer_mode == other.outer_mode);
 }
 
@@ -2072,11 +2074,16 @@ subreg_shape::operator != (const subreg_shape &other) const
    current mode is anywhere near being 65536 bytes in size, so the
    id comfortably fits in an int.  */
 
-inline unsigned int
+inline unsigned HOST_WIDE_INT
 subreg_shape::unique_id () const
 {
-  STATIC_ASSERT (MAX_MACHINE_MODE <= 256);
-  return (int) inner_mode + ((int) outer_mode << 8) + (offset << 16);
+  { STATIC_ASSERT (MAX_MACHINE_MODE <= 256); }
+  { STATIC_ASSERT (NUM_POLY_INT_COEFFS <= 3); }
+  { STATIC_ASSERT (sizeof (offset.coeffs[0]) <= 2); }
+  int res = (int) inner_mode + ((int) outer_mode << 8);
+  for (int i = 0; i < NUM_POLY_INT_COEFFS; ++i)
+    res += (HOST_WIDE_INT) offset.coeffs[i] << ((1 + i) * 16);
+  return res;
 }
 
 /* Return the shape of a SUBREG rtx.  */
@@ -2330,11 +2337,10 @@ extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
 extern int address_cost (rtx, machine_mode, addr_space_t, bool);
 extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
                               struct full_rtx_costs *);
-extern unsigned int subreg_lsb (const_rtx);
-extern unsigned int subreg_lsb_1 (machine_mode, machine_mode,
-                                 unsigned int);
-extern unsigned int subreg_size_offset_from_lsb (unsigned int, unsigned int,
-                                                unsigned int);
+extern poly_uint64 subreg_lsb (const_rtx);
+extern poly_uint64 subreg_lsb_1 (machine_mode, machine_mode, poly_uint64);
+extern poly_uint64 subreg_size_offset_from_lsb (poly_uint64, poly_uint64,
+                                               poly_uint64);
 extern bool read_modify_subreg_p (const_rtx);
 
 /* Return the subreg byte offset for a subreg whose outer mode is
@@ -2343,22 +2349,22 @@ extern bool read_modify_subreg_p (const_rtx);
    the inner value.  This is the inverse of subreg_lsb_1 (which converts
    byte offsets to bit shifts).  */
 
-inline unsigned int
+inline poly_uint64
 subreg_offset_from_lsb (machine_mode outer_mode,
                        machine_mode inner_mode,
-                       unsigned int lsb_shift)
+                       poly_uint64 lsb_shift)
 {
   return subreg_size_offset_from_lsb (GET_MODE_SIZE (outer_mode),
                                      GET_MODE_SIZE (inner_mode), lsb_shift);
 }
 
-extern unsigned int subreg_regno_offset        (unsigned int, machine_mode,
-                                        unsigned int, machine_mode);
+extern unsigned int subreg_regno_offset (unsigned int, machine_mode,
+                                        poly_uint64, machine_mode);
 extern bool subreg_offset_representable_p (unsigned int, machine_mode,
-                                          unsigned int, machine_mode);
+                                          poly_uint64, machine_mode);
 extern unsigned int subreg_regno (const_rtx);
 extern int simplify_subreg_regno (unsigned int, machine_mode,
-                                 unsigned int, machine_mode);
+                                 poly_uint64, machine_mode);
 extern unsigned int subreg_nregs (const_rtx);
 extern unsigned int subreg_nregs_with_regno (unsigned int, const_rtx);
 extern unsigned HOST_WIDE_INT nonzero_bits (const_rtx, machine_mode);
@@ -3042,7 +3048,7 @@ extern rtx operand_subword (rtx, unsigned int, int, machine_mode);
 /* In emit-rtl.c */
 extern rtx operand_subword_force (rtx, unsigned int, machine_mode);
 extern int subreg_lowpart_p (const_rtx);
-extern unsigned int subreg_size_lowpart_offset (unsigned int, unsigned int);
+extern poly_uint64 subreg_size_lowpart_offset (poly_uint64, poly_uint64);
 
 /* Return true if a subreg of mode OUTERMODE would only access part of
    an inner register with mode INNERMODE.  The other bits of the inner
@@ -3089,7 +3095,7 @@ paradoxical_subreg_p (const_rtx x)
 
 /* Return the SUBREG_BYTE for an OUTERMODE lowpart of an INNERMODE value.  */
 
-inline unsigned int
+inline poly_uint64
 subreg_lowpart_offset (machine_mode outermode, machine_mode innermode)
 {
   return subreg_size_lowpart_offset (GET_MODE_SIZE (outermode),
@@ -3124,20 +3130,21 @@ wider_subreg_mode (const_rtx x)
   return wider_subreg_mode (GET_MODE (x), GET_MODE (SUBREG_REG (x)));
 }
 
-extern unsigned int subreg_size_highpart_offset (unsigned int, unsigned int);
+extern poly_uint64 subreg_size_highpart_offset (poly_uint64, poly_uint64);
 
 /* Return the SUBREG_BYTE for an OUTERMODE highpart of an INNERMODE value.  */
 
-inline unsigned int
+inline poly_uint64
 subreg_highpart_offset (machine_mode outermode, machine_mode innermode)
 {
   return subreg_size_highpart_offset (GET_MODE_SIZE (outermode),
                                      GET_MODE_SIZE (innermode));
 }
 
-extern int byte_lowpart_offset (machine_mode, machine_mode);
-extern int subreg_memory_offset (machine_mode, machine_mode, unsigned int);
-extern int subreg_memory_offset (const_rtx);
+extern poly_int64 byte_lowpart_offset (machine_mode, machine_mode);
+extern poly_int64 subreg_memory_offset (machine_mode, machine_mode,
+                                       poly_uint64);
+extern poly_int64 subreg_memory_offset (const_rtx);
 extern rtx make_safe_from (rtx, rtx);
 extern rtx convert_memory_address_addr_space_1 (scalar_int_mode, rtx,
                                                addr_space_t, bool, bool);
@@ -3289,16 +3296,8 @@ extern rtx simplify_gen_ternary (enum rtx_code, machine_mode,
                                 machine_mode, rtx, rtx, rtx);
 extern rtx simplify_gen_relational (enum rtx_code, machine_mode,
                                    machine_mode, rtx, rtx);
-extern rtx simplify_subreg (machine_mode, rtx, machine_mode,
-                           unsigned int);
-extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode,
-                               unsigned int);
-inline rtx
-simplify_gen_subreg (machine_mode omode, rtx x, machine_mode imode,
-                    poly_uint64 offset)
-{
-  return simplify_gen_subreg (omode, x, imode, offset.to_constant ());
-}
+extern rtx simplify_subreg (machine_mode, rtx, machine_mode, poly_uint64);
+extern rtx simplify_gen_subreg (machine_mode, rtx, machine_mode, poly_uint64);
 extern rtx lowpart_subreg (machine_mode, rtx, machine_mode);
 extern rtx simplify_replace_fn_rtx (rtx, const_rtx,
                                    rtx (*fn) (rtx, const_rtx, void *), void *);
@@ -3484,7 +3483,7 @@ struct subreg_info
 };
 
 extern void subreg_get_info (unsigned int, machine_mode,
-                            unsigned int, machine_mode,
+                            poly_uint64, machine_mode,
                             struct subreg_info *);
 
 /* lists.c */
@@ -3722,7 +3721,7 @@ extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
 extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
 extern rtx gen_raw_REG (machine_mode, unsigned int);
 extern rtx gen_rtx_REG (machine_mode, unsigned int);
-extern rtx gen_rtx_SUBREG (machine_mode, rtx, int);
+extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
 extern rtx gen_rtx_MEM (machine_mode, rtx);
 extern rtx gen_rtx_VAR_LOCATION (machine_mode, tree, rtx,
                                 enum var_init_status);
@@ -3939,7 +3938,7 @@ extern rtx gen_const_mem (machine_mode, rtx);
 extern rtx gen_frame_mem (machine_mode, rtx);
 extern rtx gen_tmp_stack_mem (machine_mode, rtx);
 extern bool validate_subreg (machine_mode, machine_mode,
-                            const_rtx, unsigned int);
+                            const_rtx, poly_uint64);
 
 /* In combine.c  */
 extern unsigned int extended_count (const_rtx, machine_mode, int);
index 2116907bb1367742491aa9b49a29d109c158ac0e..5a9da9e47c233cdc421317651884bb60b46230c9 100644 (file)
@@ -1586,7 +1586,7 @@ set_noop_p (const_rtx set)
 
   if (GET_CODE (src) == SUBREG && GET_CODE (dst) == SUBREG)
     {
-      if (SUBREG_BYTE (src) != SUBREG_BYTE (dst))
+      if (maybe_ne (SUBREG_BYTE (src), SUBREG_BYTE (dst)))
        return 0;
       src = SUBREG_REG (src);
       dst = SUBREG_REG (dst);
@@ -3557,48 +3557,50 @@ loc_mentioned_in_p (rtx *loc, const_rtx in)
    and SUBREG_BYTE, return the bit offset where the subreg begins
    (counting from the least significant bit of the operand).  */
 
-unsigned int
+poly_uint64
 subreg_lsb_1 (machine_mode outer_mode,
              machine_mode inner_mode,
-             unsigned int subreg_byte)
+             poly_uint64 subreg_byte)
 {
-  unsigned int bitpos;
-  unsigned int byte;
-  unsigned int word;
+  poly_uint64 subreg_end, trailing_bytes, byte_pos;
 
   /* A paradoxical subreg begins at bit position 0.  */
   if (paradoxical_subreg_p (outer_mode, inner_mode))
     return 0;
 
-  if (WORDS_BIG_ENDIAN != BYTES_BIG_ENDIAN)
-    /* If the subreg crosses a word boundary ensure that
-       it also begins and ends on a word boundary.  */
-    gcc_assert (!((subreg_byte % UNITS_PER_WORD
-                 + GET_MODE_SIZE (outer_mode)) > UNITS_PER_WORD
-                 && (subreg_byte % UNITS_PER_WORD
-                     || GET_MODE_SIZE (outer_mode) % UNITS_PER_WORD)));
-
-  if (WORDS_BIG_ENDIAN)
-    word = (GET_MODE_SIZE (inner_mode)
-           - (subreg_byte + GET_MODE_SIZE (outer_mode))) / UNITS_PER_WORD;
-  else
-    word = subreg_byte / UNITS_PER_WORD;
-  bitpos = word * BITS_PER_WORD;
-
-  if (BYTES_BIG_ENDIAN)
-    byte = (GET_MODE_SIZE (inner_mode)
-           - (subreg_byte + GET_MODE_SIZE (outer_mode))) % UNITS_PER_WORD;
+  subreg_end = subreg_byte + GET_MODE_SIZE (outer_mode);
+  trailing_bytes = GET_MODE_SIZE (inner_mode) - subreg_end;
+  if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
+    byte_pos = trailing_bytes;
+  else if (!WORDS_BIG_ENDIAN && !BYTES_BIG_ENDIAN)
+    byte_pos = subreg_byte;
   else
-    byte = subreg_byte % UNITS_PER_WORD;
-  bitpos += byte * BITS_PER_UNIT;
+    {
+      /* When bytes and words have opposite endianness, we must be able
+        to split offsets into words and bytes at compile time.  */
+      poly_uint64 leading_word_part
+       = force_align_down (subreg_byte, UNITS_PER_WORD);
+      poly_uint64 trailing_word_part
+       = force_align_down (trailing_bytes, UNITS_PER_WORD);
+      /* If the subreg crosses a word boundary ensure that
+        it also begins and ends on a word boundary.  */
+      gcc_assert (known_le (subreg_end - leading_word_part,
+                           (unsigned int) UNITS_PER_WORD)
+                 || (known_eq (leading_word_part, subreg_byte)
+                     && known_eq (trailing_word_part, trailing_bytes)));
+      if (WORDS_BIG_ENDIAN)
+       byte_pos = trailing_word_part + (subreg_byte - leading_word_part);
+      else
+       byte_pos = leading_word_part + (trailing_bytes - trailing_word_part);
+    }
 
-  return bitpos;
+  return byte_pos * BITS_PER_UNIT;
 }
 
 /* Given a subreg X, return the bit offset where the subreg begins
    (counting from the least significant bit of the reg).  */
 
-unsigned int
+poly_uint64
 subreg_lsb (const_rtx x)
 {
   return subreg_lsb_1 (GET_MODE (x), GET_MODE (SUBREG_REG (x)),
@@ -3611,29 +3613,32 @@ subreg_lsb (const_rtx x)
    lsb of the inner value.  This is the inverse of the calculation
    performed by subreg_lsb_1 (which converts byte offsets to bit shifts).  */
 
-unsigned int
-subreg_size_offset_from_lsb (unsigned int outer_bytes,
-                            unsigned int inner_bytes,
-                            unsigned int lsb_shift)
+poly_uint64
+subreg_size_offset_from_lsb (poly_uint64 outer_bytes, poly_uint64 inner_bytes,
+                            poly_uint64 lsb_shift)
 {
   /* A paradoxical subreg begins at bit position 0.  */
-  if (outer_bytes > inner_bytes)
+  gcc_checking_assert (ordered_p (outer_bytes, inner_bytes));
+  if (maybe_gt (outer_bytes, inner_bytes))
     {
-      gcc_checking_assert (lsb_shift == 0);
+      gcc_checking_assert (known_eq (lsb_shift, 0U));
       return 0;
     }
 
-  gcc_assert (lsb_shift % BITS_PER_UNIT == 0);
-  unsigned int lower_bytes = lsb_shift / BITS_PER_UNIT;
-  unsigned int upper_bytes = inner_bytes - (lower_bytes + outer_bytes);
+  poly_uint64 lower_bytes = exact_div (lsb_shift, BITS_PER_UNIT);
+  poly_uint64 upper_bytes = inner_bytes - (lower_bytes + outer_bytes);
   if (WORDS_BIG_ENDIAN && BYTES_BIG_ENDIAN)
     return upper_bytes;
   else if (!WORDS_BIG_ENDIAN && !BYTES_BIG_ENDIAN)
     return lower_bytes;
   else
     {
-      unsigned int lower_word_part = lower_bytes & -UNITS_PER_WORD;
-      unsigned int upper_word_part = upper_bytes & -UNITS_PER_WORD;
+      /* When bytes and words have opposite endianness, we must be able
+        to split offsets into words and bytes at compile time.  */
+      poly_uint64 lower_word_part = force_align_down (lower_bytes,
+                                                     UNITS_PER_WORD);
+      poly_uint64 upper_word_part = force_align_down (upper_bytes,
+                                                     UNITS_PER_WORD);
       if (WORDS_BIG_ENDIAN)
        return upper_word_part + (lower_bytes - lower_word_part);
       else
@@ -3662,7 +3667,7 @@ subreg_size_offset_from_lsb (unsigned int outer_bytes,
 
 void
 subreg_get_info (unsigned int xregno, machine_mode xmode,
-                unsigned int offset, machine_mode ymode,
+                poly_uint64 offset, machine_mode ymode,
                 struct subreg_info *info)
 {
   unsigned int nregs_xmode, nregs_ymode;
@@ -3679,6 +3684,9 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
      at least one register.  */
   if (HARD_REGNO_NREGS_HAS_PADDING (xregno, xmode))
     {
+      /* As a consequence, we must be dealing with a constant number of
+        scalars, and thus a constant offset.  */
+      HOST_WIDE_INT coffset = offset.to_constant ();
       nregs_xmode = HARD_REGNO_NREGS_WITH_PADDING (xregno, xmode);
       unsigned int nunits = GET_MODE_NUNITS (xmode);
       scalar_mode xmode_unit = GET_MODE_INNER (xmode);
@@ -3697,9 +3705,9 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
         3 for each part, but in memory it's two 128-bit parts.
         Padding is assumed to be at the end (not necessarily the 'high part')
         of each unit.  */
-      if ((offset / GET_MODE_SIZE (xmode_unit) + 1 < nunits)
-         && (offset / GET_MODE_SIZE (xmode_unit)
-             != ((offset + ysize - 1) / GET_MODE_SIZE (xmode_unit))))
+      if ((coffset / GET_MODE_SIZE (xmode_unit) + 1 < nunits)
+         && (coffset / GET_MODE_SIZE (xmode_unit)
+             != ((coffset + ysize - 1) / GET_MODE_SIZE (xmode_unit))))
        {
          info->representable_p = false;
          rknown = true;
@@ -3711,7 +3719,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
   nregs_ymode = hard_regno_nregs (xregno, ymode);
 
   /* Paradoxical subregs are otherwise valid.  */
-  if (!rknown && offset == 0 && ysize > xsize)
+  if (!rknown && known_eq (offset, 0U) && ysize > xsize)
     {
       info->representable_p = true;
       /* If this is a big endian paradoxical subreg, which uses more
@@ -3746,16 +3754,22 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
        {
          info->representable_p = false;
          info->nregs = CEIL (ysize, regsize_xmode);
-         info->offset = offset / regsize_xmode;
+         if (!can_div_trunc_p (offset, regsize_xmode, &info->offset))
+           /* Checked by validate_subreg.  We must know at compile time
+              which inner registers are being accessed.  */
+           gcc_unreachable ();
          return;
        }
       /* It's not valid to extract a subreg of mode YMODE at OFFSET that
         would go outside of XMODE.  */
-      if (!rknown && ysize + offset > xsize)
+      if (!rknown && maybe_gt (ysize + offset, xsize))
        {
          info->representable_p = false;
          info->nregs = nregs_ymode;
-         info->offset = offset / regsize_xmode;
+         if (!can_div_trunc_p (offset, regsize_xmode, &info->offset))
+           /* Checked by validate_subreg.  We must know at compile time
+              which inner registers are being accessed.  */
+           gcc_unreachable ();
          return;
        }
       /* Quick exit for the simple and common case of extracting whole
@@ -3763,26 +3777,27 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
       /* ??? It would be better to integrate this into the code below,
         if we can generalize the concept enough and figure out how
         odd-sized modes can coexist with the other weird cases we support.  */
+      HOST_WIDE_INT count;
       if (!rknown
          && WORDS_BIG_ENDIAN == REG_WORDS_BIG_ENDIAN
          && regsize_xmode == regsize_ymode
-         && (offset % regsize_ymode) == 0)
+         && constant_multiple_p (offset, regsize_ymode, &count))
        {
          info->representable_p = true;
          info->nregs = nregs_ymode;
-         info->offset = offset / regsize_ymode;
+         info->offset = count;
          gcc_assert (info->offset + info->nregs <= (int) nregs_xmode);
          return;
        }
     }
 
   /* Lowpart subregs are otherwise valid.  */
-  if (!rknown && offset == subreg_lowpart_offset (ymode, xmode))
+  if (!rknown && known_eq (offset, subreg_lowpart_offset (ymode, xmode)))
     {
       info->representable_p = true;
       rknown = true;
 
-      if (offset == 0 || nregs_xmode == nregs_ymode)
+      if (known_eq (offset, 0U) || nregs_xmode == nregs_ymode)
        {
          info->offset = 0;
          info->nregs = nregs_ymode;
@@ -3803,19 +3818,24 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
      These conditions may be relaxed but subreg_regno_offset would
      need to be redesigned.  */
   gcc_assert ((xsize % num_blocks) == 0);
-  unsigned int bytes_per_block = xsize / num_blocks;
+  poly_uint64 bytes_per_block = xsize / num_blocks;
 
   /* Get the number of the first block that contains the subreg and the byte
      offset of the subreg from the start of that block.  */
-  unsigned int block_number = offset / bytes_per_block;
-  unsigned int subblock_offset = offset % bytes_per_block;
+  unsigned int block_number;
+  poly_uint64 subblock_offset;
+  if (!can_div_trunc_p (offset, bytes_per_block, &block_number,
+                       &subblock_offset))
+    /* Checked by validate_subreg.  We must know at compile time which
+       inner registers are being accessed.  */
+    gcc_unreachable ();
 
   if (!rknown)
     {
       /* Only the lowpart of each block is representable.  */
       info->representable_p
-       = (subblock_offset
-          == subreg_size_lowpart_offset (ysize, bytes_per_block));
+       = known_eq (subblock_offset,
+                   subreg_size_lowpart_offset (ysize, bytes_per_block));
       rknown = true;
     }
 
@@ -3842,7 +3862,7 @@ subreg_get_info (unsigned int xregno, machine_mode xmode,
    RETURN - The regno offset which would be used.  */
 unsigned int
 subreg_regno_offset (unsigned int xregno, machine_mode xmode,
-                    unsigned int offset, machine_mode ymode)
+                    poly_uint64 offset, machine_mode ymode)
 {
   struct subreg_info info;
   subreg_get_info (xregno, xmode, offset, ymode, &info);
@@ -3858,7 +3878,7 @@ subreg_regno_offset (unsigned int xregno, machine_mode xmode,
    RETURN - Whether the offset is representable.  */
 bool
 subreg_offset_representable_p (unsigned int xregno, machine_mode xmode,
-                              unsigned int offset, machine_mode ymode)
+                              poly_uint64 offset, machine_mode ymode)
 {
   struct subreg_info info;
   subreg_get_info (xregno, xmode, offset, ymode, &info);
@@ -3875,7 +3895,7 @@ subreg_offset_representable_p (unsigned int xregno, machine_mode xmode,
 
 int
 simplify_subreg_regno (unsigned int xregno, machine_mode xmode,
-                      unsigned int offset, machine_mode ymode)
+                      poly_uint64 offset, machine_mode ymode)
 {
   struct subreg_info info;
   unsigned int yregno;
index 9a3df4c62ee8af19257b16e3ceb5cdb2feb60596..8cb496afafb28355c32b2697eea1a0ef6ad2917a 100644 (file)
@@ -87,6 +87,9 @@ add_rtx (const_rtx x, hash &hstate)
       case 'i':
        hstate.add_int (XINT (x, i));
        break;
+      case 'p':
+       hstate.add_poly_int (SUBREG_BYTE (x));
+       break;
       case 'V':
       case 'E':
        j = XVECLEN (x, i);
index d20815e255b712b7dabf53a39ef90e6e75569d56..7214e764bf5d3d8a5af82d0fe3fdbd26b8f3e2fc 100644 (file)
@@ -70,7 +70,7 @@ gen_lowpart_general (machine_mode mode, rtx x)
          && !reload_completed)
        return gen_lowpart_general (mode, force_reg (xmode, x));
 
-      HOST_WIDE_INT offset = byte_lowpart_offset (mode, GET_MODE (x));
+      poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x));
       return adjust_address (x, mode, offset);
     }
 }
@@ -115,7 +115,7 @@ gen_lowpart_if_possible (machine_mode mode, rtx x)
   else if (MEM_P (x))
     {
       /* This is the only other case we handle.  */
-      HOST_WIDE_INT offset = byte_lowpart_offset (mode, GET_MODE (x));
+      poly_int64 offset = byte_lowpart_offset (mode, GET_MODE (x));
       rtx new_rtx = adjust_address_nv (x, mode, offset);
       if (! memory_address_addr_space_p (mode, XEXP (new_rtx, 0),
                                         MEM_ADDR_SPACE (x)))
index d4b70850c16bbf688185dec4d8bceb1d98955b3a..6feaaf78d6c02cea62c9657b8fb89810bf89399f 100644 (file)
@@ -789,7 +789,7 @@ simplify_truncation (machine_mode mode, rtx op,
       && (INTVAL (XEXP (op, 1)) & (precision - 1)) == 0
       && UINTVAL (XEXP (op, 1)) < op_precision)
     {
-      int byte = subreg_lowpart_offset (mode, op_mode);
+      poly_int64 byte = subreg_lowpart_offset (mode, op_mode);
       int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
       return simplify_gen_subreg (mode, XEXP (op, 0), op_mode,
                                  (WORDS_BIG_ENDIAN
@@ -815,7 +815,7 @@ simplify_truncation (machine_mode mode, rtx op,
       && (GET_MODE_SIZE (int_mode) >= UNITS_PER_WORD
          || WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN))
     {
-      int byte = subreg_lowpart_offset (int_mode, int_op_mode);
+      poly_int64 byte = subreg_lowpart_offset (int_mode, int_op_mode);
       int shifted_bytes = INTVAL (XEXP (op, 1)) / BITS_PER_UNIT;
       return adjust_address_nv (XEXP (op, 0), int_mode,
                                (WORDS_BIG_ENDIAN
@@ -2825,7 +2825,7 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode,
           && GET_CODE (SUBREG_REG (opleft)) == ASHIFT
           && GET_CODE (opright) == LSHIFTRT
           && GET_CODE (XEXP (opright, 0)) == SUBREG
-          && SUBREG_BYTE (opleft) == SUBREG_BYTE (XEXP (opright, 0))
+         && known_eq (SUBREG_BYTE (opleft), SUBREG_BYTE (XEXP (opright, 0)))
          && GET_MODE_SIZE (int_mode) < GET_MODE_SIZE (inner_mode)
           && rtx_equal_p (XEXP (SUBREG_REG (opleft), 0),
                           SUBREG_REG (XEXP (opright, 0)))
@@ -6236,7 +6236,7 @@ simplify_immed_subreg (fixed_size_mode outermode, rtx op,
    Return 0 if no simplifications are possible.  */
 rtx
 simplify_subreg (machine_mode outermode, rtx op,
-                machine_mode innermode, unsigned int byte)
+                machine_mode innermode, poly_uint64 byte)
 {
   /* Little bit of sanity checking.  */
   gcc_assert (innermode != VOIDmode);
@@ -6247,16 +6247,16 @@ simplify_subreg (machine_mode outermode, rtx op,
   gcc_assert (GET_MODE (op) == innermode
              || GET_MODE (op) == VOIDmode);
 
-  if ((byte % GET_MODE_SIZE (outermode)) != 0)
+  if (!multiple_p (byte, GET_MODE_SIZE (outermode)))
     return NULL_RTX;
 
-  if (byte >= GET_MODE_SIZE (innermode))
+  if (maybe_ge (byte, GET_MODE_SIZE (innermode)))
     return NULL_RTX;
 
-  if (outermode == innermode && !byte)
+  if (outermode == innermode && known_eq (byte, 0U))
     return op;
 
-  if (byte % GET_MODE_UNIT_SIZE (innermode) == 0)
+  if (multiple_p (byte, GET_MODE_UNIT_SIZE (innermode)))
     {
       rtx elt;
 
@@ -6277,12 +6277,15 @@ simplify_subreg (machine_mode outermode, rtx op,
     {
       /* simplify_immed_subreg deconstructs OP into bytes and constructs
         the result from bytes, so it only works if the sizes of the modes
-        are known at compile time.  Cases that apply to general modes
-        should be handled here before calling simplify_immed_subreg.  */
+        and the value of the offset are known at compile time.  Cases that
+        that apply to general modes and offsets should be handled here
+        before calling simplify_immed_subreg.  */
       fixed_size_mode fs_outermode, fs_innermode;
+      unsigned HOST_WIDE_INT cbyte;
       if (is_a <fixed_size_mode> (outermode, &fs_outermode)
-         && is_a <fixed_size_mode> (innermode, &fs_innermode))
-       return simplify_immed_subreg (fs_outermode, op, fs_innermode, byte);
+         && is_a <fixed_size_mode> (innermode, &fs_innermode)
+         && byte.is_constant (&cbyte))
+       return simplify_immed_subreg (fs_outermode, op, fs_innermode, cbyte);
 
       return NULL_RTX;
     }
@@ -6295,32 +6298,33 @@ simplify_subreg (machine_mode outermode, rtx op,
       rtx newx;
 
       if (outermode == innermostmode
-         && byte == 0 && SUBREG_BYTE (op) == 0)
+         && known_eq (byte, 0U)
+         && known_eq (SUBREG_BYTE (op), 0))
        return SUBREG_REG (op);
 
       /* Work out the memory offset of the final OUTERMODE value relative
         to the inner value of OP.  */
-      HOST_WIDE_INT mem_offset = subreg_memory_offset (outermode,
-                                                      innermode, byte);
-      HOST_WIDE_INT op_mem_offset = subreg_memory_offset (op);
-      HOST_WIDE_INT final_offset = mem_offset + op_mem_offset;
+      poly_int64 mem_offset = subreg_memory_offset (outermode,
+                                                   innermode, byte);
+      poly_int64 op_mem_offset = subreg_memory_offset (op);
+      poly_int64 final_offset = mem_offset + op_mem_offset;
 
       /* See whether resulting subreg will be paradoxical.  */
       if (!paradoxical_subreg_p (outermode, innermostmode))
        {
          /* In nonparadoxical subregs we can't handle negative offsets.  */
-         if (final_offset < 0)
+         if (maybe_lt (final_offset, 0))
            return NULL_RTX;
          /* Bail out in case resulting subreg would be incorrect.  */
-         if (final_offset % GET_MODE_SIZE (outermode)
-             || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode))
+         if (!multiple_p (final_offset, GET_MODE_SIZE (outermode))
+             || maybe_ge (final_offset, GET_MODE_SIZE (innermostmode)))
            return NULL_RTX;
        }
       else
        {
-         HOST_WIDE_INT required_offset
-           = subreg_memory_offset (outermode, innermostmode, 0);
-         if (final_offset != required_offset)
+         poly_int64 required_offset = subreg_memory_offset (outermode,
+                                                            innermostmode, 0);
+         if (maybe_ne (final_offset, required_offset))
            return NULL_RTX;
          /* Paradoxical subregs always have byte offset 0.  */
          final_offset = 0;
@@ -6373,7 +6377,7 @@ simplify_subreg (machine_mode outermode, rtx op,
             The information is used only by alias analysis that can not
             grog partial register anyway.  */
 
-         if (subreg_lowpart_offset (outermode, innermode) == byte)
+         if (known_eq (subreg_lowpart_offset (outermode, innermode), byte))
            ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op);
          return x;
        }
@@ -6398,25 +6402,28 @@ simplify_subreg (machine_mode outermode, rtx op,
   if (GET_CODE (op) == CONCAT
       || GET_CODE (op) == VEC_CONCAT)
     {
-      unsigned int part_size, final_offset;
+      unsigned int part_size;
+      poly_uint64 final_offset;
       rtx part, res;
 
       machine_mode part_mode = GET_MODE (XEXP (op, 0));
       if (part_mode == VOIDmode)
        part_mode = GET_MODE_INNER (GET_MODE (op));
       part_size = GET_MODE_SIZE (part_mode);
-      if (byte < part_size)
+      if (known_lt (byte, part_size))
        {
          part = XEXP (op, 0);
          final_offset = byte;
        }
-      else
+      else if (known_ge (byte, part_size))
        {
          part = XEXP (op, 1);
          final_offset = byte - part_size;
        }
+      else
+       return NULL_RTX;
 
-      if (final_offset + GET_MODE_SIZE (outermode) > part_size)
+      if (maybe_gt (final_offset + GET_MODE_SIZE (outermode), part_size))
        return NULL_RTX;
 
       part_mode = GET_MODE (part);
@@ -6434,15 +6441,15 @@ simplify_subreg (machine_mode outermode, rtx op,
      it extracts higher bits that the ZERO_EXTEND's source bits.  */
   if (GET_CODE (op) == ZERO_EXTEND && SCALAR_INT_MODE_P (innermode))
     {
-      unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte);
-      if (bitpos >= GET_MODE_PRECISION (GET_MODE (XEXP (op, 0))))
+      poly_uint64 bitpos = subreg_lsb_1 (outermode, innermode, byte);
+      if (known_ge (bitpos, GET_MODE_PRECISION (GET_MODE (XEXP (op, 0)))))
        return CONST0_RTX (outermode);
     }
 
   scalar_int_mode int_outermode, int_innermode;
   if (is_a <scalar_int_mode> (outermode, &int_outermode)
       && is_a <scalar_int_mode> (innermode, &int_innermode)
-      && byte == subreg_lowpart_offset (int_outermode, int_innermode))
+      && known_eq (byte, subreg_lowpart_offset (int_outermode, int_innermode)))
     {
       /* Handle polynomial integers.  The upper bits of a paradoxical
         subreg are undefined, so this is safe regardless of whether
@@ -6472,7 +6479,7 @@ simplify_subreg (machine_mode outermode, rtx op,
 
 rtx
 simplify_gen_subreg (machine_mode outermode, rtx op,
-                    machine_mode innermode, unsigned int byte)
+                    machine_mode innermode, poly_uint64 byte)
 {
   rtx newx;
 
@@ -6668,7 +6675,7 @@ test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg)
                                                duplicate, last_par));
 
   /* Test a scalar subreg of a VEC_DUPLICATE.  */
-  unsigned int offset = subreg_lowpart_offset (inner_mode, mode);
+  poly_uint64 offset = subreg_lowpart_offset (inner_mode, mode);
   ASSERT_RTX_EQ (scalar_reg,
                 simplify_gen_subreg (inner_mode, duplicate,
                                      mode, offset));
@@ -6688,7 +6695,7 @@ test_vector_ops_duplicate (machine_mode mode, rtx scalar_reg)
                                                duplicate, vec_par));
 
       /* Test a vector subreg of a VEC_DUPLICATE.  */
-      unsigned int offset = subreg_lowpart_offset (narrower_mode, mode);
+      poly_uint64 offset = subreg_lowpart_offset (narrower_mode, mode);
       ASSERT_RTX_EQ (narrower_duplicate,
                     simplify_gen_subreg (narrower_mode, duplicate,
                                          mode, offset));
@@ -6801,7 +6808,7 @@ simplify_const_poly_int_tests<N>::run ()
   rtx x10 = gen_int_mode (poly_int64 (-31, -24), HImode);
   rtx two = GEN_INT (2);
   rtx six = GEN_INT (6);
-  HOST_WIDE_INT offset = subreg_lowpart_offset (QImode, HImode);
+  poly_uint64 offset = subreg_lowpart_offset (QImode, HImode);
 
   /* These tests only try limited operation combinations.  Fuller arithmetic
      testing is done directly on poly_ints.  */
index 610c2f6d6c430ef25e0390233b8568755f81097e..4abb62515999deb27abefab927a0fa9c67f5a247 100644 (file)
@@ -555,7 +555,7 @@ debug_lowpart_subreg (machine_mode outer_mode, rtx expr,
 {
   if (inner_mode == VOIDmode)
     inner_mode = GET_MODE (expr);
-  int offset = subreg_lowpart_offset (outer_mode, inner_mode);
+  poly_int64 offset = subreg_lowpart_offset (outer_mode, inner_mode);
   rtx ret = simplify_gen_subreg (outer_mode, expr, inner_mode, offset);
   if (ret)
     return ret;
index 1a4caaa09b4678877028393ee5c6e694e954ea43..33e5a2410268590c7787d287aaf438606d743ed4 100644 (file)
@@ -3522,6 +3522,12 @@ loc_cmp (rtx x, rtx y)
        else
          return 1;
 
+      case 'p':
+       r = compare_sizes_for_sort (SUBREG_BYTE (x), SUBREG_BYTE (y));
+       if (r != 0)
+         return r;
+       break;
+
       case 'V':
       case 'E':
        /* Compare the vector length first.  */
@@ -5369,7 +5375,7 @@ track_loc_p (rtx loc, tree expr, poly_int64 offset, bool store_reg_p,
 static rtx
 var_lowpart (machine_mode mode, rtx loc)
 {
-  unsigned int offset, reg_offset, regno;
+  unsigned int regno;
 
   if (GET_MODE (loc) == mode)
     return loc;
@@ -5377,12 +5383,12 @@ var_lowpart (machine_mode mode, rtx loc)
   if (!REG_P (loc) && !MEM_P (loc))
     return NULL;
 
-  offset = byte_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 offset = byte_lowpart_offset (mode, GET_MODE (loc));
 
   if (MEM_P (loc))
     return adjust_address_nv (loc, mode, offset);
 
-  reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
+  poly_uint64 reg_offset = subreg_lowpart_offset (mode, GET_MODE (loc));
   regno = REGNO (loc) + subreg_regno_offset (REGNO (loc), GET_MODE (loc),
                                             reg_offset, mode);
   return gen_rtx_REG_offset (loc, mode, regno, offset);