diff mbox series

[045/nnn] poly_int: REG_ARGS_SIZE

Message ID 87h8upn5nm.fsf@linaro.org
State New
Headers show
Series [045/nnn] poly_int: REG_ARGS_SIZE | expand

Commit Message

Richard Sandiford Oct. 23, 2017, 5:19 p.m. UTC
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-10-23  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.

Comments

Jeff Law Dec. 6, 2017, 12:10 a.m. UTC | #1
On 10/23/2017 11:19 AM, Richard Sandiford wrote:
> 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-10-23  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.

> 

OK.
jeff
Andreas Schwab Dec. 22, 2017, 9:56 p.m. UTC | #2
This breaks gcc.dg/tls/opt-3.c, gcc.dg/tls/pr47715-3.c and
gcc.dg/tls/struct-1.c on m68k:

/daten/aranym/gcc/gcc-20171222/gcc/testsuite/gcc.dg/tls/opt-3.c:11:3: internal compiler error: in add_args_size_note, at rtlanal.c:2379
0xae7aa9 add_args_size_note(rtx_insn*, poly_int<1u, long>)
        ../../gcc/rtlanal.c:2379
0x7ea4ca fixup_args_size_notes(rtx_insn*, rtx_insn*, poly_int<1u, long>)
        ../../gcc/expr.c:4105
0x7f6a02 emit_single_push_insn
        ../../gcc/expr.c:4225
0x7fa412 emit_push_insn(rtx_def*, machine_mode, tree_node*, rtx_def*, unsigned int, int, rtx_def*, poly_int<1u, long>, rtx_def*, rtx_def*, int, rtx_def*, bool)
        ../../gcc/expr.c:4561
0x6b8976 store_one_arg
        ../../gcc/calls.c:5694
0x6c15b1 expand_call(tree_node*, rtx_def*, int)
        ../../gcc/calls.c:4030
0x7f0485 expand_expr_real_1(tree_node*, rtx_def*, machine_mode, expand_modifier, rtx_def**, bool)
        ../../gcc/expr.c:10927
0x6d6c97 expand_expr
        ../../gcc/expr.h:276
0x6d6c97 expand_call_stmt
        ../../gcc/cfgexpand.c:2690
0x6d6c97 expand_gimple_stmt_1
        ../../gcc/cfgexpand.c:3624
0x6d6c97 expand_gimple_stmt
        ../../gcc/cfgexpand.c:3790
0x6d8058 expand_gimple_tailcall
        ../../gcc/cfgexpand.c:3836
0x6d8058 expand_gimple_basic_block
        ../../gcc/cfgexpand.c:5774
0x6dd62e execute
        ../../gcc/cfgexpand.c:6403


Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
Richard Sandiford Dec. 23, 2017, 9:36 a.m. UTC | #3
Andreas Schwab <schwab@linux-m68k.org> writes:
> This breaks gcc.dg/tls/opt-3.c, gcc.dg/tls/pr47715-3.c and

> gcc.dg/tls/struct-1.c on m68k:

>

> /daten/aranym/gcc/gcc-20171222/gcc/testsuite/gcc.dg/tls/opt-3.c:11:3:

> internal compiler error: in add_args_size_note, at rtlanal.c:2379

> 0xae7aa9 add_args_size_note(rtx_insn*, poly_int<1u, long>)

>         ../../gcc/rtlanal.c:2379

> 0x7ea4ca fixup_args_size_notes(rtx_insn*, rtx_insn*, poly_int<1u, long>)

>         ../../gcc/expr.c:4105

> 0x7f6a02 emit_single_push_insn

>         ../../gcc/expr.c:4225

> 0x7fa412 emit_push_insn(rtx_def*, machine_mode, tree_node*, rtx_def*,

> unsigned int, int, rtx_def*, poly_int<1u, long>, rtx_def*, rtx_def*,

> int, rtx_def*, bool)

>         ../../gcc/expr.c:4561

> 0x6b8976 store_one_arg

>         ../../gcc/calls.c:5694

> 0x6c15b1 expand_call(tree_node*, rtx_def*, int)

