This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
E500 subreg fixes
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 22 Nov 2006 00:41:29 +0000 (UTC)
- Subject: E500 subreg fixes
When generating PowerPC E500 SPE code, there are various problems with
subregs associated with registers being 64 bits for some modes but 32 bits
for others, and various associated instruction patterns and restrictions
to address those problems.
Some of the patterns are restricted to DFmode in the TARGET_E500_DOUBLE
case, but would equally apply with vector modes in the TARGET_SPE case,
and are needed to avoid generic patterns such as movsi_internal1 getting
used with the high part of a 64-bit register, for which such generic
patterns will not work. This patch extends the patterns that store into
SImode subregs of 64-bit values to apply to the other modes, adds
corresponding patterns that load values from those subregs, and adds
memory alternatives. It makes invalid_e500_subreg detect the high-part
SImode subregs, and makes input_operand reject invalid subregs the same
way rs6000_nonimmediate_operand does.
Tested with no regressions with crosses to powerpc-none-linux-gnuspe
--enable-e500_double, mainline, 4.2 and 4.1. This fixes the following
test failures (in all three places):
FAIL: gcc.c-torture/execute/20050604-1.c execution, -O0
FAIL: gcc.c-torture/execute/pr23135.c execution, -O0
FAIL: gcc.dg/tree-ssa/gen-vect-25.c execution test
OK to commit to mainline, 4.2, 4.1?
2006-11-21 Joseph Myers <joseph@codesourcery.com>
* spe.md (SPE64): New mode macro.
(mov_sidf_e500_subreg0): Change to mov_si<mode>_e500_subreg0. Add
memory load.
(mov_si<mode>_e500_subreg0_2): New.
(mov_sidf_e500_subreg4): Change to mov_si<mode>_e500_subreg4. Add
memory load.
(mov_si<mode>_e500_subreg4_2): New.
* predicates.md (input_operand): Do not allow invalid E500
subregs.
(rs6000_nonimmediate_operand): Check for invalid E500 subregs also
if TARGET_SPE.
* rs6000.c (invalid_e500_subreg): Check for subregs involving
DFmode if TARGET_E500_DOUBLE. Check for subregs involving vector
modes if TARGET_SPE.
Index: spe.md
===================================================================
--- spe.md (revision 118968)
+++ spe.md (working copy)
@@ -32,6 +32,9 @@
(E500_CR_IOR_COMPARE 1012)
])
+;; Modes using a 64-bit register.
+(define_mode_macro SPE64 [DF V4HI V2SF V1DI V2SI])
+
(define_insn "*negsf2_gpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
(neg:SF (match_operand:SF 1 "gpc_reg_operand" "r")))]
@@ -2241,18 +2244,40 @@
}"
[(set_attr "length" "8,8")])
-(define_insn "*mov_sidf_e500_subreg0"
- [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 0)
- (match_operand:SI 1 "register_operand" "r"))]
- "TARGET_E500_DOUBLE"
- "evmergelo %0,%1,%0")
+(define_insn "*mov_si<mode>_e500_subreg0"
+ [(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,&r") 0)
+ (match_operand:SI 1 "input_operand" "r,m"))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ evmergelo %0,%1,%0
+ evmergelohi %0,%0,%0\;{l%U1%X1|lwz%U1%X1} %0,%1\;evmergelohi %0,%0,%0")
-(define_insn "*mov_sidf_e500_subreg4"
- [(set (subreg:SI (match_operand:DF 0 "register_operand" "+r") 4)
- (match_operand:SI 1 "register_operand" "r"))]
- "TARGET_E500_DOUBLE"
- "mr %0,%1")
+;; ??? Could use evstwwe for memory stores in some cases, depending on
+;; the offset.
+(define_insn "*mov_si<mode>_e500_subreg0_2"
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+ (subreg:SI (match_operand:SPE64 1 "register_operand" "+r,&r") 0))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ evmergehi %0,%0,%1
+ evmergelohi %1,%1,%1\;{st%U0%X0|stw%U0%X0} %1,%0")
+(define_insn "*mov_si<mode>_e500_subreg4"
+ [(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,r") 4)
+ (match_operand:SI 1 "input_operand" "r,m"))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ mr %0,%1
+ {l%U1%X1|lwz%U1%X1} %0,%1")
+
+(define_insn "*mov_si<mode>_e500_subreg4_2"
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+ (subreg:SI (match_operand:SPE64 1 "register_operand" "r,r") 4))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ mr %0,%1
+ {st%U0%X0|stw%U0%X0} %1,%0")
+
;; FIXME: Allow r=CONST0.
(define_insn "*movdf_e500_double"
[(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m")
Index: rs6000.c
===================================================================
--- rs6000.c (revision 118968)
+++ rs6000.c (working copy)
@@ -2713,20 +2713,31 @@
bool
invalid_e500_subreg (rtx op, enum machine_mode mode)
{
- /* Reject (subreg:SI (reg:DF)). */
- if (GET_CODE (op) == SUBREG
+ if (TARGET_E500_DOUBLE)
+ {
+ /* Reject (subreg:SI (reg:DF)). */
+ if (GET_CODE (op) == SUBREG
+ && mode == SImode
+ && REG_P (SUBREG_REG (op))
+ && GET_MODE (SUBREG_REG (op)) == DFmode)
+ return true;
+
+ /* Reject (subreg:DF (reg:DI)). */
+ if (GET_CODE (op) == SUBREG
+ && mode == DFmode
+ && REG_P (SUBREG_REG (op))
+ && GET_MODE (SUBREG_REG (op)) == DImode)
+ return true;
+ }
+
+ if (TARGET_SPE
+ && GET_CODE (op) == SUBREG
&& mode == SImode
&& REG_P (SUBREG_REG (op))
- && GET_MODE (SUBREG_REG (op)) == DFmode)
+ && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op)))
+ && SUBREG_BYTE (op) != 4)
return true;
- /* Reject (subreg:DF (reg:DI)). */
- if (GET_CODE (op) == SUBREG
- && mode == DFmode
- && REG_P (SUBREG_REG (op))
- && GET_MODE (SUBREG_REG (op)) == DImode)
- return true;
-
return false;
}
Index: predicates.md
===================================================================
--- predicates.md (revision 118968)
+++ predicates.md (working copy)
@@ -722,6 +722,12 @@
&& easy_vector_constant (op, mode))
return 1;
+ /* Do not allow invalid E500 subregs. */
+ if ((TARGET_E500_DOUBLE || TARGET_SPE)
+ && GET_CODE (op) == SUBREG
+ && invalid_e500_subreg (op, mode))
+ return 0;
+
/* For floating-point or multi-word mode, the only remaining valid type
is a register. */
if (SCALAR_FLOAT_MODE_P (mode)
@@ -756,7 +762,7 @@
(define_predicate "rs6000_nonimmediate_operand"
(match_code "reg,subreg,mem")
{
- if (TARGET_E500_DOUBLE
+ if ((TARGET_E500_DOUBLE || TARGET_SPE)
&& GET_CODE (op) == SUBREG
&& invalid_e500_subreg (op, mode))
return 0;
--
Joseph S. Myers
joseph@codesourcery.com