aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn David Anglin <dave.anglin@nrc-cnrc.gc.ca>2005-01-15 18:57:29 +0000
committerJohn David Anglin <danglin@gcc.gnu.org>2005-01-15 18:57:29 +0000
commit2d5ca9a017f4ca590249b3bc987fc7c1803b00ee (patch)
treeb7d3dc9a86910317266f385ff932710e7f1ebca2
parent6a9836b1cd7bc1a599df3f8af8bf1f93a7b38e9c (diff)
downloadgcc-2d5ca9a017f4ca590249b3bc987fc7c1803b00ee.zip
gcc-2d5ca9a017f4ca590249b3bc987fc7c1803b00ee.tar.gz
gcc-2d5ca9a017f4ca590249b3bc987fc7c1803b00ee.tar.bz2
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
-rw-r--r--gcc/ChangeLog14
-rw-r--r--gcc/config/pa/pa-protos.h3
-rw-r--r--gcc/config/pa/pa.c47
-rw-r--r--gcc/config/pa/pa.h16
-rw-r--r--gcc/config/pa/pa.md156
5 files changed, 125 insertions, 111 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 48a6a76..81cfd92 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,17 @@
+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>
* config/rs6000/aix52.h (CPLUSPLUS_CPP_SPEC): Revert previous change.
diff --git a/gcc/config/pa/pa-protos.h b/gcc/config/pa/pa-protos.h
index a5bc024..bb49ca3 100644
--- a/gcc/config/pa/pa-protos.h
+++ b/gcc/config/pa/pa-protos.h
@@ -79,7 +79,8 @@ extern int arith_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_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 ior_operand (rtx, enum machine_mode);
extern int arith32_operand (rtx, enum machine_mode);
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index 58642d1..7d0dff5 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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
- instruction. */
+ instruction with a cache-control completer. */
int
-prefetch_operand (rtx op, enum machine_mode mode)
+prefetch_cc_operand (rtx op, enum machine_mode mode)
{
if (GET_CODE (op) != MEM)
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,
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 (XEXP (op, 0)) == PLUS
- && REG_P (XEXP (XEXP (op, 0), 0))
- && REG_P (XEXP (XEXP (op, 0), 1)))
+ && GET_CODE (op) == PLUS
+ && REG_P (XEXP (op, 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
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index 4507759..61a3325 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -1296,7 +1296,12 @@ extern int may_call_alloca;
`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) \
((C) == 'Q' ? \
@@ -1307,6 +1312,10 @@ extern int may_call_alloca;
&& !symbolic_memory_operand (OP, VOIDmode) \
&& !IS_LO_SUM_DLT_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' ? \
(GET_CODE (OP) == MEM \
&& IS_LO_SUM_DLT_ADDR_P (XEXP (OP, 0))) \
@@ -1336,7 +1345,7 @@ extern int may_call_alloca;
: ((C) == 'S' ? \
(GET_CODE (OP) == CONST_INT && INTVAL (OP) == 31) \
: ((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
@@ -2102,7 +2111,8 @@ forget_section (void) \
CONST_DOUBLE}}, \
{"move_dest_operand", {SUBREG, REG, 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}}, \
{"pic_label_operand", {LABEL_REF, CONST}}, \
{"fp_reg_operand", {REG}}, \
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index aa6d1ac..c79c982 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -9283,134 +9283,88 @@ add,l %2,%3,%3\;bv,n %%r0(%3)"
(match_operand 2 "const_int_operand" "")]
"TARGET_PA_20"
{
- /* The PA 2.0 prefetch instructions only support short displacements
- 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;
+ int locality = INTVAL (operands[2]);
- /* We change operand0 to a MEM as we don't have the infrastructure to
- output all the supported address modes for ldw/ldd but we do have
- 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 (locality < 0 || locality > 3)
+ abort ();
- if (TARGET_64BIT)
- emit_insn (gen_prefetch_64 (operands[0], operands[1], operands[2]));
- else
- emit_insn (gen_prefetch_32 (operands[0], operands[1], operands[2]));
- DONE;
-})
+ /* Change operand[0] to a MEM as we don't have the infrastructure
+ to output all the supported address modes for ldw/ldd when we use
+ the address directly. However, we do have it for MEMs. */
+ operands[0] = gen_rtx_MEM (QImode, operands[0]);
-(define_insn "prefetch_64"
- [(prefetch (match_operand:DI 0 "prefetch_operand" "A,RQ")
- (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 the address isn't valid for the prefetch, replace it. */
+ if (locality)
{
- {
- "",
- "ldw RT'%A0,%%r0",
- },
- {
- "",
- "ldd RT'%A0,%%r0",
- },
- },
+ if (!prefetch_nocc_operand (operands[0], QImode))
+ operands[0]
+ = 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]));
+ }
+ else
{
- {
- "ldw%M0,sl %0,%%r0",
- "ldw%M0 %0,%%r0",
- },
- {
- "ldd%M0,sl %0,%%r0",
- "ldd%M0 %0,%%r0",
- }
+ if (!prefetch_cc_operand (operands[0], QImode))
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_to_mode_reg (Pmode,
+ XEXP (operands[0], 0)));
+ emit_insn (gen_prefetch_cc (operands[0], operands[1], operands[2]));
}
+ 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 locality = INTVAL (operands[2]);
- if ((which_alternative != 0 && which_alternative != 1)
- || (read_or_write != 0 && read_or_write != 1)
- || (locality < 0 || locality > 3))
+ if (read_or_write < 0 || read_or_write > 1)
abort ();
- if (which_alternative == 0 && locality == 0)
- abort ();
-
- return instr [which_alternative][read_or_write][locality == 0 ? 0 : 1];
+ return instr [read_or_write];
}
[(set_attr "type" "load")
(set_attr "length" "4")])
-(define_insn "prefetch_32"
- [(prefetch (match_operand:SI 0 "prefetch_operand" "A,RQ")
+(define_insn "prefetch_nocc"
+ [(prefetch (match_operand:QI 0 "prefetch_nocc_operand" "A,RQ")
(match_operand:SI 1 "const_int_operand" "n,n")
(match_operand:SI 2 "const_int_operand" "n,n"))]
- "TARGET_PA_20
- && (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] = {
+ "TARGET_PA_20 && operands[2] != const0_rtx"
+{
+ /* 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] = {
{
- {
- "",
- "ldw RT'%A0,%%r0",
- },
- {
- "",
- "ldd RT'%A0,%%r0",
- },
+ "ldw RT'%A0,%%r0",
+ "ldd RT'%A0,%%r0",
},
{
- {
- "ldw%M0,sl %0,%%r0",
- "ldw%M0 %0,%%r0",
- },
- {
- "ldd%M0,sl %0,%%r0",
- "ldd%M0 %0,%%r0",
- }
+ "ldw%M0 %0,%%r0",
+ "ldd%M0 %0,%%r0",
}
};
int read_or_write = INTVAL (operands[1]);
- int locality = INTVAL (operands[2]);
if ((which_alternative != 0 && which_alternative != 1)
- || (read_or_write != 0 && read_or_write != 1)
- || (locality < 0 || locality > 3))
- abort ();
-
- if (which_alternative == 0 && locality == 0)
+ || (read_or_write < 0 || read_or_write > 1))
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 "length" "4")])