Blob Blame History Raw
2019-01-21  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/88904
	* cfgcleanup.c (thread_jump): Verify cond2 doesn't mention
	any nonequal registers before processing BB_END (b).

	* gcc.c-torture/execute/pr88904.c: New test.

--- gcc/cfgcleanup.c.jj	2019-01-01 12:37:19.147942300 +0100
+++ gcc/cfgcleanup.c	2019-01-21 16:45:52.576636305 +0100
@@ -338,6 +338,13 @@ thread_jump (edge e, basic_block b)
        insn != NEXT_INSN (BB_END (b)) && !failed;
        insn = NEXT_INSN (insn))
     {
+      /* cond2 must not mention any register that is not equal to the
+	 former block.  Check this before processing that instruction,
+	 as BB_END (b) could contain also clobbers.  */
+      if (insn == BB_END (b)
+	  && mentions_nonequal_regs (cond2, nonequal))
+	goto failed_exit;
+
       if (INSN_P (insn))
 	{
 	  rtx pat = PATTERN (insn);
@@ -362,11 +369,6 @@ thread_jump (edge e, basic_block b)
       goto failed_exit;
     }
 
-  /* cond2 must not mention any register that is not equal to the
-     former block.  */
-  if (mentions_nonequal_regs (cond2, nonequal))
-    goto failed_exit;
-
   EXECUTE_IF_SET_IN_REG_SET (nonequal, 0, i, rsi)
     goto failed_exit;
 
--- gcc/testsuite/gcc.c-torture/execute/pr88904.c.jj	2019-01-21 16:47:16.194265770 +0100
+++ gcc/testsuite/gcc.c-torture/execute/pr88904.c	2019-01-21 16:46:59.278543027 +0100
@@ -0,0 +1,38 @@
+/* PR rtl-optimization/88904 */
+
+volatile int v;
+
+__attribute__((noipa)) void
+bar (const char *x, const char *y, int z)
+{
+  if (!v)
+    __builtin_abort ();
+  asm volatile ("" : "+g" (x));
+  asm volatile ("" : "+g" (y));
+  asm volatile ("" : "+g" (z));
+}
+
+#define my_assert(e) ((e) ? (void) 0 : bar (#e, __FILE__, __LINE__))
+
+typedef struct {
+  unsigned M1;
+  unsigned M2 : 1;
+  int : 0;
+  unsigned M3 : 1;
+} S;
+
+S
+foo ()
+{
+  S result = {0, 0, 1};
+  return result;
+}
+
+int
+main ()
+{
+  S ret = foo ();
+  my_assert (ret.M2 == 0);
+  my_assert (ret.M3 == 1);
+  return 0;
+}