]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000.c (rs6000_split_altivec_in_gprs): New function.
authorHartmut Penner <hpenner@de.ibm.com>
Mon, 30 Jun 2003 13:30:45 +0000 (13:30 +0000)
committerHartmut Penner <hpenner@gcc.gnu.org>
Mon, 30 Jun 2003 13:30:45 +0000 (13:30 +0000)
2003-06-30 Hartmut Penner  <hpenner@de.ibm.com>

        * config/rs6000/rs6000.c (rs6000_split_altivec_in_gprs): New function.
        (altivec_in_gprs_p): New function.

* config/rs6000/rs6000-protos (rs6000_split_altivec_in_gprs): New
prototype.
(altivec_in_gprs_p): New prototype.

* config/rs6000/altivec.md (*movv4si_internal): Change
multi-assembler alternative to '#'. Add postreload splitter to
handle this cases.
(*movv4hi_internal): Likewise.
(*movv4qi_internal): Likewise.
(*movv4sf_internal): Likewise.

From-SVN: r68704

gcc/ChangeLog
gcc/config/rs6000/altivec.md
gcc/config/rs6000/rs6000-protos.h
gcc/config/rs6000/rs6000.c

index 9b559e5fb9f3c10ba8e1866fb3c30fd116bfe67c..b78d3d8aa9492bdaf3e3f399683f3d01a75a8837 100644 (file)
@@ -1,3 +1,19 @@
+2003-06-30 Hartmut Penner  <hpenner@de.ibm.com>
+
+        * config/rs6000/rs6000.c (rs6000_split_altivec_in_gprs): New function.
+        (altivec_in_gprs_p): New function.
+
+       * config/rs6000/rs6000-protos (rs6000_split_altivec_in_gprs): New 
+       prototype.
+       (altivec_in_gprs_p): New prototype.
+
+       * config/rs6000/altivec.md (*movv4si_internal): Change
+       multi-assembler alternative to '#'. Add postreload splitter to
+       handle this cases.
+       (*movv4hi_internal): Likewise.
+       (*movv4qi_internal): Likewise.
+       (*movv4sf_internal): Likewise.
+
 2003-06-30  Jason Merrill  <jason@redhat.com>
 
        * defaults.h (PUSH_ARGS_REVERSED): Define default here.
index d182744ab785697ad3a3fa1c026a78915dd988e4..5b1dc3692929e1a82cba3361b8226f481959ffe9 100644 (file)
     case 0: return \"stvx %1,%y0\";
     case 1: return \"lvx %0,%y1\";
     case 2: return \"vor %0,%1,%1\";
-    case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
-    case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
-    case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+    case 3: return \"#\";
+    case 4: return \"#\";
+    case 5: return \"#\";
     case 6: return output_vec_const_move (operands);
     default: abort();
     }
 }"
