Commit 2d5ca9a0 by John David Anglin Committed by John David Anglin

pa-protos.h (prefetch_operand): Delete.

	* pa-protos.h (prefetch_operand): Delete.
	(prefetch_cc_operand, prefetch_nocc_operand): New declations.
	* pa.c (prefetch_operand): Delete.
	(prefetch_cc_operand, prefetch_nocc_operand): New functions.
	* pa.h (EXTRA_CONSTRAINT): Add `W' constraint.
	(PREDICATE_CODES): Delete prefetch_operand.  Add prefetch_cc_operand
	and prefetch_nocc_operand.
	* pa.md (prefetch): Rework to avoid reload problems handling short
	displacements when a cache control completer needs to be provided.
	(prefetch_32, prefetch_64): Delete.
	(prefetch_cc, prefetch_nocc): New patterns.

From-SVN: r93702
parent 6a9836b1
2005-01-15 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* pa-protos.h (prefetch_operand): Delete.
(prefetch_cc_operand, prefetch_nocc_operand): New declations.
* pa.c (prefetch_operand): Delete.
(prefetch_cc_operand, prefetch_nocc_operand): New functions.
* pa.h (EXTRA_CONSTRAINT): Add `W' constraint.
(PREDICATE_CODES): Delete prefetch_operand. Add prefetch_cc_operand
and prefetch_nocc_operand.
* pa.md (prefetch): Rework to avoid reload problems handling short
displacements when a cache control completer needs to be provided.
(prefetch_32, prefetch_64): Delete.
(prefetch_cc, prefetch_nocc): New patterns.
2005-01-15 David Edelsohn <edelsohn@gnu.org> 2005-01-15 David Edelsohn <edelsohn@gnu.org>
* config/rs6000/aix52.h (CPLUSPLUS_CPP_SPEC): Revert previous change. * config/rs6000/aix52.h (CPLUSPLUS_CPP_SPEC): Revert previous change.
......
...@@ -79,7 +79,8 @@ extern int arith_operand (rtx, enum machine_mode); ...@@ -79,7 +79,8 @@ extern int arith_operand (rtx, enum machine_mode);
extern int read_only_operand (rtx, enum machine_mode); extern int read_only_operand (rtx, enum machine_mode);
extern int move_dest_operand (rtx, enum machine_mode); extern int move_dest_operand (rtx, enum machine_mode);
extern int move_src_operand (rtx, enum machine_mode); extern int move_src_operand (rtx, enum machine_mode);
extern int prefetch_operand (rtx, enum machine_mode); extern int prefetch_cc_operand (rtx, enum machine_mode);
extern int prefetch_nocc_operand (rtx, enum machine_mode);
extern int and_operand (rtx, enum machine_mode); extern int and_operand (rtx, enum machine_mode);
extern int ior_operand (rtx, enum machine_mode); extern int ior_operand (rtx, enum machine_mode);
extern int arith32_operand (rtx, enum machine_mode); extern int arith32_operand (rtx, enum machine_mode);
......
...@@ -752,24 +752,59 @@ move_src_operand (rtx op, enum machine_mode mode) ...@@ -752,24 +752,59 @@ move_src_operand (rtx op, enum machine_mode mode)
} }
/* Accept anything that can be used as the source operand for a prefetch /* Accept anything that can be used as the source operand for a prefetch
instruction. */ instruction with a cache-control completer. */
int int
prefetch_operand (rtx op, enum machine_mode mode) prefetch_cc_operand (rtx op, enum machine_mode mode)
{ {
if (GET_CODE (op) != MEM) if (GET_CODE (op) != MEM)
return 0; return 0;
op = XEXP (op, 0);
/* We must reject virtual registers as we don't allow REG+D. */
if (op == virtual_incoming_args_rtx
|| op == virtual_stack_vars_rtx
|| op == virtual_stack_dynamic_rtx
|| op == virtual_outgoing_args_rtx
|| op == virtual_cfa_rtx)
return 0;
if (!REG_P (op) && !IS_INDEX_ADDR_P (op))
return 0;
/* Until problems with management of the REG_POINTER flag are resolved, /* Until problems with management of the REG_POINTER flag are resolved,
we need to delay creating prefetch insns with unscaled indexed addresses we need to delay creating prefetch insns with unscaled indexed addresses
until CSE is not expected. */ until CSE is not expected. */
if (!TARGET_NO_SPACE_REGS if (!TARGET_NO_SPACE_REGS
&& !cse_not_expected && !cse_not_expected
&& GET_CODE (XEXP (op, 0)) == PLUS && GET_CODE (op) == PLUS
&& REG_P (XEXP (XEXP (op, 0), 0)) && REG_P (XEXP (op, 0)))
&& REG_P (XEXP (XEXP (op, 0), 1)))
return 0; return 0;
return memory_address_p (mode, XEXP (op, 0)); return memory_address_p (mode, op);
}
/* Accept anything that can be used as the source operand for a prefetch
instruction with no cache-control completer. */
int
prefetch_nocc_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) != MEM)
return 0;
op = XEXP (op, 0);
/* Until problems with management of the REG_POINTER flag are resolved,
we need to delay creating prefetch insns with unscaled indexed addresses
until CSE is not expected. */
if (!TARGET_NO_SPACE_REGS
&& !cse_not_expected
&& GET_CODE (op) == PLUS
&& REG_P (XEXP (op, 0))
&& REG_P (XEXP (op, 1)))
return 0;
return memory_address_p (mode, op);
} }
/* Accept REG and any CONST_INT that can be moved in one instruction into a /* Accept REG and any CONST_INT that can be moved in one instruction into a
......
...@@ -1296,7 +1296,12 @@ extern int may_call_alloca; ...@@ -1296,7 +1296,12 @@ extern int may_call_alloca;
`T' is for floating-point loads and stores. `T' is for floating-point loads and stores.
`U' is the constant 63. */ `U' is the constant 63.
`W' is a register indirect memory operand. We could allow short
displacements but GO_IF_LEGITIMATE_ADDRESS can't tell when a
long displacement is valid. This is only used for prefetch
instructions with the `sl' completer. */
#define EXTRA_CONSTRAINT(OP, C) \ #define EXTRA_CONSTRAINT(OP, C) \
((C) == 'Q' ? \ ((C) == 'Q' ? \
...@@ -1307,6 +1312,10 @@ extern int may_call_alloca; ...@@ -1307,6 +1312,10 @@ extern int may_call_alloca;
&& !symbolic_memory_operand (OP, VOIDmode) \ && !symbolic_memory_operand (OP, VOIDmode) \
&& !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)) \ && !IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0)) \
&& !IS_INDEX_ADDR_P (XEXP (OP, 0)))) \ && !IS_INDEX_ADDR_P (XEXP (OP, 0)))) \
: ((C) == 'W' ? \
(GET_CODE (OP) == MEM \
&& REG_P (XEXP (OP, 0)) \
&& REG_OK_FOR_BASE_P (XEXP (OP, 0))) \
: ((C) == 'A' ? \ : ((C) == 'A' ? \
(GET_CODE (OP) == MEM \ (GET_CODE (OP) == MEM \
&& IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))) \ && IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))) \
...@@ -1336,7 +1345,7 @@ extern int may_call_alloca; ...@@ -1336,7 +1345,7 @@ extern int may_call_alloca;
: ((C) == 'S' ? \ : ((C) == 'S' ? \
(GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) \ (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) \
: ((C) == 'U' ? \ : ((C) == 'U' ? \
(GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63) : 0)))))) (GET_CODE (OP) == CONST_INT && INTVAL (OP) == 63) : 0)))))))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
...@@ -2102,7 +2111,8 @@ forget_section (void) \ ...@@ -2102,7 +2111,8 @@ forget_section (void) \
CONST_DOUBLE}}, \ CONST_DOUBLE}}, \
{"move_dest_operand", {SUBREG, REG, MEM}}, \ {"move_dest_operand", {SUBREG, REG, MEM}}, \
{"move_src_operand", {SUBREG, REG, CONST_INT, MEM}}, \ {"move_src_operand", {SUBREG, REG, CONST_INT, MEM}}, \
{"prefetch_operand", {MEM}}, \ {"prefetch_cc_operand", {MEM}}, \
{"prefetch_nocc_operand", {MEM}}, \
{"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}}, \ {"reg_or_cint_move_operand", {SUBREG, REG, CONST_INT}}, \
{"pic_label_operand", {LABEL_REF, CONST}}, \ {"pic_label_operand", {LABEL_REF, CONST}}, \
{"fp_reg_operand", {REG}}, \ {"fp_reg_operand", {REG}}, \
......
...@@ -9283,134 +9283,88 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ...@@ -9283,134 +9283,88 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(match_operand 2 "const_int_operand" "")] (match_operand 2 "const_int_operand" "")]
"TARGET_PA_20" "TARGET_PA_20"
{ {
/* The PA 2.0 prefetch instructions only support short displacements int locality = INTVAL (operands[2]);
when a cache control completer needs to be supplied. Thus, we
can't use LO_SUM DLT addresses with the spatial locality completer. */
if (operands[2] == const0_rtx && IS_LO_SUM_DLT_ADDR_P (operands[0]))
FAIL;
/* We change operand0 to a MEM as we don't have the infrastructure to if (locality < 0 || locality > 3)
output all the supported address modes for ldw/ldd but we do have abort ();
it for MEMs. */
operands[0] = gen_rtx_MEM (Pmode, operands[0]);
if (!TARGET_NO_SPACE_REGS
&& !cse_not_expected
&& GET_CODE (XEXP (operands[0], 0)) == PLUS
&& REG_P (XEXP (XEXP (operands[0], 0), 0))
&& REG_P (XEXP (XEXP (operands[0], 0), 1)))
operands[0]
= replace_equiv_address (operands[0],
copy_to_mode_reg (Pmode,
XEXP (operands[0], 0)));
if (TARGET_64BIT) /* Change operand[0] to a MEM as we don't have the infrastructure
emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2])); to output all the supported address modes for ldw/ldd when we use
else the address directly. However, we do have it for MEMs. */
emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2])); operands[0] = gen_rtx_MEM (QImode, operands[0]);
DONE;
})
(define_insn "prefetch_64" /* If the address isn't valid for the prefetch, replace it. */
[(prefetch (match_operand:DI 0 "prefetch_operand" "A,RQ") if (locality)
(match_operand:DI 1 "const_int_operand" "n,n")
(match_operand:DI 2 "const_int_operand" "n,n"))]
"TARGET_64BIT
&& (operands[2] != const0_rtx
|| GET_CODE (XEXP (operands[0], 0)) != PLUS
|| GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != CONST_INT
|| INT_5_BITS (XEXP (XEXP (operands[0], 0), 1)))"
{
/* The SL completor indicates good spatial locality but poor temporal
locality. The ldw instruction with a target of general register 0
prefetches a cache line for a read. The ldd instruction prefetches
a cache line for a write. */
static const char * const instr[2][2][2] = {
{ {
{ if (!prefetch_nocc_operand (operands[0], QImode))
"", operands[0]
"ldw RT'%A0,%%r0", = replace_equiv_address (operands[0],
}, copy_to_mode_reg (Pmode,
{ XEXP (operands[0], 0)));
"", emit_insn (gen_prefetch_nocc (operands[0], operands[1], operands[2]));
"ldd RT'%A0,%%r0", }
}, else
},
{ {
{ if (!prefetch_cc_operand (operands[0], QImode))
"ldw%M0,sl %0,%%r0", operands[0]
"ldw%M0 %0,%%r0", = replace_equiv_address (operands[0],
}, copy_to_mode_reg (Pmode,
{ XEXP (operands[0], 0)));
"ldd%M0,sl %0,%%r0", emit_insn (gen_prefetch_cc (operands[0], operands[1], operands[2]));
"ldd%M0 %0,%%r0",
}
} }
DONE;
})
(define_insn "prefetch_cc"
[(prefetch (match_operand:QI 0 "prefetch_cc_operand" "RW")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))]
"TARGET_PA_20 && operands[2] == const0_rtx"
{
/* The SL cache-control completor indicates good spatial locality but
poor temporal locality. The ldw instruction with a target of general
register 0 prefetches a cache line for a read. The ldd instruction
prefetches a cache line for a write. */
static const char * const instr[2] = {
"ldw%M0,sl %0,%%r0",
"ldd%M0,sl %0,%%r0"
}; };
int read_or_write = INTVAL (operands[1]); int read_or_write = INTVAL (operands[1]);
int locality = INTVAL (operands[2]);
if ((which_alternative != 0 && which_alternative != 1) if (read_or_write < 0 || read_or_write > 1)
|| (read_or_write != 0 && read_or_write != 1)
|| (locality < 0 || locality > 3))
abort (); abort ();
if (which_alternative == 0 && locality == 0) return instr [read_or_write];
abort ();
return instr [which_alternative][read_or_write][locality == 0 ? 0 : 1];
} }
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "length" "4")]) (set_attr "length" "4")])
(define_insn "prefetch_32" (define_insn "prefetch_nocc"
[(prefetch (match_operand:SI 0 "prefetch_operand" "A,RQ") [(prefetch (match_operand:QI 0 "prefetch_nocc_operand" "A,RQ")
(match_operand:SI 1 "const_int_operand" "n,n") (match_operand:SI 1 "const_int_operand" "n,n")
(match_operand:SI 2 "const_int_operand" "n,n"))] (match_operand:SI 2 "const_int_operand" "n,n"))]
"TARGET_PA_20 "TARGET_PA_20 && operands[2] != const0_rtx"
&& (operands[2] != const0_rtx {
|| GET_CODE (XEXP (operands[0], 0)) != PLUS /* The ldw instruction with a target of general register 0 prefetches
|| GET_CODE (XEXP (XEXP (operands[0], 0), 1)) != CONST_INT a cache line for a read. The ldd instruction prefetches a cache line
|| INT_5_BITS (XEXP (XEXP (operands[0], 0), 1)))" for a write. */
{ static const char * const instr[2][2] = {
/* The SL completor indicates good spatial locality but poor temporal
locality. The ldw instruction with a target of general register 0
prefetches a cache line for a read. The ldd instruction prefetches
a cache line for a write. */
static const char * const instr[2][2][2] = {
{ {
{ "ldw RT'%A0,%%r0",
"", "ldd RT'%A0,%%r0",
"ldw RT'%A0,%%r0",
},
{
"",
"ldd RT'%A0,%%r0",
},
}, },
{ {
{ "ldw%M0 %0,%%r0",
"ldw%M0,sl %0,%%r0", "ldd%M0 %0,%%r0",
"ldw%M0 %0,%%r0",
},
{
"ldd%M0,sl %0,%%r0",
"ldd%M0 %0,%%r0",
}
} }
}; };
int read_or_write = INTVAL (operands[1]); int read_or_write = INTVAL (operands[1]);
int locality = INTVAL (operands[2]);
if ((which_alternative != 0 && which_alternative != 1) if ((which_alternative != 0 && which_alternative != 1)
|| (read_or_write != 0 && read_or_write != 1) || (read_or_write < 0 || read_or_write > 1))
|| (locality < 0 || locality > 3))
abort ();
if (which_alternative == 0 && locality == 0)
abort (); abort ();
return instr [which_alternative][read_or_write][locality == 0 ? 0 : 1]; return instr [which_alternative][read_or_write];
} }
[(set_attr "type" "load") [(set_attr "type" "load")
(set_attr "length" "4")]) (set_attr "length" "4")])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment