pdp11-protos.h (pdp11_cannot_change_mode_class, [...]): Declare.

* config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
pdp11_secondary_memory_needed): Declare.
* config/pdp11/predicates.md (float_operand): New predicate.
* config/pdp11/pdp11.md (RETVAL_REGNUM): New constant.
(cbranchdf4, movdf): Change predicate.
(movsf): Handle FPU register case.
(truncdfsf2, extendsfdf2): Add FPU register case.
* config/pdp11/pdp11.c (TARGET_SECONDARY_RELOAD,
TARGET_REGISTER_MOVE_COST, TARGET_PREFERRED_RELOAD_CLASS,
TARGET_PREFERRED_OUTPUT_RELOAD_CLASS): Define.
(pdp11_register_move_cost): Update cost matrix.
(pdp11_cannot_change_mode_class, pdp11_preferred_reload_class,
pdp11_preferred_output_reload_class, pdp11_secondary_reload,
pdp11_secondary_memory_needed): New function.
(pdp11_return_in_memory): Add other float types.
* config/pdp11/pdp11.h (HARD_REGNO_MODE_OK): Add other float
types. 
(SECONDARY_MEMORY_NEEDED, CANNOT_CHANGE_MODE_CLASS): Define.
(PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS,
REGISTER_MOVE_COST): Delete.
(BASE_RETURN_VALUE_REG): Add other float types.

From-SVN: r166060
This commit is contained in:
Paul Koning 2010-10-29 14:32:59 +00:00 committed by Paul Koning
parent 1e4bf85b80
commit a01c666cc6
6 changed files with 201 additions and 54 deletions

View File

@ -1,3 +1,27 @@
2010-10-29 Paul Koning <pkoning@equallogic.com>
* config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
pdp11_secondary_memory_needed): Declare.
* config/pdp11/predicates.md (float_operand): New predicate.
* config/pdp11/pdp11.md (RETVAL_REGNUM): New constant.
(cbranchdf4, movdf): Change predicate.
(movsf): Handle FPU register case.
(truncdfsf2, extendsfdf2): Add FPU register case.
* config/pdp11/pdp11.c (TARGET_SECONDARY_RELOAD,
TARGET_REGISTER_MOVE_COST, TARGET_PREFERRED_RELOAD_CLASS,
TARGET_PREFERRED_OUTPUT_RELOAD_CLASS): Define.
(pdp11_register_move_cost): Update cost matrix.
(pdp11_cannot_change_mode_class, pdp11_preferred_reload_class,
pdp11_preferred_output_reload_class, pdp11_secondary_reload,
pdp11_secondary_memory_needed): New function.
(pdp11_return_in_memory): Add other float types.
* config/pdp11/pdp11.h (HARD_REGNO_MODE_OK): Add other float
types.
(SECONDARY_MEMORY_NEEDED, CANNOT_CHANGE_MODE_CLASS): Define.
(PREFERRED_RELOAD_CLASS, SECONDARY_RELOAD_CLASS,
REGISTER_MOVE_COST): Delete.
(BASE_RETURN_VALUE_REG): Add other float types.
2010-10-29 Nick Clifton<nickc@redhat.com>
* doc/invoke.texi: Document -mam34 and -mtune options.

View File

@ -31,7 +31,11 @@ extern const char *output_move_quad (rtx *);
extern const char *output_block_move (rtx *);
extern const char *output_jump (enum rtx_code, int, int);
extern void print_operand_address (FILE *, rtx);
extern int pdp11_register_move_cost (enum reg_class, enum reg_class);
extern bool pdp11_cannot_change_mode_class (enum machine_mode,
enum machine_mode, enum reg_class);
extern bool pdp11_secondary_memory_needed (reg_class_t, reg_class_t,
enum machine_mode);
#endif /* RTX_CODE */
extern void output_ascii (FILE *, const char *, int);

View File

