This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, committed] SPE frob code take 2 (PR target/27287)


	This is the second attempt to get the SPE "frob" code (patterns to
handle SUBREG) correct.

	In E500 double mode, DFmode is contained in a single GPR that can
hold a doubleword, while DImode is spread across the lower halves of two
GPRs.

	evmergehi moves the high part of each input operand into the
respective high and low parts of the output operand.  evmergelo moves the
low parts into the respective high and low parts.

	evmergehi is used to move the high part of a double into the low
part of a GPR int.  The low part can be moved directly and there
apparently is no need for the current evmergelo. Loading a DFmode from
memory into a punned DImode pair of registers is accomplished with two
loads.

	I suspect that frob_di_df needs a similar memory alternative and
corrected register_operand predicate, but I do not want to make too many
changes this late in stage3.  frob_df_di probably needs its predicate
fixed a well.

	This patch also removes %H, which does not mean "high".  %H is a
mask for shift counts and completely unrelated.

	Hopefully this is good enough for GCC 4.2 and, if there are no
problems, I will backport this to GCC 4.1.

Bootstrapped and regression tested on powerpc-ibm-aix5.2.0.0.
Bootstrapped with SPE e500_double configuration.

David


2006-09-11  Guenter Roeck  <guenter@roeck-us.net>
	    David Edelsohn  <edelsohn@gnu.org>

	PR target/27287
	* config/rs6000/spe.md (frob_df_di): Remove %H.
	(frob_di_df): Remove %H.  Change evmergelo to mr.
	(frob_di_df_2): Remove %H.  Change evldd to two loads.

Index: spe.md
===================================================================
--- spe.md	(revision 116807)
+++ spe.md	(working copy)
@@ -2200,24 +2200,41 @@
         (subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))]
   "TARGET_E500_DOUBLE"
   "@
-   evmergelo %0,%H1,%L1
+   evmergelo %0,%1,%L1
    evldd%X1 %0,%y1")
 
 (define_insn "*frob_di_df"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
         (subreg:DI (match_operand:DF 1 "input_operand" "r") 0))]
-  "TARGET_E500_DOUBLE" /*one of these can be an mr */
-  "evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1"
+  "TARGET_E500_DOUBLE"
+  "evmergehi %0,%1,%1\;mr %L0,%1"
   [(set_attr "length" "8")])
 
 (define_insn "*frob_di_df_2"
   [(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r,r") 0)
 	(match_operand:DF 1 "input_operand" "r,m"))]
   "TARGET_E500_DOUBLE"
-  "@
-   evmergehi %H0,%1,%1\;evmergelo %L0,%1,%1
-   evldd%X1 %0,%y1"
-  [(set_attr "length" "8,4")])
+  "*
+{
+  switch (which_alternative)
+    {
+    default: 
+      gcc_unreachable ();
+    case 0:
+      return \"evmergehi %0,%1,%1\;mr %L0,%1\";
+    case 1:
+      /* If the low-address word is used in the address, we must load
+	it last.  Otherwise, load it first.  Note that we cannot have
+	auto-increment in that case since the address register is
+	known to be dead.  */
+      if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+			     operands[1], 0))
+	return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
+      else
+        return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
+    }
+}"
+  [(set_attr "length" "8,8")])
 
 (define_insn "*mov_sidf_e500_subreg0"
   [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 0)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]