[committed] Fix ICE in maybe_record_trace_start

Message ID ad22d7c5-a3a3-ac9d-bbfb-4decc5c25c5e@redhat.com
State New
Headers show
Series
  • [committed] Fix ICE in maybe_record_trace_start
Related show

Commit Message

Jeff Law Feb. 12, 2018, 6:32 p.m.
This was something my tester was tripping over on h8-elf.  I was hoping
it was going to fix the similar ICEs for the SH port, but alas those are
different.

The fundamental problem is generic code generated something like this:

(set (temp) (plus (stack_pointer_rtx) (const_int))
(set (stack_pointer_rtx) (temp))  REG_ARGS_SIZE note


The backward propagation step in cse.c turns the first insn into:

(set (stack_pointer_rtx) (plus (stack_pointer_rtx) (const_int))

And the second insn gets deleted, losing the REG_ARGS_SIZE note.

We then cross jump the tail of that block with the tail of another block
which has REG_ARGS_SIZE notes that do not get deleted.

The net result is at the commonized tail we have two paths which
different notions of REG_ARGS_SIZE and thus different CFIs, triggering
the ICE.

The most sensible way to fix this is to move the REG_ARGS_SIZE note
during the backward propagation step in cse.c

That allows the H8 port to build libgcc/newlib across all its multilib
variants.

I've also bootstrapped and regression tested on x86_64-linux-gnu, though
I doubt it really got exercised there.

Installing on the trunk.  Now back to the SH, rx and mips problems with
maybe_record_trace_start.

Jeff

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5a264391268..d5913d0a7db 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@ 
+2018-02-12  Jeff Law  <law@redhat.com>
+
+	* cse.c (try_back_substitute_reg): Move any REG_ARGS_SIZE note when
+	successfully back substituting a reg.
+
 2018-02-12  Richard Biener  <rguenther@suse.de>
 
 	PR tree-optimization/84037
diff --git a/gcc/cse.c b/gcc/cse.c
index 825b0bd8989..a73a771041a 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -4256,6 +4256,15 @@  try_back_substitute_reg (rtx set, rtx_insn *insn)
 		  && (reg_mentioned_p (dest, XEXP (note, 0))
 		      || rtx_equal_p (src, XEXP (note, 0))))
 		remove_note (insn, note);
+
+	      /* If INSN has a REG_ARGS_SIZE note, move it to PREV.  */
+	      note = find_reg_note (insn, REG_ARGS_SIZE, NULL_RTX);
+	      if (note != 0)
+		{
+		  remove_note (insn, note);
+		  gcc_assert (!find_reg_note (prev, REG_ARGS_SIZE, NULL_RTX));
+		  set_unique_reg_note (prev, REG_ARGS_SIZE, XEXP (note, 0));
+		}
 	    }
 	}
     }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dba0bedb7cf..8f22a65c7bb 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@ 
+2018-02-12  Jeff Law  <law@redhat.com>
+
+	* gcc.c-torture/compile/reg-args-size.c: New test.
+
 2018-02-12  Carl Love  <cel@us.ibm.com>
 
 	* gcc.target/powerpc/builtins-4-runnable.c (main): Move int128 and
diff --git a/gcc/testsuite/gcc.c-torture/compile/regs-arg-size.c b/gcc/testsuite/gcc.c-torture/compile/regs-arg-size.c
new file mode 100644
index 00000000000..0ca0b9f034b
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/regs-arg-size.c
@@ -0,0 +1,36 @@ 
+int foo;
+typedef long unsigned int size_t;
+typedef short unsigned int wchar_t;
+struct tm
+{
+  int tm_mday;
+  int tm_mon;
+  int tm_year;
+};
+size_t
+__strftime (wchar_t * s, size_t maxsize, const wchar_t * format, const struct tm *tim_p)
+{
+  size_t count = 0;
+  int len = 0;
+  size_t i, ctloclen;
+  unsigned long width;
+  {
+    if (foo)
+      {
+	{
+	  wchar_t *fmt = L"%s%.*d";
+	  len = swprintf (&s[count], maxsize, fmt, "-", width, 0);
+	}
+	if ((count) >= maxsize)
+	  return 0;
+      }
+    else
+      {
+	len =
+	  swprintf (&s[count], maxsize - count, L"%.2d/%.2d/%.2d", 42, 99, 0);
+	if ((count) >= maxsize)
+	  return 0;
+
+      }
+  }
+}