]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000.c (rs6000_hard_regno_mode_ok): Allow DFmode...
authorMichael Meissner <meissner@linux.vnet.ibm.com>
Fri, 27 Sep 2013 19:33:52 +0000 (19:33 +0000)
committerMichael Meissner <meissner@gcc.gnu.org>
Fri, 27 Sep 2013 19:33:52 +0000 (19:33 +0000)
[gcc]
2013-09-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

* config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
DFmode, DImode, and SFmode in the upper VSX registers based on the
-mupper-regs-{df,sf} flags.  Fix wu constraint to be ALTIVEC_REGS
if -mpower8-vector.  Combine -mvsx-timode handling with the rest
of the VSX register handling.

* config/rs6000/rs6000.md (f32_lv): Use %x0 for VSX regsters.
(f32_sv): Likewise.
(zero_extendsidi2_lfiwzx): Add support for loading into the
Altivec registers with -mpower8-vector.  Use wu/wv constraints to
only do VSX memory options on Altivec registers.
(extendsidi2_lfiwax): Likewise.
(extendsfdf2_fpr): Likewise.
(mov<mode>_hardfloat, SF/SD modes): Likewise.
(mov<mode>_hardfloat32, DF/DD modes): Likewise.
(mov<mode>_hardfloat64, DF/DD modes): Likewise.
(movdi_internal64): Likewise.

[gcc/testsuite]
2013-09-27  Michael Meissner  <meissner@linux.vnet.ibm.com>

* gcc.target/powerpc/p8vector-ldst.c: New test for -mupper-regs-sf
and -mupper-regs-df.

From-SVN: r202984

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c [new file with mode: 0644]

index 9712bc80dfeb39d101596251b0a9029a9023bcf8..d7f20cb367783237606ac930e2da79abb381947b 100644 (file)
@@ -1,3 +1,23 @@
+2013-09-27  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * config/rs6000/rs6000.c (rs6000_hard_regno_mode_ok): Allow
+       DFmode, DImode, and SFmode in the upper VSX registers based on the
+       -mupper-regs-{df,sf} flags.  Fix wu constraint to be ALTIVEC_REGS
+       if -mpower8-vector.  Combine -mvsx-timode handling with the rest
+       of the VSX register handling.
+
+       * config/rs6000/rs6000.md (f32_lv): Use %x0 for VSX regsters.
+       (f32_sv): Likewise.
+       (zero_extendsidi2_lfiwzx): Add support for loading into the
+       Altivec registers with -mpower8-vector.  Use wu/wv constraints to
+       only do VSX memory options on Altivec registers.
+       (extendsidi2_lfiwax): Likewise.
+       (extendsfdf2_fpr): Likewise.
+       (mov<mode>_hardfloat, SF/SD modes): Likewise.
+       (mov<mode>_hardfloat32, DF/DD modes): Likewise.
+       (mov<mode>_hardfloat64, DF/DD modes): Likewise.
+       (movdi_internal64): Likewise.
+
 2013-09-27  Xinliang David Li  <davidxl@google.com>
 
        * opts.c (finish_options): Adjust parameters
index 1f98c668e744406002ced73b89556ae3e7fd766b..4197687c083ef986d106452d4b395948b5952e69 100644 (file)
@@ -1626,19 +1626,28 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
 
   /* VSX registers that overlap the FPR registers are larger than for non-VSX
      implementations.  Don't allow an item to be split between a FP register
-     and an Altivec register.  */
-  if (VECTOR_MEM_VSX_P (mode))
+     and an Altivec register.  Allow TImode in all VSX registers if the user
+     asked for it.  */
+  if (TARGET_VSX && VSX_REGNO_P (regno)
+      && (VECTOR_MEM_VSX_P (mode)
+         || (TARGET_VSX_SCALAR_FLOAT && mode == SFmode)
+         || (TARGET_VSX_SCALAR_DOUBLE && (mode == DFmode || mode == DImode))
+         || (TARGET_VSX_TIMODE && mode == TImode)))
     {
       if (FP_REGNO_P (regno))
        return FP_REGNO_P (last_regno);
 
       if (ALTIVEC_REGNO_P (regno))
-       return ALTIVEC_REGNO_P (last_regno);
-    }
+       {
+         if (mode == SFmode && !TARGET_UPPER_REGS_SF)
+           return 0;
 
-  /* Allow TImode in all VSX registers if the user asked for it.  */
-  if (mode == TImode && TARGET_VSX_TIMODE && VSX_REGNO_P (regno))
-    return 1;
+         if ((mode == DFmode || mode == DImode) && !TARGET_UPPER_REGS_DF)
+           return 0;
+
+         return ALTIVEC_REGNO_P (last_regno);
+       }
+    }
 
   /* The GPRs can hold any mode, but values bigger than one register
      cannot go past R31.  */