>         ../../gcc/calls.c:4030

> 0x7f0485 expand_expr_real_1(tree_node*, rtx_def*, machine_mode,

> expand_modifier, rtx_def**, bool)

>         ../../gcc/expr.c:10927

> 0x6d6c97 expand_expr

>         ../../gcc/expr.h:276

> 0x6d6c97 expand_call_stmt

>         ../../gcc/cfgexpand.c:2690

> 0x6d6c97 expand_gimple_stmt_1

>         ../../gcc/cfgexpand.c:3624

> 0x6d6c97 expand_gimple_stmt

>         ../../gcc/cfgexpand.c:3790

> 0x6d8058 expand_gimple_tailcall

>         ../../gcc/cfgexpand.c:3836

> 0x6d8058 expand_gimple_basic_block

>         ../../gcc/cfgexpand.c:5774

> 0x6dd62e execute

>         ../../gcc/cfgexpand.c:6403


Bah.  Looks like I need to update my scripts to use --enable-tls,
since I'd ended up with emultls for the m68k targets.

I think the assert is catching a pre-existing bug here.  If we pushed
a value that needs a call to something like __tls_get_addr, we ended
up with two different REG_ARGS_SIZE notes on the same instruction.

It seems to be OK for emit_single_push_insn to push something that
needs a call to __tls_get_addr:

      /* We have to allow non-call_pop patterns for the case
	 of emit_single_push_insn of a TLS address.  */
      if (GET_CODE (pat) != PARALLEL)
	return 0;

so I think the problem is in the way this is handled rather than the fact
that it occurs at all.

If we're pushing a value X that needs a call C to calculate, we'll
add REG_ARGS_SIZE notes to the pushes and pops for C as part of the
call sequence.  Then emit_single_push_insn calls fixup_args_size_notes
on the whole push sequence (the calculation of X, including C,
and the push of X itself).  This is where the double notes came from.
But emit_single_push_insn_1 adjusted stack_pointer_delta *before* the
push, so the notes added for C were relative to the situation after
the future push of X rather than before it.

Presumably this didn't matter in practice because the note added
second tended to trump the note added first.  But code is allowed to
walk REG_NOTES without having to disregard secondary notes.

This patch seems to fix it for me, but I'm not sure how best to test it.

Thanks,
Richard


2017-12-23  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
	* expr.c (fixup_args_size_notes): Check that any existing
	REG_ARGS_SIZE notes are correct, and don't try to re-add them.
	(emit_single_push_insn_1): Move stack_pointer_delta adjustment to...
	(emit_single_push_insn): ...here.