@ -216,7 +216,17 @@ static const struct default_options pdp11_option_optimization_table[] =
#undef TARGET_TRAMPOLINE_INIT
#define TARGET_TRAMPOLINE_INIT pdp11_trampoline_init
struct gcc_target targetm = TARGET_INITIALIZER;
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD pdp11_secondary_reload
#undef TARGET_REGISTER_MOVE_COST
#define TARGET_REGISTER_MOVE_COST pdp11_register_move_cost
#undef TARGET_PREFERRED_RELOAD_CLASS
#define TARGET_PREFERRED_RELOAD_CLASS pdp11_preferred_reload_class
#undef TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
#define TARGET_PREFERRED_OUTPUT_RELOAD_CLASS pdp11_preferred_output_reload_class
/* Implement TARGET_HANDLE_OPTION. */
@ -417,7 +427,7 @@ pdp11_output_function_epilogue (FILE *stream, HOST_WIDE_INT size)
/* get ACs */
for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
if (df_regs_ever_live_p (i) && call_used_regs[i])
if (df_regs_ever_live_p (i) && ! call_used_regs[i])
via_ac = i;
for (i = AC5_REGNUM; i >= AC0_REGNUM; i--)
@ -1054,22 +1064,23 @@ static const int move_costs[N_REG_CLASSES][N_REG_CLASSES] =
/* NO MUL GEN LFPU NLFPU FPU ALL */
/* NO */ { 0, 0, 0, 0, 0, 0, 0},
/* MUL */ { 0, 2, 2, 10, 22, 22, 22},
/* GEN */ { 0, 2, 2, 10, 22, 22, 22},
/* LFPU */ { 0, 10, 10, 2, 2, 2, 10},
/* NLFPU */ { 0, 22, 22, 2, 2, 2, 22},
/* FPU */ { 0, 22, 22, 2, 2, 2, 22},
/* ALL */ { 0, 22, 22, 10, 22, 22, 22}
/* MUL */ { 0, 2, 2, 22, 22, 22, 22},
/* GEN */ { 0, 2, 2, 22, 22, 22, 22},
/* LFPU */ { 0, 22, 22, 2, 2, 2, 22},
/* NLFPU */ { 0, 22, 22, 2, 10, 10, 22},
/* FPU */ { 0, 22, 22, 2, 10, 10, 22},
/* ALL */ { 0, 22, 22, 22, 22, 22, 22}
} ;
/* -- note that some moves are tremendously expensive,
because they require lots of tricks! do we have to
charge the costs incurred by secondary reload class
-- as we do here with 22 -- or not ? */
-- as we do here with 10 -- or not ? */
int
pdp11_register_move_cost (enum reg_class c1, enum reg_class c2)
static int
pdp11_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
reg_class_t c1, reg_class_t c2)
{
return move_costs[(int)c1][(int)c2];
}
@ -1634,6 +1645,108 @@ legitimate_const_double_p (rtx address)
return 0;
}
/* Implement CANNOT_CHANGE_MODE_CLASS. */
bool
pdp11_cannot_change_mode_class (enum machine_mode from,
enum machine_mode to,
enum reg_class rclass)
{
/* Also, FPU registers contain a whole float value and the parts of
it are not separately accessible.
So we disallow all mode changes involving FPRs. */
if (FLOAT_MODE_P (from) != FLOAT_MODE_P (to))
return true;
return reg_classes_intersect_p (FPU_REGS, rclass);
}
/* TARGET_PREFERRED_RELOAD_CLASS
Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class.
loading is easier into LOAD_FPU_REGS than FPU_REGS! */
static reg_class_t
pdp11_preferred_reload_class (rtx x, reg_class_t class)
{
if (class == FPU_REGS)
return LOAD_FPU_REGS;
if (class == ALL_REGS)
{
if (FLOAT_MODE_P (GET_MODE (x)))
return LOAD_FPU_REGS;
else
return GENERAL_REGS;
}
return class;
}
/* TARGET_PREFERRED_OUTPUT_RELOAD_CLASS
Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class.
loading is easier into LOAD_FPU_REGS than FPU_REGS! */
static reg_class_t
pdp11_preferred_output_reload_class (rtx x, reg_class_t class)
{
if (class == FPU_REGS)
return LOAD_FPU_REGS;
if (class == ALL_REGS)
{
if (FLOAT_MODE_P (GET_MODE (x)))
return LOAD_FPU_REGS;
else
return GENERAL_REGS;
}
return class;
}
/* TARGET_SECONDARY_RELOAD.
FPU registers AC4 and AC5 (class NO_LOAD_FPU_REGS) require an
intermediate register (AC0-AC3: LOAD_FPU_REGS). Everything else
can be loade/stored directly. */
reg_class_t
pdp11_secondary_reload (bool in_p ATTRIBUTE_UNUSED,
rtx x,
reg_class_t reload_class,
enum machine_mode reload_mode ATTRIBUTE_UNUSED,
secondary_reload_info *sri ATTRIBUTE_UNUSED)
{
if (reload_class != NO_LOAD_FPU_REGS || GET_CODE (x) != REG ||
REGNO_REG_CLASS (REGNO (x)) == LOAD_FPU_REGS)
return NO_REGS;
return LOAD_FPU_REGS;
}
/* Target routine to check if register to register move requires memory.
The answer is yes if we're going between general register and FPU
registers. The mode doesn't matter in making this check.
*/
bool
pdp11_secondary_memory_needed (reg_class_t c1, reg_class_t c2,
enum machine_mode mode ATTRIBUTE_UNUSED)
{
int fromfloat = (c1 == LOAD_FPU_REGS || c1 == NO_LOAD_FPU_REGS ||
c1 == FPU_REGS);
int tofloat = (c2 == LOAD_FPU_REGS || c2 == NO_LOAD_FPU_REGS ||
c2 == FPU_REGS);
return (fromfloat != tofloat);
}
/* A copy of output_addr_const modified for pdp11 expression syntax.
output_addr_const also gets called for %cDIGIT and %nDIGIT, which we don't
use, and for debugging output, which we don't support with this port either.
@ -1751,7 +1864,7 @@ pdp11_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
ac0 if DFmode and FPU present - compatibility problem with
libraries for non-floating point.... */
return (TYPE_MODE (type) == DImode
|| (TYPE_MODE (type) == DFmode && ! TARGET_AC0));
|| (FLOAT_MODE_P (TYPE_MODE (type)) && ! TARGET_AC0));
}
/* Worker function for TARGET_FUNCTION_VALUE.
@ -1854,3 +1967,5 @@ pdp11_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
? GET_MODE_SIZE (mode)
: int_size_in_bytes (type));
}
struct gcc_target targetm = TARGET_INITIALIZER;

View File

@ -215,15 +215,19 @@ extern const struct real_format pdp11_d_format;
/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
On the pdp, the cpu registers can hold any mode - check alignment
On the pdp, the cpu registers can hold any mode other than float
(because otherwise we may end up being asked to move from CPU to FPU
register, which isn't a valid operation on the PDP11).
For CPU registers, check alignment.
FPU can only hold DF - simplifies life!
FPU accepts SF and DF but actually holds a DF - simplifies life!
*/
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(((REGNO) <= PC_REGNUM)? \
((GET_MODE_BITSIZE(MODE) <= 16) \
|| (GET_MODE_BITSIZE(MODE) >= 32 && !((REGNO) & 1))) \
:(MODE) == DFmode)
|| (GET_MODE_BITSIZE(MODE) >= 32 && \
!((REGNO) & 1) && !FLOAT_MODE_P (MODE))) \
:FLOAT_MODE_P (MODE))
/* Value is 1 if it is a good idea to tie two pseudo registers
@ -322,18 +326,9 @@ enum reg_class { NO_REGS, MUL_REGS, GENERAL_REGS, LOAD_FPU_REGS, NO_LOAD_FPU_REG
#define IRA_COVER_CLASSES { GENERAL_REGS, FPU_REGS, LIM_REG_CLASSES }
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class.
loading is easier into LOAD_FPU_REGS than FPU_REGS! */
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
(((CLASS) != FPU_REGS)?(CLASS):LOAD_FPU_REGS)
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,x) \
(((CLASS) == NO_LOAD_FPU_REGS && !(REG_P(x) && LOAD_FPU_REG_P(REGNO(x))))?LOAD_FPU_REGS:NO_REGS)
/* Hook for testing if memory is needed for moving between registers. */
#define SECONDARY_MEMORY_NEEDED(class1, class2, m) \
pdp11_secondary_memory_needed (class1, class2, m)
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS. */
@ -343,6 +338,8 @@ loading is easier into LOAD_FPU_REGS than FPU_REGS! */
1 \
)
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
pdp11_cannot_change_mode_class (FROM, TO, CLASS)
/* Stack layout; function entry, exit and calling. */
@ -386,7 +383,7 @@ extern int current_first_parm_offset;
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0. */
#define BASE_RETURN_VALUE_REG(MODE) \
((MODE) == DFmode ? 8 : 0)
(FLOAT_MODE_P (MODE) ? AC0_REGNUM : RETVAL_REGNUM)
/* 1 if N is a possible register number for function argument passing.
- not used on pdp */
@ -674,10 +671,6 @@ extern int may_call_alloca;
/* #define NO_FUNCTION_CSE */
/* cost of moving one register class to another */
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
pdp11_register_move_cost (CLASS1, CLASS2)
/* Tell emit-rtl.c how to initialize special values on a per-function base. */
extern struct rtx_def *cc0_reg_rtx;

