PR88845 shows a problem where LRA spilled an input operand of an inline
asm statement by calling our generic movsf pattern which ended up generating
an insn we don't have a pattern for, so we ICE.  The insn was:

  (insn (set (reg:SF 125)
             (subreg:SF (reg:SI 124) 0)))

The problem is that rs6000_emit_move_si_sf_subreg() is disabled for LRA
and so wasn't able to call gen_movsf_from_si() which generates the correct
pattern for moving a 32-bit value from a GPR to a FPR.  The patch below
fixes the issue by allowing rs6000_emit_move_si_sf_subreg() to be called
during LRA as well as creating an expander so that when it is called during
LRA, we can create the scratch register that is required for its associated
splitter.  We have to do this, since LRA has already converted all of the
scratches into real registers before it does any spilling.

This passed bootstrap and regtesting on powerpc64le-linux with no
regressions.  Ok for mainline?

Peter

gcc/
        PR rtl-optimization/88845
        * config/rs6000/rs6000.c (rs6000_emit_move_si_sf_subreg): Enable during
        LRA.
        * config/rs6000/rs6000.md (movsf_from_si): New expander; old insn and
        splitter renamed from this ...
        (movsf_from_si_internal): ... to this.

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/config/rs6000/rs6000.md
===================================================================
--- gcc/config/rs6000/rs6000.md (revision 269263)
+++ gcc/config/rs6000/rs6000.md (working copy)
@@ -7353,9 +7353,31 @@ (define_insn "*mov<mode>_softfloat"
 ;; This function is called before reload, and it creates the temporary as
 ;; needed.
 
+(define_expand "movsf_from_si"
+  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand")
+                  (unspec:SF [(match_operand:SI 1 "input_operand" )]
+                             UNSPEC_SF_FROM_SI))
+             (clobber (match_scratch:DI 2))])]
+  "TARGET_NO_SF_SUBREG
+   && (register_operand (operands[0], SFmode)
+       || register_operand (operands[1], SImode))"
+{
+  if (lra_in_progress
+      && REG_P (operands[0])
+      && REG_P (operands[1]))
+    {
+      /* If LRA is generating a direct move from a GPR to a FPR,
+        then the splitter is going to need a scratch register.  */
+      rtx insn = gen_movsf_from_si_internal (operands[0], operands[1]);
+      XEXP (XVECEXP (insn, 0, 1), 0) = gen_reg_rtx (DImode);
+      emit_insn (insn);
+      DONE;
+    }
+})
+
 ;;         LWZ          LFS        LXSSP      LXSSPX     STW        STFIWX
 ;;         STXSIWX      GPR->VSX   VSX->GPR   GPR->GPR
-(define_insn_and_split "movsf_from_si"
+(define_insn_and_split "movsf_from_si_internal"
   [(set (match_operand:SF 0 "nonimmediate_operand"
            "=!r,       f,         wb,        wu,        m,         Z,
             Z,         wy,        ?r,        !r")
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,25 @@
+/* { dg-do compile { target powerpc*-*-linux* } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } } */
+/* { dg-skip-if "" { powerpc*-*-*spe* } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { 
"-mcpu=power8" } } */
+/* { dg-options "-mcpu=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