This patch fixes a corner case in the AMD GCN md-reorg pass when the
EXEC register is live on entry to a BB, and could be clobbered by code
inserted by the pass before a use in (e.g.) a different BB.

I don't have a standalone test case demonstrating this failure mode,
but I did observe it with an offload compiler (on another branch) with
a particular benchmark.

Tested with standalone AMD GCN target. I will commit shortly.

Julian

2021-01-13  Julian Brown  <jul...@codesourcery.com>

gcc/
        * config/gcn/gcn.c (gcn_md_reorg): Fix case where EXEC reg is live
        on entry to a BB.
---
 gcc/config/gcn/gcn.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index 0fb9bd26727..630ce4eebc7 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -4501,6 +4501,8 @@ gcn_md_reorg (void)
       df_insn_rescan_all ();
     }
 
+  df_live_add_problem ();
+  df_live_set_all_dirty ();
   df_analyze ();
 
   /* This pass ensures that the EXEC register is set correctly, according
@@ -4522,6 +4524,17 @@ gcn_md_reorg (void)
       int64_t curr_exec = 0;   /* 0 here means 'the value is that of EXEC
                                   after last_exec_def is executed'.  */
 
+      bitmap live_in = DF_LR_IN (bb);
+      bool exec_live_on_entry = false;
+      if (bitmap_bit_p (live_in, EXEC_LO_REG)
+         || bitmap_bit_p (live_in, EXEC_HI_REG))
+       {
+         if (dump_file)
+           fprintf (dump_file, "EXEC reg is live on entry to block %d\n",
+                    (int) bb->index);
+         exec_live_on_entry = true;
+       }
+
       FOR_BB_INSNS_SAFE (bb, insn, curr)
        {
          if (!NONDEBUG_INSN_P (insn))
@@ -4660,6 +4673,8 @@ gcn_md_reorg (void)
                         exec_lo_def_p == exec_hi_def_p ? "full" : "partial",
                         INSN_UID (insn));
            }
+
+         exec_live_on_entry = false;
        }
 
       COPY_REG_SET (&live, DF_LR_OUT (bb));
@@ -4669,7 +4684,7 @@ gcn_md_reorg (void)
         at the end of the block.  */
       if ((REGNO_REG_SET_P (&live, EXEC_LO_REG)
           || REGNO_REG_SET_P (&live, EXEC_HI_REG))
-         && (!curr_exec_known || !curr_exec_explicit))
+         && (!curr_exec_known || !curr_exec_explicit || exec_live_on_entry))
        {
          rtx_insn *end_insn = BB_END (bb);
 
-- 
2.29.2

Reply via email to