@@ -2385,13 +2394,17 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
       rs6000_constraints[RS6000_CONSTRAINT_wa] = VSX_REGS;
       rs6000_constraints[RS6000_CONSTRAINT_wd] = VSX_REGS;
       rs6000_constraints[RS6000_CONSTRAINT_wf] = VSX_REGS;
-      rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
 
       if (TARGET_VSX_TIMODE)
        rs6000_constraints[RS6000_CONSTRAINT_wt] = VSX_REGS;
 
-      rs6000_constraints[RS6000_CONSTRAINT_ws]
-       = (TARGET_UPPER_REGS_DF) ? VSX_REGS : FLOAT_REGS;
+      if (TARGET_UPPER_REGS_DF)
+       {
+         rs6000_constraints[RS6000_CONSTRAINT_ws] = VSX_REGS;
+         rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
+       }
+      else
+       rs6000_constraints[RS6000_CONSTRAINT_ws] = FLOAT_REGS;
     }
 
   /* Add conditional constraints based on various options, to allow us to
@@ -2411,12 +2424,16 @@ rs6000_init_hard_regno_mode_ok (bool global_init_p)
   if (TARGET_POWERPC64)
     rs6000_constraints[RS6000_CONSTRAINT_wr] = GENERAL_REGS;
 
-  if (TARGET_P8_VECTOR)
+  if (TARGET_P8_VECTOR && TARGET_UPPER_REGS_SF)
+    {
+      rs6000_constraints[RS6000_CONSTRAINT_wu] = ALTIVEC_REGS;
+      rs6000_constraints[RS6000_CONSTRAINT_wy] = VSX_REGS;
+      rs6000_constraints[RS6000_CONSTRAINT_ww] = VSX_REGS;
+    }
+  else if (TARGET_P8_VECTOR)
     {
-      rs6000_constraints[RS6000_CONSTRAINT_wv] = ALTIVEC_REGS;
-      rs6000_constraints[RS6000_CONSTRAINT_wy]
-       = rs6000_constraints[RS6000_CONSTRAINT_ww]
-       = (TARGET_UPPER_REGS_SF) ? VSX_REGS : FLOAT_REGS;
+      rs6000_constraints[RS6000_CONSTRAINT_wy] = FLOAT_REGS;
+      rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
     }
   else if (TARGET_VSX)
     rs6000_constraints[RS6000_CONSTRAINT_ww] = FLOAT_REGS;
index 9f749f9a591db1433283fdb44949c94b0ddb7838..3ab031622d6d1bcbbe3c310520e5fafb1600b2c2 100644 (file)
 (define_mode_attr f32_lr [(SF "f")              (SD "wz")])
 (define_mode_attr f32_lm [(SF "m")              (SD "Z")])
 (define_mode_attr f32_li [(SF "lfs%U1%X1 %0,%1") (SD "lfiwzx %0,%y1")])
-(define_mode_attr f32_lv [(SF "lxsspx %0,%y1")  (SD "lxsiwzx %0,%y1")])
+(define_mode_attr f32_lv [(SF "lxsspx %x0,%y1")         (SD "lxsiwzx %x0,%y1")])
 
 ; Definitions for store from 32-bit fpr register
 (define_mode_attr f32_sr [(SF "f")               (SD "wx")])
 (define_mode_attr f32_sm [(SF "m")               (SD "Z")])
 (define_mode_attr f32_si [(SF "stfs%U0%X0 %1,%0") (SD "stfiwx %1,%y0")])
-(define_mode_attr f32_sv [(SF "stxsspx %1,%y0")          (SD "stxsiwzx %1,%y0")])
+(define_mode_attr f32_sv [(SF "stxsspx %x1,%y0")  (SD "stxsiwzx %x1,%y0")])
 
 ; Definitions for 32-bit fpr direct move
 (define_mode_attr f32_dm [(SF "wn") (SD "wm")])
   "")
 
 (define_insn "*zero_extendsidi2_lfiwzx"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wm")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wz,!wu")
        (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r,r,Z,Z")))]
   "TARGET_POWERPC64 && TARGET_LFIWZX"
   "@
   "")
 
 (define_insn "*extendsidi2_lfiwax"
-  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wm")
+  [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,??wm,!wl,!wu")
        (sign_extend:DI (match_operand:SI 1 "lwa_operand" "m,r,r,Z,Z")))]
   "TARGET_POWERPC64 && TARGET_LFIWAX"
   "@
   "")
 
 (define_insn_and_split "*extendsfdf2_fpr"
-  [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d")
-       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
+  [(set (match_operand:DF 0 "gpc_reg_operand" "=d,?d,d,wy,?wy,wv")
+       (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m,0,wz,Z")))]
   "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT"
   "@
    #
    fmr %0,%1
-   lfs%U1%X1 %0,%1"
+   lfs%U1%X1 %0,%1
+   #
+   xxlor %x0,%x1,%x1
+   lxsspx %x0,%y1"
   "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
   [(const_int 0)]
 {
         (if_then_else
           (match_test "update_address_mem (operands[1], VOIDmode)")
           (const_string "fpload_u")
-          (const_string "fpload")))])])
+          (const_string "fpload")))
+       (const_string "fp")
+       (const_string "vecsimple")
+       (if_then_else
+       (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
+       (const_string "fpload_ux")
+       (if_then_else
+        (match_test "update_address_mem (operands[1], VOIDmode)")
+        (const_string "fpload_u")
+        (const_string "fpload")))])])
 
 (define_expand "truncdfsf2"
   [(set (match_operand:SF 0 "gpc_reg_operand" "")
 }")
 
 (define_insn "mov<mode>_hardfloat"
-  [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wm,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
-       (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wm,r,<f32_dm>,r,h,0,G,Fn"))]
+  [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,<f32_lr>,<f32_sm>,wu,Z,?<f32_dm>,?r,*c*l,!r,*h,!r,!r")
+       (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,<f32_lm>,<f32_sr>,Z,wu,r,<f32_dm>,r,h,0,G,Fn"))]
   "(gpc_reg_operand (operands[0], <MODE>mode)
    || gpc_reg_operand (operands[1], <MODE>mode))
    && (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)"
 ;; reloading.
 
 (define_insn "*mov<mode>_hardfloat32"
-  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,!r,!r,!r")
-       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,G,H,F"))]
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,!r,!r,!r")
+       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,G,H,F"))]
   "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT 
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
    lfd%U1%X1 %0,%1
    fmr %0,%1
    lxsd%U1x %x0,%y1
-   lxsd%U1x %x0,%y1
-   stxsd%U0x %x1,%y0
    stxsd%U0x %x1,%y0
    xxlor %x0,%x1,%x1
-   xxlor %x0,%x1,%x1
    xxlxor %x0,%x0,%x0
    #
    #
         (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
         (const_string "fpload_ux")
         (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (const_string "fpstore"))
        (if_then_else
         (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
         (const_string "fpstore_ux")
         (const_string "fpstore"))
        (const_string "vecsimple")
        (const_string "vecsimple")
-       (const_string "vecsimple")
        (const_string "store")
        (const_string "load")
        (const_string "two")
        (const_string "fp")
        (const_string "fp")
        (const_string "*")])
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,8,8,8,12,16")])
+   (set_attr "length" "4,4,4,4,4,4,4,8,8,8,8,12,16")])
 
 (define_insn "*mov<mode>_softfloat32"
   [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,r,r,r")
 ; ld/std require word-aligned displacements -> 'Y' constraint.
 ; List Y->r and r->Y before r->r for reload.
 (define_insn "*mov<mode>_hardfloat64"
-  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,ws,?wa,Z,?Z,ws,?wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
-       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,Z,ws,wa,ws,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
+  [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wm")
+       (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wm,r"))]
   "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT
    && (gpc_reg_operand (operands[0], <MODE>mode)
        || gpc_reg_operand (operands[1], <MODE>mode))"
    lfd%U1%X1 %0,%1
    fmr %0,%1
    lxsd%U1x %x0,%y1
-   lxsd%U1x %x0,%y1
-   stxsd%U0x %x1,%y0
    stxsd%U0x %x1,%y0
    xxlor %x0,%x1,%x1
-   xxlor %x0,%x1,%x1
    xxlxor %x0,%x0,%x0
    std%U0%X0 %1,%0
    ld%U1%X1 %0,%1
         (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
         (const_string "fpload_ux")
         (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[1], VOIDmode)")
-        (const_string "fpload_ux")
-        (const_string "fpload"))
-       (if_then_else
-        (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
-        (const_string "fpstore_ux")
-        (const_string "fpstore"))
        (if_then_else
         (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
         (const_string "fpstore_ux")
         (const_string "fpstore"))
        (const_string "vecsimple")
        (const_string "vecsimple")
-       (const_string "vecsimple")
        (if_then_else
         (match_test "update_indexed_address_mem (operands[0], VOIDmode)")
         (const_string "store_ux")
        (const_string "mffgpr")
        (const_string "mftgpr")
        (const_string "mffgpr")])
-   (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
+   (set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,4,4,8,12,16,4,4,4,4")])
 
 (define_insn "*mov<mode>_softfloat64"
   [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=Y,r,r,cl,r,r,r,r,*h")
 { rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
 
 (define_insn "*movdi_internal64"
-  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wa,?wa,r,*h,*h,?wa,r,?*wg,r,?*wm")
-       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wa,Z,wa,*h,r,0,O,*wg,r,*wm,r"))]
+  [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,?m,?*d,?*d,?Z,?wv,?wa,r,*h,*h,?wa,r,?*wg,r,?*wm")
+       (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,d,m,d,wv,Z,wa,*h,r,0,O,*wg,r,*wm,r"))]
   "TARGET_POWERPC64
    && (gpc_reg_operand (operands[0], DImode)
        || gpc_reg_operand (operands[1], DImode))"
index 2696aa2ea85e1f8488259a94a24d0ad2c3dc44f9..0543842af205a8102bcac73fa8d94b28e3dbd69f 100644 (file)
@@ -1,3 +1,8 @@
+2013-09-27  Michael Meissner  <meissner@linux.vnet.ibm.com>
+
+       * gcc.target/powerpc/p8vector-ldst.c: New test for -mupper-regs-sf
+       and -mupper-regs-df.
+
 2013-09-27  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/58551
diff --git a/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c b/gcc/testsuite/gcc.target/powerpc/p8vector-ldst.c
new file mode 100644 (file)
index 0000000..d0b3eb0
--- /dev/null
@@ -0,0 +1,42 @@
+/* { dg-do compile { target { powerpc*-*-* } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-mcpu=power8 -O2 -mupper-regs-df -mupper-regs-sf" } */
+
+float load_sf (float *p)
+{
+  float f = *p;
+  __asm__ ("# reg %x0" : "+v" (f));
+  return f;
+}
+
+double load_df (double *p)
+{
+  double d = *p;
+  __asm__ ("# reg %x0" : "+v" (d));
+  return d;
+}
+
+double load_dfsf (float *p)
+{
+  double d = (double) *p;
+  __asm__ ("# reg %x0" : "+v" (d));
+  return d;
+}
+
+void store_sf (float *p, float f)
+{
+  __asm__ ("# reg %x0" : "+v" (f));
+  *p = f;
+}
+
+void store_df (double *p, double d)
+{
+  __asm__ ("# reg %x0" : "+v" (d));
+  *p = d;
+}
+
+/* { dg-final { scan-assembler-times "lxsspx"  2 } } */
+/* { dg-final { scan-assembler-times "lxsdx"   1 } } */
+/* { dg-final { scan-assembler-times "stxsspx" 1 } } */
+/* { dg-final { scan-assembler-times "stxsdx"  1 } } */