View File

@ -25,6 +25,7 @@
(define_constants
[
;; Register numbers
(RETVAL_REGNUM 0)
(FRAME_POINTER_REGNUM 5)
(STACK_POINTER_REGNUM 6)
(PC_REGNUM 7)
@ -196,7 +197,7 @@
(define_expand "cbranchdf4"
[(set (cc0)
(compare (match_operand:DF 1 "general_operand")
(match_operand:DF 2 "general_operand")))
(match_operand:DF 2 "register_or_const0_operand")))
(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
[(cc0) (const_int 0)])
@ -318,11 +319,9 @@
}"
[(set_attr "length" "2,4,4,6")])
;; do we have to supply all these moves? e.g. to
;; NO_LOAD_FPU_REGs ?
(define_insn "movdf"
[(set (match_operand:DF 0 "general_operand" "=a,fR,a,Q,g")
(match_operand:DF 1 "general_operand" "fFR,a,Q,a,g"))]
[(set (match_operand:DF 0 "float_operand" "=a,fR,a,Q,g")
(match_operand:DF 1 "float_operand" "fFR,a,Q,a,g"))]
"TARGET_FPU"
"* if (which_alternative ==0 || which_alternative == 2)
return \"ldd %1, %0\";
@ -334,11 +333,17 @@
[(set_attr "length" "2,2,10,10,32")])
(define_insn "movsf"
[(set (match_operand:SF 0 "general_operand" "=g,r,g")
(match_operand:SF 1 "general_operand" "r,rmF,g"))]
[(set (match_operand:SF 0 "float_operand" "=a,fR,a,Q,g")
(match_operand:SF 1 "float_operand" "fFR,a,Q,a,g"))]
"TARGET_FPU"
"* return output_move_double (operands);"
[(set_attr "length" "16,16,16")])
"* if (which_alternative ==0 || which_alternative == 2)
return \"{ldcfd|movof} %1, %0\";
else if (which_alternative == 1 || which_alternative == 3)
return \"{stcdf|movfo} %1, %0\";
else
return output_move_double (operands); "
;; just a guess..
[(set_attr "length" "2,2,10,10,16")])
;; maybe fiddle a bit with move_ratio, then
;; let constraints only accept a register ...
@ -386,15 +391,11 @@
;;- truncation instructions
(define_insn "truncdfsf2"
[(set (match_operand:SF 0 "general_operand" "=r,R,Q")
(float_truncate:SF (match_operand:DF 1 "register_operand" "a,a,a")))]
[(set (match_operand:SF 0 "general_operand" "=f,R,Q")
(float_truncate:SF (match_operand:DF 1 "register_operand" "f,a,a")))]
"TARGET_FPU"
"* if (which_alternative ==0)
{
output_asm_insn(\"{stcdf|movfo} %1, -(sp)\", operands);
output_asm_insn(\"mov (sp)+, %0\", operands);
operands[0] = gen_rtx_REG (HImode, REGNO (operands[0])+1);
output_asm_insn(\"mov (sp)+, %0\", operands);
return \"\";
}
else if (which_alternative == 1)
@ -402,7 +403,7 @@
else
return \"{stcdf|movfo} %1, %0\";
"
[(set_attr "length" "6,2,4")])
[(set_attr "length" "0,2,4")])
(define_expand "truncsihi2"
@ -439,14 +440,14 @@
;;- sign extension instructions
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=a,a,a")
(float_extend:DF (match_operand:SF 1 "general_operand" "r,R,Q")))]
[(set (match_operand:DF 0 "register_operand" "=f,a,a")
(float_extend:DF (match_operand:SF 1 "general_operand" "f,R,Q")))]
"TARGET_FPU"
"@
mov %1, -(sp)\;{ldcfd|movof} (sp)+,%0
/* nothing */
{ldcfd|movof} %1, %0
{ldcfd|movof} %1, %0"
[(set_attr "length" "4,2,4")])
[(set_attr "length" "0,2,4")])
;; does movb sign extend in register-to-register move?
(define_insn "extendqihi2"
@ -856,6 +857,7 @@
}"
[(set_attr "length" "4,8,8,12,4,4,8,6,6,12")])
;; FIXME This definition is wrong, PR/41822
(define_insn "andhi3"
[(set (match_operand:HI 0 "general_operand" "=rR,rR,Q,Q")
(and:HI (match_operand:HI 1 "general_operand" "0,0,0,0")

View File

@ -35,3 +35,12 @@
sh = INTVAL (op);
return (abs (sh) > 1 && abs (sh) <= 4);
})
;; Accept anything general-operand accepts, except that registers must
;; be FPU registers.
(define_predicate "float_operand"
(if_then_else (match_code "reg")
(ior
(match_test "REGNO_REG_CLASS (REGNO (op)) == LOAD_FPU_REGS")
(match_test "REGNO_REG_CLASS (REGNO (op)) == NO_LOAD_FPU_REGS"))
(match_test "general_operand (op, mode)")))