On 3/4/19 4:24 PM, Peter Bergner wrote:
> On 3/4/19 4:16 PM, Peter Bergner wrote:
>> Index: gcc/config/rs6000/rs6000.c
>> ===================================================================
>> --- gcc/config/rs6000/rs6000.c       (revision 269028)
>> +++ gcc/config/rs6000/rs6000.c       (working copy)
>> @@ -9887,7 +9887,7 @@ valid_sf_si_move (rtx dest, rtx src, mac
>>  static bool
>>  rs6000_emit_move_si_sf_subreg (rtx dest, rtx source, machine_mode mode)
>>  {
>> -  if (TARGET_DIRECT_MOVE_64BIT && !lra_in_progress && !reload_completed
>> +  if (TARGET_DIRECT_MOVE_64BIT && !reload_completed
>>        && (!SUBREG_P (dest) || !sf_subreg_operand (dest, mode))
>>        && SUBREG_P (source) && sf_subreg_operand (source, mode))
>>      {
>> @@ -9902,7 +9902,9 @@ rs6000_emit_move_si_sf_subreg (rtx dest,
>>  
>>        if (mode == SFmode && inner_mode == SImode)
>>      {
>> -      emit_insn (gen_movsf_from_si (dest, inner_source));
>> +      rtx_insn *insn = emit_insn (gen_movsf_from_si (dest, inner_source));
>> +      if (lra_in_progress)
>> +        remove_scratches_1 (insn);
>>        return true;
>>      }
>>      }
> 
> But maybe the call to remove_scratches_1() should move to lra_emit_move(),
> which is how we get to this code in the first place?  Who knows what other
> generic move patterns might need scratches too?

Like this.  This bootstraps and regtests with no regressions.  Do you prefer
this instead?  If so, we'll need Vlad or Jeff or ... to approve the LRA
changes.

Vlad and Jeff,

The original problem and patch is described here:

    https://gcc.gnu.org/ml/gcc-patches/2019-03/msg00061.html

Short answer is, after enabling a rs6000 move pattern we need for spilling,
we ICE when spilling, because the move pattern uses a scratch register
and scratch registers are replaced early on during LRA initialization.
The patch below just extracts out the code that fixes up one insn and
makes it a function itself.  I then changed lra_emit_move() to then call
that function after generating the move insn so as to replace the scratch
register the move pattern generated.  Thoughts on this patch compared to
the rs6000 only patch linked above?

Peter


gcc/
        PR rtl-optimization/88845
        * config/rs6000/rs6000.c (rs6000_emit_move_si_sf_subreg): Enable during
        LRA.
        * lra.c (remove_scratches_1): New function.
        (remove_scratches): Use it.
        (lra_emit_move): Likewise.

gcc/testsuite/
        PR rtl-optimization/88845
        * gcc.target/powerpc/pr88845.c: New test.

Index: gcc/config/rs6000/rs6000.c
===================================================================
--- gcc/config/rs6000/rs6000.c  (revision 269263)
+++ gcc/config/rs6000/rs6000.c  (working copy)
@@ -9887,7 +9887,7 @@ valid_sf_si_move (rtx dest, rtx src, mac
 static bool
 rs6000_emit_move_si_sf_subreg (rtx dest, rtx source, machine_mode mode)
 {
-  if (TARGET_DIRECT_MOVE_64BIT && !lra_in_progress && !reload_completed
+  if (TARGET_DIRECT_MOVE_64BIT && !reload_completed
       && (!SUBREG_P (dest) || !sf_subreg_operand (dest, mode))
       && SUBREG_P (source) && sf_subreg_operand (source, mode))
     {
Index: gcc/lra.c
===================================================================
--- gcc/lra.c   (revision 269263)
+++ gcc/lra.c   (working copy)
@@ -159,6 +159,7 @@ static void invalidate_insn_recog_data (
 static int get_insn_freq (rtx_insn *);
 static void invalidate_insn_data_regno_info (lra_insn_recog_data_t,
                                             rtx_insn *, int);
+static void remove_scratches_1 (rtx_insn *);
 
 /* Expand all regno related info needed for LRA.  */
 static void
@@ -494,7 +495,11 @@ lra_emit_move (rtx x, rtx y)
       if (rtx_equal_p (x, y))
        return;
       old = max_reg_num ();
-      emit_move_insn (x, y);
+      rtx_insn *insn = emit_move_insn (x, y);
+      /* The move pattern may require scratch registers, so convert them
+        into real registers now.  */
+      if (insn != NULL_RTX)
+       remove_scratches_1 (insn);
       if (REG_P (x))
        lra_reg_info[ORIGINAL_REGNO (x)].last_reload = ++lra_curr_reload_num;
       /* Function emit_move can create pseudos -- so expand the pseudo
@@ -2077,47 +2082,53 @@ lra_register_new_scratch_op (rtx_insn *i
   add_reg_note (insn, REG_UNUSED, op);
 }
 
-/* Change scratches onto pseudos and save their location.  */
+/* Change INSN's scratches into pseudos and save their location.  */
 static void
-remove_scratches (void)
+remove_scratches_1 (rtx_insn *insn)
 {
   int i;
   bool insn_changed_p;
-  basic_block bb;
-  rtx_insn *insn;
   rtx reg;
   lra_insn_recog_data_t id;
   struct lra_static_insn_data *static_id;
 
+  id = lra_get_insn_recog_data (insn);
+  static_id = id->insn_static_data;
+  insn_changed_p = false;
+  for (i = 0; i < static_id->n_operands; i++)
+    if (GET_CODE (*id->operand_loc[i]) == SCRATCH
+       && GET_MODE (*id->operand_loc[i]) != VOIDmode)
+      {
+       insn_changed_p = true;
+       *id->operand_loc[i] = reg
+         = lra_create_new_reg (static_id->operand[i].mode,
+                               *id->operand_loc[i], ALL_REGS, NULL);
+       lra_register_new_scratch_op (insn, i, id->icode);
+       if (lra_dump_file != NULL)
+         fprintf (lra_dump_file,
+                  "Removing SCRATCH in insn #%u (nop %d)\n",
+                  INSN_UID (insn), i);
+      }
+  if (insn_changed_p)
+    /* Because we might use DF right after caller-saves sub-pass
+       we need to keep DF info up to date.  */
+    df_insn_rescan (insn);
+}
+
+/* Change scratches into pseudos and save their location.  */
+static void
+remove_scratches (void)
+{
+  basic_block bb;
+  rtx_insn *insn;
+
   scratches.create (get_max_uid ());
   bitmap_initialize (&scratch_bitmap, &reg_obstack);
   bitmap_initialize (&scratch_operand_bitmap, &reg_obstack);
   FOR_EACH_BB_FN (bb, cfun)
     FOR_BB_INSNS (bb, insn)
     if (INSN_P (insn))
-      {
-       id = lra_get_insn_recog_data (insn);
-       static_id = id->insn_static_data;
-       insn_changed_p = false;
-       for (i = 0; i < static_id->n_operands; i++)
-         if (GET_CODE (*id->operand_loc[i]) == SCRATCH
-             && GET_MODE (*id->operand_loc[i]) != VOIDmode)
-           {
-             insn_changed_p = true;
-             *id->operand_loc[i] = reg
-               = lra_create_new_reg (static_id->operand[i].mode,
-                                     *id->operand_loc[i], ALL_REGS, NULL);
-             lra_register_new_scratch_op (insn, i, id->icode);
-             if (lra_dump_file != NULL)
-               fprintf (lra_dump_file,
-                        "Removing SCRATCH in insn #%u (nop %d)\n",
-                        INSN_UID (insn), i);
-           }
-       if (insn_changed_p)
-         /* Because we might use DF right after caller-saves sub-pass
-            we need to keep DF info up to date.  */
-         df_insn_rescan (insn);
-      }
+      remove_scratches_1 (insn);
 }
 
 /* Changes pseudos created by function remove_scratches onto scratches.        
 */
Index: gcc/testsuite/gcc.target/powerpc/pr88845.c
===================================================================
--- gcc/testsuite/gcc.target/powerpc/pr88845.c  (nonexistent)
+++ gcc/testsuite/gcc.target/powerpc/pr88845.c  (working copy)
@@ -0,0 +1,24 @@
+/* { dg-do compile { target powerpc*-*-linux* } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mdejagnu-cpu=power8 -O2" } */
+/* { dg-final { scan-assembler {\mmtvsrd\M} { target { lp64 } } } } */
+/* { dg-final { scan-assembler {\mxscvspdpn\M} { target { lp64 } } } } */
+
+/* Verify that we do not ICE and that we generate a direct move
+   for float types when compiling for 64-bit.  */
+
+struct a {
+  unsigned ui;
+  float f;
+};
+
+void
+foo (void)
+{
+  float e;
+  struct a s;
+  e = s.f;
+  __asm__("" : : "d" (e));
+}


Reply via email to