Index: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-12-23 09:29:20.226338285 +0000
+++ gcc/expr.c	2017-12-23 09:29:45.783339673 +0000
@@ -4089,6 +4089,14 @@ fixup_args_size_notes (rtx_insn *prev, r
       if (!NONDEBUG_INSN_P (insn))
 	continue;
 
+      /* We might have existing REG_ARGS_SIZE notes, e.g. when pushing
+	 a call argument containing a TLS address that itself requires
+	 a call to __tls_get_addr.  The handling of stack_pointer_delta
+	 in emit_single_push_insn is supposed to ensure that any such
+	 notes are already correct.  */
+      rtx note = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
+      gcc_assert (!note || known_eq (args_size, get_args_size (note)));
+
       poly_int64 this_delta = find_args_size_adjust (insn);
       if (known_eq (this_delta, 0))
 	{
@@ -4102,7 +4110,8 @@ fixup_args_size_notes (rtx_insn *prev, r
       if (known_eq (this_delta, HOST_WIDE_INT_MIN))
 	saw_unknown = true;
 
-      add_args_size_note (insn, args_size);
+      if (!note)
+	add_args_size_note (insn, args_size);
       if (STACK_GROWS_DOWNWARD)
 	this_delta = -poly_uint64 (this_delta);
 
@@ -4126,7 +4135,6 @@ emit_single_push_insn_1 (machine_mode mo
   rtx dest;
   enum insn_code icode;
 
-  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
   /* If there is push pattern, use it.  Otherwise try old way of throwing
      MEM representing push operation to move expander.  */
   icode = optab_handler (push_optab, mode);
@@ -4213,6 +4221,14 @@ emit_single_push_insn (machine_mode mode
 
   emit_single_push_insn_1 (mode, x, type);
 
+  /* Adjust stack_pointer_delta to describe the situation after the push
+     we just performed.  Note that we must do this after the push rather
+     than before the push in case calculating X needs pushes and pops of
+     its own (e.g. if calling __tls_get_addr).  The REG_ARGS_SIZE notes
+     for such pushes and pops must not include the effect of the future
+     push of X.  */
+  stack_pointer_delta += PUSH_ROUNDING (GET_MODE_SIZE (mode));
+
   last = get_last_insn ();
 
   /* Notice the common case where we emitted exactly one insn.  */
Andreas Schwab Dec. 24, 2017, 12:49 p.m. UTC | #4
On Dez 23 2017, Richard Sandiford <richard.sandiford@linaro.org> wrote:

> gcc/

> 	* expr.c (fixup_args_size_notes): Check that any existing

> 	REG_ARGS_SIZE notes are correct, and don't try to re-add them.

> 	(emit_single_push_insn_1): Move stack_pointer_delta adjustment to...

> 	(emit_single_push_insn): ...here.


Successfully regtested on m68k-linux.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
diff mbox series

Patch

Index: gcc/rtl.h
===================================================================
--- gcc/rtl.h	2017-10-23 17:16:55.754801166 +0100
+++ gcc/rtl.h	2017-10-23 17:18:57.862160702 +0100
@@ -3329,6 +3329,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);
@@ -3364,6 +3365,7 @@  extern int find_regno_fusage (const_rtx,
 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);
@@ -3954,8 +3956,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: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	2017-10-23 17:18:53.836514583 +0100
+++ gcc/rtlanal.c	2017-10-23 17:18:57.862160702 +0100
@@ -937,6 +937,15 @@  strip_offset (rtx x, poly_int64_pod *off
   *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));
+}
 
 /* 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 r
 				       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
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c	2017-10-23 17:18:42.394520412 +0100
+++ gcc/builtins.c	2017-10-23 17:18:57.855161317 +0100
@@ -5027,7 +5027,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: gcc/calls.c
===================================================================
--- gcc/calls.c	2017-10-23 17:16:50.357530032 +0100
+++ gcc/calls.c	2017-10-23 17:18:57.856161229 +0100
@@ -497,7 +497,7 @@  emit_call_1 (rtx funexp, tree fntree ATT
       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)
@@ -507,7 +507,7 @@  emit_call_1 (rtx funexp, tree fntree ATT
      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: gcc/explow.c
===================================================================
--- gcc/explow.c	2017-10-23 17:18:53.832514935 +0100
+++ gcc/explow.c	2017-10-23 17:18:57.859160965 +0100
@@ -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: gcc/cfgcleanup.c
===================================================================
--- gcc/cfgcleanup.c	2017-10-23 17:11:40.377197950 +0100
+++ gcc/cfgcleanup.c	2017-10-23 17:18:57.856161229 +0100
@@ -1182,7 +1182,7 @@  old_insns_match_p (int mode ATTRIBUTE_UN
       /* ??? 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)
+	  && must_eq (find_args_size_adjust (i1), HOST_WIDE_INT_MIN))
 	return dir_none;
     }
   else if (p1 || p2)
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	2017-10-23 17:16:50.358529897 +0100
+++ gcc/combine.c	2017-10-23 17:18:57.858161053 +0100
@@ -14140,7 +14140,7 @@  distribute_notes (rtx notes, rtx_insn *f
 	     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))
@@ -14159,7 +14159,7 @@  distribute_notes (rtx notes, rtx_insn *f
 	      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 (may_ne (old_size, args_size)
 			  || (CALL_P (i3)
 			      && !ACCUMULATE_OUTGOING_ARGS
 			      && find_reg_note (i3, REG_NORETURN, NULL_RTX)));
Index: gcc/dwarf2cfi.c
===================================================================
--- gcc/dwarf2cfi.c	2017-10-23 17:16:57.208604839 +0100
+++ gcc/dwarf2cfi.c	2017-10-23 17:18:57.858161053 +0100
@@ -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);
 }
@@ -924,16 +927,16 @@  reg_save (unsigned int reg, unsigned int
 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_zero (delta))
     return;
 
   cur_trace->end_true_args_size = args_size;
@@ -959,16 +962,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 (may_ne (cur_trace->end_delay_args_size, args_size))
     {
       cur_trace->end_delay_args_size = args_size;
 
@@ -2289,7 +2290,6 @@  static void dump_cfi_row (FILE *f, dw_cf
 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);
@@ -2302,7 +2302,7 @@  maybe_record_trace_start (rtx_insn *star
 	       (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
@@ -2342,7 +2342,7 @@  maybe_record_trace_start (rtx_insn *star
 #endif
 
       /* The args_size is allowed to conflict if it isn't actually used.  */
-      if (ti->beg_true_args_size != args_size)
+      if (may_ne (ti->beg_true_args_size, args_size))
 	ti->args_size_undefined = true;
     }
 }