-  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
-   (set_attr "length" "*,*,*,16,16,16,*")])
+  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(define_split
+  [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+        (match_operand:V4SI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
+
+(define_split
+  [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+        (match_operand:V4SI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 6))
+   (set (match_dup 3) (match_dup 7))
+   (set (match_dup 4) (match_dup 8))
+   (set (match_dup 5) (match_dup 9))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
 
 (define_split
   [(set (match_operand:V4SI 0 "altivec_register_operand" "")
      case 0: return \"stvx %1,%y0\";
      case 1: return \"lvx %0,%y1\";
      case 2: return \"vor %0,%1,%1\";
-     case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
-     case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
-     case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+     case 3: return \"#\";
+     case 4: return \"#\";
+     case 5: return \"#\";
      case 6: return output_vec_const_move (operands);
      default: abort ();
      }
 }"
-  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
-   (set_attr "length" "*,*,*,16,16,16,*")])
+  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(define_split
+  [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+        (match_operand:V8HI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
+
+(define_split
+  [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+        (match_operand:V8HI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 6))
+   (set (match_dup 3) (match_dup 7))
+   (set (match_dup 4) (match_dup 8))
+   (set (match_dup 5) (match_dup 9))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
 
 (define_split
   [(set (match_operand:V8HI 0 "altivec_register_operand" "")
     case 0: return \"stvx %1,%y0\";
     case 1: return \"lvx %0,%y1\";
     case 2: return \"vor %0,%1,%1\";
-    case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
-    case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
-    case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+    case 3: return \"#\";
+    case 4: return \"#\";
+    case 5: return \"#\";
     case 6: return output_vec_const_move (operands);
     default: abort ();
     }
 }"
-  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
-   (set_attr "length" "*,*,*,16,16,16,*")])
+  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(define_split
+  [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+        (match_operand:V16QI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
+
+(define_split
+  [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+        (match_operand:V16QI 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 6))
+   (set (match_dup 3) (match_dup 7))
+   (set (match_dup 4) (match_dup 8))
+   (set (match_dup 5) (match_dup 9))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
 
 (define_split
   [(set (match_operand:V16QI 0 "altivec_register_operand" "")
     case 0: return \"stvx %1,%y0\";
     case 1: return \"lvx %0,%y1\";
     case 2: return \"vor %0,%1,%1\";
-    case 3: return \"stw%U0 %1,%0\;stw %L1,%L0\;stw %Y1,%Y0\;stw %Z1,%Z0\";
-    case 4: return \"lwz%U1 %0,%1\;lwz %L0,%L1\;lwz %Y0,%Y1\;lwz %Z0,%Z1\";
-    case 5: return \"mr %0,%1\;mr %L0,%L1\;mr %Y0,%Y1\;mr %Z0,%Z1\";
+    case 3: return \"#\";
+    case 4: return \"#\";
+    case 5: return \"#\";
     case 6: return output_vec_const_move (operands);
     default: abort ();
     }
 }"
-  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")
-   (set_attr "length" "*,*,*,16,16,16,*")])
+  [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+
+(define_split
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+        (match_operand:V4SF 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 4))
+   (set (match_dup 3) (match_dup 5))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
+
+(define_split
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+        (match_operand:V4SF 1 "input_operand" ""))]
+  "TARGET_ALTIVEC && reload_completed && !TARGET_POWERPC64 
+   && altivec_in_gprs_p (operands[0], operands[1])"
+  [(set (match_dup 2) (match_dup 6))
+   (set (match_dup 3) (match_dup 7))
+   (set (match_dup 4) (match_dup 8))
+   (set (match_dup 5) (match_dup 9))]
+"{
+     rs6000_split_altivec_in_gprs (operands);
+}")
 
 (define_insn "get_vrsave_internal"
   [(set (match_operand:SI 0 "register_operand" "=r")
index 051da0206a7ebf977c5d5ad7e2a47e0ca388355d..327ab1fa216caab3551104d659bedebec13eff6c 100644 (file)
@@ -101,6 +101,7 @@ extern int includes_rldic_lshift_p PARAMS ((rtx, rtx));
 extern int includes_rldicr_lshift_p PARAMS ((rtx, rtx));
 extern int registers_ok_for_quad_peep PARAMS ((rtx, rtx));
 extern int addrs_ok_for_quad_peep PARAMS ((rtx, rtx));
+extern int altivec_in_gprs_p (rtx, rtx);
 extern enum reg_class secondary_reload_class PARAMS ((enum reg_class,
                                                      enum machine_mode, rtx));
 extern int ccr_bit PARAMS ((rtx, int));
@@ -125,6 +126,7 @@ extern int mtcrf_operation PARAMS ((rtx, enum machine_mode));
 extern int lmw_operation PARAMS ((rtx, enum machine_mode));
 extern struct rtx_def *create_TOC_reference PARAMS ((rtx));
 extern void rs6000_emit_eh_toc_restore PARAMS ((rtx));
+extern void rs6000_split_altivec_in_gprs (rtx *);
 extern void rs6000_emit_move PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx rs6000_legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
 extern rtx rs6000_legitimize_reload_address PARAMS ((rtx, enum machine_mode,
index 524772b5ffe72ac37e8e8fc380d5989f8c4ce2cb..df5d775ee16ab38ec344c424a9d099393dcd487b 100644 (file)
@@ -2308,6 +2308,21 @@ small_data_operand (op, mode)
   return 0;
 #endif
 }
+
+/* Return 1 for all valid move insn operand combination involving altivec      
+   vectors in gprs.  */
+
+int
+altivec_in_gprs_p (rtx op0, rtx op1)
+{
+  if (REG_P (op0) && REGNO_REG_CLASS (REGNO (op0)) == GENERAL_REGS)
+    return 1;
+
+  if (REG_P (op1) && REGNO_REG_CLASS (REGNO (op1)) == GENERAL_REGS) 
+    return 1;
+  return 0;
+}
+
 \f
 /* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address.  */
 
@@ -9640,6 +9655,83 @@ rs6000_emit_minmax (dest, code, op0, op1)
   if (target != dest)
     emit_move_insn (dest, target);
 }
+
+/* Called by altivec splitter.
+   Input: 
+          operands[0] : Destination of move
+          operands[1] : Source of move
+         noperands   : Size of operands vector
+   Output:
+         operands[2-5] ([2-3] in 64 bit) : Destination slots
+         operands[6-9] ([4-5] in 64 bit) : Source slots
+
+   Splits the move of operands[1] to operands[0].
+   This is done, if GPRs are one of the operands.  In this case
+   a sequence of simple move insns has to be issued.  The sequence of these
+   move insns has to be done in correct order to avoid early clobber of the
+   base register or destructive overlap of registers. 
+*/
+         
+void
+rs6000_split_altivec_in_gprs (rtx *operands)
+{
+    int nregs, reg, i, j;
+  enum machine_mode mode; 
+
+  /* Calculate number to move (2/4 for 32/64 bit mode).  */ 
+
+  reg = REG_P (operands[0]) ? REGNO (operands[0]) : REGNO (operands[1]); 
+  mode = GET_MODE (operands[0]);
+  nregs = HARD_REGNO_NREGS (reg, mode);                                  
+  
+  if (REG_P (operands[1]) 
+      && REG_P (operands[0]) 
+      && (REGNO (operands[1]) < REGNO (operands[0])))
+    {  
+      /* Move register range backwards, if we have destructive overlap.  */
+
+      j = nregs;
+      for (i = 0; i < nregs; i++)
+        {
+          j--;
+          operands[i + 2] = operand_subword (operands[0], j, 0, mode);
+          operands[i + 2 + nregs] = 
+            operand_subword (operands[1], j, 0, mode);   
+        }
+    }     
+  else
+    {
+      j = -1;
+
+      if (GET_CODE (operands[1]) == MEM)
+        {
+          rtx breg;
+          /* We have offsettable addresses only. If we use one of the
+             registers to address memory, we have change that register last.  */            
+          breg = GET_CODE (XEXP (operands[1], 0)) == PLUS ?
+              XEXP (XEXP (operands[1], 0), 0) :
+              XEXP (operands[1], 0);
+
+          if (REGNO (breg) >= REGNO (operands[0]) 
+              && REGNO (breg) < REGNO (operands[0]) + nregs)
+              j = REGNO (breg) - REGNO (operands[0]);
+        }
+
+      for (i = 0; i < nregs; i++)
+        { 
+          /* Calculate index to next subword.  */
+          j++;
+          if (j == nregs) 
+            j = 0;
+
+          operands[i + 2] = operand_subword (operands[0], j, 0, mode);
+          operands[i + 2 + nregs] = 
+            operand_subword (operands[1], j, 0, mode);
+
+        }
+    }
+}
+
 \f
 /* This page contains routines that are used to determine what the
    function prologue and epilogue code will do and write them out.  */