diff mbox series

loop-invariant: Fix -fcompare-debug failure [PR103837]

Message ID 20211228102151.GP2646553@tucnak
State New
Headers show
Series loop-invariant: Fix -fcompare-debug failure [PR103837] | expand

Commit Message

Jakub Jelinek Dec. 28, 2021, 10:21 a.m. UTC
Hi!

In the following testcase we have a -fcompare-debug failure, because
can_move_invariant_reg doesn't ignore DEBUG_INSNs in its decisions.
In the testcase we have due to uninitialized variable:
  loop_header
    debug_insn using pseudo84
    pseudo84 = invariant
    insn using pseudo84
  end loop
and with -g decide not to move the pseudo84 = invariant before the
loop header; in this case not resetting the debug insns might be fine.
But, we could have also:
  pseudo84 = whatever
  loop_header
    debug_insn using pseudo84
    pseudo84 = invariant
    insn using pseudo84
  end loop
and in that case not resetting the debug insns would result in wrong-debug.
And, we don't really have generally a good substitution on what pseudo84
contains, it could inherit various values from different paths.
So, the following patch ignores DEBUG_INSNs in the decisions, and if there
are any that previously prevented the optimization, resets them before
return true.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-12-28  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/103837
	* loop-invariant.c (can_move_invariant_reg): Ignore DEBUG_INSNs in
	the decisions whether to return false or continue and right before
	returning true reset those debug insns that previously caused
	returning false.

	* gcc.dg/pr103837.c: New test.


	Jakub

Comments

Jeff Law Dec. 28, 2021, 3:26 p.m. UTC | #1
On 12/28/2021 3:21 AM, Jakub Jelinek wrote:
> Hi!
>
> In the following testcase we have a -fcompare-debug failure, because
> can_move_invariant_reg doesn't ignore DEBUG_INSNs in its decisions.
> In the testcase we have due to uninitialized variable:
>    loop_header
>      debug_insn using pseudo84
>      pseudo84 = invariant
>      insn using pseudo84
>    end loop
> and with -g decide not to move the pseudo84 = invariant before the
> loop header; in this case not resetting the debug insns might be fine.
> But, we could have also:
>    pseudo84 = whatever
>    loop_header
>      debug_insn using pseudo84
>      pseudo84 = invariant
>      insn using pseudo84
>    end loop
> and in that case not resetting the debug insns would result in wrong-debug.
> And, we don't really have generally a good substitution on what pseudo84
> contains, it could inherit various values from different paths.
> So, the following patch ignores DEBUG_INSNs in the decisions, and if there
> are any that previously prevented the optimization, resets them before
> return true.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2021-12-28  Jakub Jelinek  <jakub@redhat.com>
>
> 	PR rtl-optimization/103837
> 	* loop-invariant.c (can_move_invariant_reg): Ignore DEBUG_INSNs in
> 	the decisions whether to return false or continue and right before
> 	returning true reset those debug insns that previously caused
> 	returning false.
>
> 	* gcc.dg/pr103837.c: New test.
OK
jeff
diff mbox series

Patch

--- gcc/loop-invariant.c.jj	2021-11-25 08:33:08.619232065 +0100
+++ gcc/loop-invariant.c	2021-12-27 13:44:44.094132316 +0100
@@ -1691,6 +1691,7 @@  can_move_invariant_reg (class loop *loop
   unsigned int dest_regno, defs_in_loop_count = 0;
   rtx_insn *insn = inv->insn;
   basic_block bb = BLOCK_FOR_INSN (inv->insn);
+  auto_vec <rtx_insn *, 16> debug_insns_to_reset;
 
   /* We ignore hard register and memory access for cost and complexity reasons.
      Hard register are few at this stage and expensive to consider as they
@@ -1725,10 +1726,13 @@  can_move_invariant_reg (class loop *loop
 	continue;
 
       /* Don't move if a use is not dominated by def in insn.  */
-      if (use_bb == bb && DF_INSN_LUID (insn) >= DF_INSN_LUID (use_insn))
-	return false;
-      if (!dominated_by_p (CDI_DOMINATORS, use_bb, bb))
-	return false;
+      if ((use_bb == bb && DF_INSN_LUID (insn) >= DF_INSN_LUID (use_insn))
+	  || !dominated_by_p (CDI_DOMINATORS, use_bb, bb))
+	{
+	  if (!DEBUG_INSN_P (use_insn))
+	    return false;
+	  debug_insns_to_reset.safe_push (use_insn);
+	}
     }
 
   /* Check for other defs.  Any other def in the loop might reach a use
@@ -1751,6 +1755,13 @@  can_move_invariant_reg (class loop *loop
 	return false;
     }
 
+  /* Reset debug uses if a use is not dominated by def in insn.  */
+  for (auto use_insn : debug_insns_to_reset)
+    {
+      INSN_VAR_LOCATION_LOC (use_insn) = gen_rtx_UNKNOWN_VAR_LOC ();
+      df_insn_rescan (use_insn);
+    }
+
   return true;
 }
 
--- gcc/testsuite/gcc.dg/pr103837.c.jj	2021-12-27 13:42:23.262111770 +0100
+++ gcc/testsuite/gcc.dg/pr103837.c	2021-12-27 13:41:36.635767125 +0100
@@ -0,0 +1,19 @@ 
+/* PR rtl-optimization/103837 */
+/* { dg-do compile } */
+/* { dg-options "-Og -fcompare-debug -fmove-loop-invariants -fnon-call-exceptions -fexceptions -fdelete-dead-exceptions -fno-tree-dce -w" } */
+
+unsigned long int
+foo (int x)
+{
+  double a;
+  int b;
+  unsigned long int ret = a;
+
+  for (;;)
+    {
+      b = !!((int) a);
+      a = x;
+    }
+
+  return ret;
+}