@@ -2353,11 +2353,11 @@  maybe_record_trace_start (rtx_insn *star
 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_zero (save_args_size))
     {
       maybe_record_trace_start (start, origin);
       return;
@@ -2549,7 +2549,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
@@ -2557,7 +2556,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);
 
@@ -2799,7 +2798,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)
 	{
@@ -2811,7 +2810,7 @@  connect_traces (void)
 	    continue;
 	  gcc_assert (!ti->args_size_undefined);
 
-	  if (ti->beg_delay_args_size != prev_args_size)
+	  if (may_ne (ti->beg_delay_args_size, prev_args_size))
 	    {
 	      /* ??? Search back to previous CFI note.  */
 	      add_cfi_insn = PREV_INSN (ti->eh_head);
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	2017-10-23 17:16:55.754801166 +0100
+++ gcc/emit-rtl.c	2017-10-23 17:18:57.859160965 +0100
@@ -3947,7 +3947,7 @@  try_split (rtx pat, rtx_insn *trial, int
 	  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: gcc/recog.c
===================================================================
--- gcc/recog.c	2017-10-23 17:16:50.372528007 +0100
+++ gcc/recog.c	2017-10-23 17:18:57.860160878 +0100
@@ -3464,7 +3464,7 @@  peep2_attempt (basic_block bb, rtx_insn
 
   /* 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: gcc/reload1.c
===================================================================
--- gcc/reload1.c	2017-10-23 17:18:53.835514671 +0100
+++ gcc/reload1.c	2017-10-23 17:18:57.861160790 +0100
@@ -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: gcc/expr.c
===================================================================
--- gcc/expr.c	2017-10-23 17:18:56.434286222 +0100
+++ gcc/expr.c	2017-10-23 17:18:57.860160878 +0100
@@ -3939,9 +3939,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;
@@ -4064,22 +4064,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_zero (this_delta))
 	{
 	  if (!CALL_P (insn)
 	      || ACCUMULATE_OUTGOING_ARGS
@@ -4088,17 +4087,17 @@  fixup_args_size_notes (rtx_insn *prev, r
 	}
 
       gcc_assert (!saw_unknown);
-      if (this_delta == HOST_WIDE_INT_MIN)
+      if (must_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);
 
       args_size -= this_delta;
     }
 
-  return saw_unknown ? INT_MIN : args_size;
+  return saw_unknown ? poly_int64 (HOST_WIDE_INT_MIN) : args_size;
 }
 
 #ifdef PUSH_ROUNDING
@@ -4193,7 +4192,7 @@  emit_single_push_insn_1 (machine_mode mo
 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;
 
@@ -4204,12 +4203,13 @@  emit_single_push_insn (machine_mode mode
   /* 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 (must_eq (delta, HOST_WIDE_INT_MIN)
+	      || must_eq (delta, old_delta));
 }
 #endif