poly_int: REG_ARGS_SIZE
authorRichard Sandiford <richard.sandiford@linaro.org>
Thu, 21 Dec 2017 07:00:46 +0000 (07:00 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Thu, 21 Dec 2017 07:00:46 +0000 (07:00 +0000)
This patch adds new utility functions for manipulating REG_ARGS_SIZE
notes and allows the notes to carry polynomial as well as constant sizes.

The code was inconsistent about whether INT_MIN or HOST_WIDE_INT_MIN
should be used to represent an unknown size.  The patch uses
HOST_WIDE_INT_MIN throughout.

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

gcc/
* rtl.h (get_args_size, add_args_size_note): New functions.
(find_args_size_adjust): Return a poly_int64 rather than a
HOST_WIDE_INT.
(fixup_args_size_notes): Likewise.  Make the same change to the
end_args_size parameter.
* rtlanal.c (get_args_size, add_args_size_note): New functions.
* builtins.c (expand_builtin_trap): Use add_args_size_note.
* calls.c (emit_call_1): Likewise.
* explow.c (adjust_stack_1): Likewise.
* cfgcleanup.c (old_insns_match_p): Update use of
find_args_size_adjust.
* combine.c (distribute_notes): Track polynomial arg sizes.
* dwarf2cfi.c (dw_trace_info): Change beg_true_args_size,
end_true_args_size, beg_delay_args_size and end_delay_args_size
from HOST_WIDE_INT to poly_int64.
(add_cfi_args_size): Take the args_size as a poly_int64 rather
than a HOST_WIDE_INT.
(notice_args_size, notice_eh_throw, maybe_record_trace_start)
(maybe_record_trace_start_abnormal, scan_trace, connect_traces): Track
polynomial arg sizes.
* emit-rtl.c (try_split): Use get_args_size.
* recog.c (peep2_attempt): Likewise.
* reload1.c (reload_as_needed): Likewise.
* expr.c (find_args_size_adjust): Return the adjustment as a
poly_int64 rather than a HOST_WIDE_INT.
(fixup_args_size_notes): Change end_args_size from a HOST_WIDE_INT
to a poly_int64 and change the return type in the same way.
(emit_single_push_insn): Track polynomial arg sizes.

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

13 files changed:
gcc/ChangeLog
gcc/builtins.c
gcc/calls.c
gcc/cfgcleanup.c
gcc/combine.c
gcc/dwarf2cfi.c
gcc/emit-rtl.c
gcc/explow.c
gcc/expr.c
gcc/recog.c
gcc/reload1.c
gcc/rtl.h
gcc/rtlanal.c

index 64577be7f0bba86d1054aff9d79b695e924d1d76..40d62bf9ed679942d74ca583c35bf1cf46a3cbcb 100644 (file)
@@ -1,3 +1,36 @@
+2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * rtl.h (get_args_size, add_args_size_note): New functions.
+       (find_args_size_adjust): Return a poly_int64 rather than a
+       HOST_WIDE_INT.
+       (fixup_args_size_notes): Likewise.  Make the same change to the
+       end_args_size parameter.
+       * rtlanal.c (get_args_size, add_args_size_note): New functions.
+       * builtins.c (expand_builtin_trap): Use add_args_size_note.
+       * calls.c (emit_call_1): Likewise.
+       * explow.c (adjust_stack_1): Likewise.
+       * cfgcleanup.c (old_insns_match_p): Update use of
+       find_args_size_adjust.
+       * combine.c (distribute_notes): Track polynomial arg sizes.
+       * dwarf2cfi.c (dw_trace_info): Change beg_true_args_size,
+       end_true_args_size, beg_delay_args_size and end_delay_args_size
+       from HOST_WIDE_INT to poly_int64.
+       (add_cfi_args_size): Take the args_size as a poly_int64 rather
+       than a HOST_WIDE_INT.
+       (notice_args_size, notice_eh_throw, maybe_record_trace_start)
+       (maybe_record_trace_start_abnormal, scan_trace, connect_traces): Track
+       polynomial arg sizes.
+       * emit-rtl.c (try_split): Use get_args_size.
+       * recog.c (peep2_attempt): Likewise.
+       * reload1.c (reload_as_needed): Likewise.
+       * expr.c (find_args_size_adjust): Return the adjustment as a
+       poly_int64 rather than a HOST_WIDE_INT.
+       (fixup_args_size_notes): Change end_args_size from a HOST_WIDE_INT
+       to a poly_int64 and change the return type in the same way.
+       (emit_single_push_insn): Track polynomial arg sizes.
+
 2017-12-21  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index f8b853c6ecd03466a771b06831ada7feaf6e2f54..0ff0efea908ec2f9833e5ad8affce1cd40be3b3e 100644 (file)
@@ -5179,7 +5179,7 @@ expand_builtin_trap (void)
         REG_ARGS_SIZE note to prevent crossjumping of calls with
         different args sizes.  */
       if (!ACCUMULATE_OUTGOING_ARGS)
-       add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+       add_args_size_note (insn, stack_pointer_delta);
     }
   else
     {
index 5feab3ac1d0b578b17220bf44fec5f45e6b2e6e2..1387d152e9eb984942774b6b18c68d87675ff386 100644 (file)
@@ -498,7 +498,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
       rounded_stack_size_rtx = GEN_INT (rounded_stack_size);
       stack_pointer_delta -= n_popped;
 
-      add_reg_note (call_insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+      add_args_size_note (call_insn, stack_pointer_delta);
 
       /* If popup is needed, stack realign must use DRAP  */
       if (SUPPORTS_STACK_ALIGNMENT)
@@ -508,7 +508,7 @@ emit_call_1 (rtx funexp, tree fntree ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNU
      REG_ARGS_SIZE note to prevent crossjumping of calls with different
      args sizes.  */
   else if (!ACCUMULATE_OUTGOING_ARGS && (ecf_flags & ECF_NORETURN) != 0)
-    add_reg_note (call_insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+    add_args_size_note (call_insn, stack_pointer_delta);
 
   if (!ACCUMULATE_OUTGOING_ARGS)
     {
index f470f18c074dfa85abf2a92669e14f58ca20ed43..6634016f4d859c4d29370c97074ac7d90057524a 100644 (file)
@@ -1173,7 +1173,7 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx_insn *i1, rtx_insn *i2)
       /* ??? Worse, this adjustment had better be constant lest we
          have differing incoming stack levels.  */
       if (!frame_pointer_needed
-          && find_args_size_adjust (i1) == HOST_WIDE_INT_MIN)
+         && known_eq (find_args_size_adjust (i1), HOST_WIDE_INT_MIN))
        return dir_none;
     }
   else if (p1 || p2)
index 9f19ee43c74109b0a95a4d4848de6cb09eaf0a81..e78a71380374f7fdb93466c0fff17aad306f7a59 100644 (file)
@@ -14145,7 +14145,7 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
             entire adjustment.  Assert i3 contains at least some adjust.  */
          if (!noop_move_p (i3))
            {
-             int old_size, args_size = INTVAL (XEXP (note, 0));
+             poly_int64 old_size, args_size = get_args_size (note);
              /* fixup_args_size_notes looks at REG_NORETURN note,
                 so ensure the note is placed there first.  */
              if (CALL_P (i3))
@@ -14164,7 +14164,7 @@ distribute_notes (rtx notes, rtx_insn *from_insn, rtx_insn *i3, rtx_insn *i2,
              old_size = fixup_args_size_notes (PREV_INSN (i3), i3, args_size);
              /* emit_call_1 adds for !ACCUMULATE_OUTGOING_ARGS
                 REG_ARGS_SIZE note to all noreturn calls, allow that here.  */
-             gcc_assert (old_size != args_size
+             gcc_assert (maybe_ne (old_size, args_size)
                          || (CALL_P (i3)
                              && !ACCUMULATE_OUTGOING_ARGS
                              && find_reg_note (i3, REG_NORETURN, NULL_RTX)));
index 8d08d86df12314e6e39f21d7b2016141e39739a3..7a7063984b4655ea81e675bd391eb97af92c7cc7 100644 (file)
@@ -102,8 +102,8 @@ struct dw_trace_info
      while scanning insns.  However, the args_size value is irrelevant at
      any point except can_throw_internal_p insns.  Therefore the "delay"
      sizes the values that must actually be emitted for this trace.  */
-  HOST_WIDE_INT beg_true_args_size, end_true_args_size;
-  HOST_WIDE_INT beg_delay_args_size, end_delay_args_size;
+  poly_int64_pod beg_true_args_size, end_true_args_size;
+  poly_int64_pod beg_delay_args_size, end_delay_args_size;
 
   /* The first EH insn in the trace, where beg_delay_args_size must be set.  */
   rtx_insn *eh_head;
@@ -475,16 +475,19 @@ add_cfi (dw_cfi_ref cfi)
 }
 
 static void
-add_cfi_args_size (HOST_WIDE_INT size)
+add_cfi_args_size (poly_int64 size)
 {
+  /* We don't yet have a representation for polynomial sizes.  */
+  HOST_WIDE_INT const_size = size.to_constant ();
+
   dw_cfi_ref cfi = new_cfi ();
 
   /* While we can occasionally have args_size < 0 internally, this state
      should not persist at a point we actually need an opcode.  */
-  gcc_assert (size >= 0);
+  gcc_assert (const_size >= 0);
 
   cfi->dw_cfi_opc = DW_CFA_GNU_args_size;
-  cfi->dw_cfi_oprnd1.dw_cfi_offset = size;
+  cfi->dw_cfi_oprnd1.dw_cfi_offset = const_size;
 
   add_cfi (cfi);
 }
@@ -927,16 +930,16 @@ reg_save (unsigned int reg, unsigned int sreg, poly_int64 offset)
 static void
 notice_args_size (rtx_insn *insn)
 {
-  HOST_WIDE_INT args_size, delta;
+  poly_int64 args_size, delta;
   rtx note;
 
   note = find_reg_note (insn, REG_ARGS_SIZE, NULL);
   if (note == NULL)
     return;
 
-  args_size = INTVAL (XEXP (note, 0));
+  args_size = get_args_size (note);
   delta = args_size - cur_trace->end_true_args_size;
-  if (delta == 0)
+  if (known_eq (delta, 0))
     return;
 
   cur_trace->end_true_args_size = args_size;
@@ -962,16 +965,14 @@ notice_args_size (rtx_insn *insn)
 static void
 notice_eh_throw (rtx_insn *insn)
 {
-  HOST_WIDE_INT args_size;
-
-  args_size = cur_trace->end_true_args_size;
+  poly_int64 args_size = cur_trace->end_true_args_size;
   if (cur_trace->eh_head == NULL)
     {
       cur_trace->eh_head = insn;
       cur_trace->beg_delay_args_size = args_size;
       cur_trace->end_delay_args_size = args_size;
     }
-  else if (cur_trace->end_delay_args_size != args_size)
+  else if (maybe_ne (cur_trace->end_delay_args_size, args_size))
     {
       cur_trace->end_delay_args_size = args_size;
 
@@ -2292,7 +2293,6 @@ static void
 maybe_record_trace_start (rtx_insn *start, rtx_insn *origin)
 {
   dw_trace_info *ti;
-  HOST_WIDE_INT args_size;
 
   ti = get_trace_info (start);
   gcc_assert (ti != NULL);
@@ -2305,7 +2305,7 @@ maybe_record_trace_start (rtx_insn *start, rtx_insn *origin)
               (origin ? INSN_UID (origin) : 0));
     }
 
-  args_size = cur_trace->end_true_args_size;
+  poly_int64 args_size = cur_trace->end_true_args_size;
   if (ti->beg_row == NULL)
     {
       /* This is the first time we've encountered this trace.  Propagate
@@ -2345,7 +2345,7 @@ maybe_record_trace_start (rtx_insn *start, rtx_insn *origin)
 #endif
 
       /* The args_size is allowed to conflict if it isn't actually used.  */
-      if (ti->beg_true_args_size != args_size)
+      if (maybe_ne (ti->beg_true_args_size, args_size))
        ti->args_size_undefined = true;
     }
 }
@@ -2356,11 +2356,11 @@ maybe_record_trace_start (rtx_insn *start, rtx_insn *origin)
 static void
 maybe_record_trace_start_abnormal (rtx_insn *start, rtx_insn *origin)
 {
-  HOST_WIDE_INT save_args_size, delta;
+  poly_int64 save_args_size, delta;
   dw_cfa_location save_cfa;
 
   save_args_size = cur_trace->end_true_args_size;
-  if (save_args_size == 0)
+  if (known_eq (save_args_size, 0))
     {
       maybe_record_trace_start (start, origin);
       return;
@@ -2552,7 +2552,6 @@ scan_trace (dw_trace_info *trace)
 
              if (INSN_FROM_TARGET_P (elt))
                {
-                 HOST_WIDE_INT restore_args_size;
                  cfi_vec save_row_reg_save;
 
                  /* If ELT is an instruction from target of an annulled
@@ -2560,7 +2559,7 @@ scan_trace (dw_trace_info *trace)
                     the args_size and CFA along the current path
                     shouldn't change.  */
                  add_cfi_insn = NULL;
-                 restore_args_size = cur_trace->end_true_args_size;
+                 poly_int64 restore_args_size = cur_trace->end_true_args_size;
                  cur_cfa = &cur_row->cfa;
                  save_row_reg_save = vec_safe_copy (cur_row->reg_save);
 
@@ -2802,7 +2801,7 @@ connect_traces (void)
   /* Connect args_size between traces that have can_throw_internal insns.  */
   if (cfun->eh->lp_array)
     {
-      HOST_WIDE_INT prev_args_size = 0;
+      poly_int64 prev_args_size = 0;
 
       for (i = 0; i < n; ++i)
        {
@@ -2814,7 +2813,7 @@ connect_traces (void)
            continue;
          gcc_assert (!ti->args_size_undefined);
 
-         if (ti->beg_delay_args_size != prev_args_size)
+         if (maybe_ne (ti->beg_delay_args_size, prev_args_size))
            {
              /* ??? Search back to previous CFI note.  */
              add_cfi_insn = PREV_INSN (ti->eh_head);
index 6f4dea325ca357a43657aae14d1fc004f2531524..8ca192f5daf2702b14797b10fad249450f41bc44 100644 (file)
@@ -3924,7 +3924,7 @@ try_split (rtx pat, rtx_insn *trial, int last)
          break;
 
        case REG_ARGS_SIZE:
-         fixup_args_size_notes (NULL, insn_last, INTVAL (XEXP (note, 0)));
+         fixup_args_size_notes (NULL, insn_last, get_args_size (note));
          break;
 
        case REG_CALL_DECL:
index 4f3e0d41d1b379b1061014fdb19665ecbfe8c8dc..38a950751330a46f703ef7909846ce9c3adb56cb 100644 (file)
@@ -941,7 +941,7 @@ adjust_stack_1 (rtx adjust, bool anti_p)
     }
 
   if (!suppress_reg_args_size)
-    add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+    add_args_size_note (insn, stack_pointer_delta);
 }
 
 /* Adjust the stack pointer by ADJUST (an rtx for a number of bytes).
index 64baaafed265db76e574d576db46c0de62aaed1a..06b6f7760a88d5687b6fcfb73691b1d7e28ea8ed 100644 (file)
@@ -3941,9 +3941,9 @@ mem_autoinc_base (rtx mem)
 
    The return value is the amount of adjustment that can be trivially
    verified, via immediate operand or auto-inc.  If the adjustment
-   cannot be trivially extracted, the return value is INT_MIN.  */
+   cannot be trivially extracted, the return value is HOST_WIDE_INT_MIN.  */
 
-HOST_WIDE_INT
+poly_int64
 find_args_size_adjust (rtx_insn *insn)
 {
   rtx dest, set, pat;
@@ -4066,22 +4066,21 @@ find_args_size_adjust (rtx_insn *insn)
     }
 }
 
-int
-fixup_args_size_notes (rtx_insn *prev, rtx_insn *last, int end_args_size)
+poly_int64
+fixup_args_size_notes (rtx_insn *prev, rtx_insn *last,
+                      poly_int64 end_args_size)
 {
-  int args_size = end_args_size;
+  poly_int64 args_size = end_args_size;
   bool saw_unknown = false;
   rtx_insn *insn;
 
   for (insn = last; insn != prev; insn = PREV_INSN (insn))
     {
-      HOST_WIDE_INT this_delta;
-
       if (!NONDEBUG_INSN_P (insn))
        continue;
 
-      this_delta = find_args_size_adjust (insn);
-      if (this_delta == 0)
+      poly_int64 this_delta = find_args_size_adjust (insn);
+      if (known_eq (this_delta, 0))
        {
          if (!CALL_P (insn)
              || ACCUMULATE_OUTGOING_ARGS
@@ -4090,15 +4089,15 @@ fixup_args_size_notes (rtx_insn *prev, rtx_insn *last, int end_args_size)
        }
 
       gcc_assert (!saw_unknown);
-      if (this_delta == HOST_WIDE_INT_MIN)
+      if (known_eq (this_delta, HOST_WIDE_INT_MIN))
        saw_unknown = true;
 
-      add_reg_note (insn, REG_ARGS_SIZE, GEN_INT (args_size));
+      add_args_size_note (insn, args_size);
       if (STACK_GROWS_DOWNWARD)
-       this_delta = -(unsigned HOST_WIDE_INT) this_delta;
+       this_delta = -poly_uint64 (this_delta);
 
       if (saw_unknown)
-       args_size = INT_MIN;
+       args_size = HOST_WIDE_INT_MIN;
       else
        args_size -= this_delta;
     }
@@ -4198,7 +4197,7 @@ emit_single_push_insn_1 (machine_mode mode, rtx x, tree type)
 static void
 emit_single_push_insn (machine_mode mode, rtx x, tree type)
 {
-  int delta, old_delta = stack_pointer_delta;
+  poly_int64 delta, old_delta = stack_pointer_delta;
   rtx_insn *prev = get_last_insn ();
   rtx_insn *last;
 
@@ -4209,12 +4208,13 @@ emit_single_push_insn (machine_mode mode, rtx x, tree type)
   /* Notice the common case where we emitted exactly one insn.  */
   if (PREV_INSN (last) == prev)
     {
-      add_reg_note (last, REG_ARGS_SIZE, GEN_INT (stack_pointer_delta));
+      add_args_size_note (last, stack_pointer_delta);
       return;
     }
 
   delta = fixup_args_size_notes (prev, last, stack_pointer_delta);
-  gcc_assert (delta == INT_MIN || delta == old_delta);
+  gcc_assert (known_eq (delta, HOST_WIDE_INT_MIN)
+             || known_eq (delta, old_delta));
 }
 #endif
 
index 8e1218b519d80fceefcf558d88d77e7d44fbef7c..99031df553d18fbeb2b21dc4fe8cea13c65d96fc 100644 (file)
@@ -3466,7 +3466,7 @@ peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
 
   /* Re-insert the ARGS_SIZE notes.  */
   if (as_note)
-    fixup_args_size_notes (before_try, last, INTVAL (XEXP (as_note, 0)));
+    fixup_args_size_notes (before_try, last, get_args_size (as_note));
 
   /* If we generated a jump instruction, it won't have
      JUMP_LABEL set.  Recompute after we're done.  */
index 7cf64124bfad08c449819b0cb9dcbde97ac64e94..2483ed9af8b500859da0af9a9892214dee8b351e 100644 (file)
@@ -4649,7 +4649,7 @@ reload_as_needed (int live_known)
                {
                  remove_note (insn, p);
                  fixup_args_size_notes (prev, PREV_INSN (next),
-                                        INTVAL (XEXP (p, 0)));
+                                        get_args_size (p));
                }
 
              /* If this was an ASM, make sure that all the reload insns
index 17fd9209e9a9c15dacc1429a98d72469892a7724..99892634a9a85860f27eb71b841bf774bf5d0183 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3355,6 +3355,7 @@ extern rtx get_related_value (const_rtx);
 extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT);
 extern void split_const (rtx, rtx *, rtx *);
 extern rtx strip_offset (rtx, poly_int64_pod *);
+extern poly_int64 get_args_size (const_rtx);
 extern bool unsigned_reg_p (rtx);
 extern int reg_mentioned_p (const_rtx, const_rtx);
 extern int count_occurrences (const_rtx, const_rtx, int);
@@ -3390,6 +3391,7 @@ extern int find_regno_fusage (const_rtx, enum rtx_code, unsigned int);
 extern rtx alloc_reg_note (enum reg_note, rtx, rtx);
 extern void add_reg_note (rtx, enum reg_note, rtx);
 extern void add_int_reg_note (rtx_insn *, enum reg_note, int);
+extern void add_args_size_note (rtx_insn *, poly_int64);
 extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
 extern rtx duplicate_reg_note (rtx);
 extern void remove_note (rtx_insn *, const_rtx);
@@ -3979,8 +3981,8 @@ extern void emit_jump (rtx);
 /* In expr.c */
 extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
                           unsigned int, int);
-extern HOST_WIDE_INT find_args_size_adjust (rtx_insn *);
-extern int fixup_args_size_notes (rtx_insn *, rtx_insn *, int);
+extern poly_int64 find_args_size_adjust (rtx_insn *);
+extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64);
 
 /* In expmed.c */
 extern void init_expmed (void);
index 859754df72454695a6654394ca70ee72034266b8..6d50781a32c312e2e773ef0bb0d15b3ad8bcdaf9 100644 (file)
@@ -937,6 +937,15 @@ strip_offset (rtx x, poly_int64_pod *offset_out)
   *offset_out = 0;
   return x;
 }
+
+/* Return the argument size in REG_ARGS_SIZE note X.  */
+
+poly_int64
+get_args_size (const_rtx x)
+{
+  gcc_checking_assert (REG_NOTE_KIND (x) == REG_ARGS_SIZE);
+  return rtx_to_poly_int64 (XEXP (x, 0));
+}
 \f
 /* Return the number of places FIND appears within X.  If COUNT_DEST is
    zero, we do not count occurrences inside the destination of a SET.  */
@@ -2362,6 +2371,15 @@ add_int_reg_note (rtx_insn *insn, enum reg_note kind, int datum)
                                       datum, REG_NOTES (insn));
 }
 
+/* Add a REG_ARGS_SIZE note to INSN with value VALUE.  */
+
+void
+add_args_size_note (rtx_insn *insn, poly_int64 value)
+{
+  gcc_checking_assert (!find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX));
+  add_reg_note (insn, REG_ARGS_SIZE, gen_int_mode (value, Pmode));
+}
+
 /* Add a register note like NOTE to INSN.  */
 
 void