aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-12-28 17:40:17 +0100
committerJakub Jelinek <jakub@redhat.com>2021-12-28 17:40:17 +0100
commit3c5fd3616f73fbcd241cc3a5e09275c2b0c49bd4 (patch)
tree866d5f0b3c7bae8a20a130111b7a98673e4be884
parent78ee8381bf0ebd09a92936bdb9e1b5c9fc85ad88 (diff)
loop-invariant: Fix -fcompare-debug failure [PR103837]
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. 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.
-rw-r--r--gcc/loop-invariant.c19
-rw-r--r--gcc/testsuite/gcc.dg/pr103837.c19
2 files changed, 34 insertions, 4 deletions
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 5eee2e5c9f8..be951554337 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1691,6 +1691,7 @@ can_move_invariant_reg (class loop *loop, struct invariant *inv, rtx reg)
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, struct invariant *inv, rtx reg)
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, struct invariant *inv, rtx reg)
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;
}
diff --git a/gcc/testsuite/gcc.dg/pr103837.c b/gcc/testsuite/gcc.dg/pr103837.c
new file mode 100644
index 00000000000..43593d52b6c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103837.c
@@ -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;
+}