The following fixes

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97978

The patch was successfully bootstrapped on x86-64.


commit fbf9b2b634e376516cd21d7aa92ef3fd5778aa10 (HEAD -> master)
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Wed Jan 6 14:48:53 2021 -0500

    [PR97978] LRA: Permit temporary allocation incorrectness after hard reg split.

    LRA can crash when a hard register was split and the same hard register
    was assigned on the previous assignment sub-pass.  The following
    patch fixes this problem.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/97978
            * lra-int.h (lra_hard_reg_split_p): New external.
            * lra.c (lra_hard_reg_split_p): New global.
            (lra): Set up lra_hard_reg_split_p after splitting a hard reg.
            * lra-assigns.c (lra_assign): Don't check allocation correctness
            after hard reg splitting.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/97978
            * gcc.target/i386/pr97978.c: New.

diff --git a/gcc/lra-assigns.c b/gcc/lra-assigns.c
index 9335e4c876e..c6a941fe663 100644
--- a/gcc/lra-assigns.c
+++ b/gcc/lra-assigns.c
@@ -1636,10 +1636,11 @@ lra_assign (bool &fails_p)
   bitmap_initialize (&all_spilled_pseudos, &reg_obstack);
   create_live_range_start_chains ();
   setup_live_pseudos_and_spill_after_risky_transforms (&all_spilled_pseudos);
-  if (! lra_asm_error_p && flag_checking)
-    /* Check correctness of allocation for call-crossed pseudos but
-       only when there are no asm errors as in the case of errors the
-       asm is removed and it can result in incorrect allocation.  */
+  if (! lra_hard_reg_split_p && ! lra_asm_error_p && flag_checking)
+    /* Check correctness of allocation but only when there are no hard reg
+       splits and asm errors as in the case of errors explicit insns involving
+       hard regs are added or the asm is removed and this can result in
+       incorrect allocation.  */
     for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
       if (lra_reg_info[i].nrefs != 0
 	  && reg_renumber[i] >= 0
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 75ba6560bcc..1b8f7b6ae61 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -273,6 +273,7 @@ typedef class lra_insn_recog_data *lra_insn_recog_data_t;
 
 extern FILE *lra_dump_file;
 
+extern bool lra_hard_reg_split_p;
 extern bool lra_asm_error_p;
 extern bool lra_reg_spill_p;
 
diff --git a/gcc/lra.c b/gcc/lra.c
index 380a21ac2ac..aa49de6f154 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -2211,6 +2211,9 @@ bitmap_head lra_subreg_reload_pseudos;
 /* File used for output of LRA debug information.  */
 FILE *lra_dump_file;
 
+/* True if we split hard reg after the last constraint sub-pass.  */
+bool lra_hard_reg_split_p;
+
 /* True if we found an asm error.  */
 bool lra_asm_error_p;
 
@@ -2359,6 +2362,7 @@ lra (FILE *f)
 	  if (live_p)
 	    lra_clear_live_ranges ();
 	  bool fails_p;
+	  lra_hard_reg_split_p = false;
 	  do
 	    {
 	      /* We need live ranges for lra_assign -- so build them.
@@ -2403,6 +2407,7 @@ lra (FILE *f)
 		  live_p = false;
 		  if (! lra_split_hard_reg_for ())
 		    break;
+		  lra_hard_reg_split_p = true;
 		}
 	    }
 	  while (fails_p);
diff --git a/gcc/testsuite/gcc.target/i386/pr97978.c b/gcc/testsuite/gcc.target/i386/pr97978.c
new file mode 100644
index 00000000000..263bca8708d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr97978.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-Os -fno-PIC" } */
+int sg;
+long int kk;
+
+void
+bp (int jz, int tj, long int li)
+{
+  if (jz == 0 || tj == 0)
+    __builtin_unreachable ();
+
+  kk = li;
+}
+
+void
+qp (void)
+{
+  ++kk;
+
+  for (;;)
+    bp (1l / sg, 0, ~0u);
+}

Reply via email to