s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
gcc/ChangeLog: * config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define. * config/s390/s390.c (s390_secondary_output_reload_class): New function. * config/s390/s390-protos.h (s390_secondary_output_reload_class): Declare it. * config/s390/s390.md ("reload_outti", "reload_outdi", "reload_outdf"): New expanders. * config/s390/s390.md ("movti" + splitters): Handle non-offsettable memory operands as source. ("movdi" + splitters): Likewise. ("movdf" + splitters): Likewise. * config/s390/s390.c (s390_split_ok_p): New function. * config/s390/s390-protos.h (s390_split_ok_p): Declare it. gcc/testsuite/ChangeLog: * gcc.dg/20030627-1.c: New test. From-SVN: r68607
This commit is contained in:
parent
5bbd6c3ee0
commit
dc65c307c8
7 changed files with 208 additions and 96 deletions
|
@ -1,3 +1,19 @@
|
|||
2003-06-27 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* config/s390/s390.h (SECONDARY_OUTPUT_RELOAD_CLASS): Define.
|
||||
* config/s390/s390.c (s390_secondary_output_reload_class): New function.
|
||||
* config/s390/s390-protos.h (s390_secondary_output_reload_class):
|
||||
Declare it.
|
||||
* config/s390/s390.md ("reload_outti", "reload_outdi",
|
||||
"reload_outdf"): New expanders.
|
||||
|
||||
* config/s390/s390.md ("movti" + splitters): Handle non-offsettable
|
||||
memory operands as source.
|
||||
("movdi" + splitters): Likewise.
|
||||
("movdf" + splitters): Likewise.
|
||||
* config/s390/s390.c (s390_split_ok_p): New function.
|
||||
* config/s390/s390-protos.h (s390_split_ok_p): Declare it.
|
||||
|
||||
2003-06-27 Kazu Hirata <kazu@cs.umass.edu>
|
||||
|
||||
* combine.c (force_to_mode): Replace the equality comparison
|
||||
|
|
|
@ -42,6 +42,7 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int));
|
|||
extern int s390_extract_hi PARAMS ((rtx, enum machine_mode, int));
|
||||
extern int s390_single_qi PARAMS ((rtx, enum machine_mode, int));
|
||||
extern int s390_extract_qi PARAMS ((rtx, enum machine_mode, int));
|
||||
extern bool s390_split_ok_p PARAMS ((rtx, rtx, enum machine_mode, int));
|
||||
extern int tls_symbolic_operand PARAMS ((rtx));
|
||||
|
||||
extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
|
||||
|
@ -60,6 +61,7 @@ extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
|
|||
extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode));
|
||||
extern enum reg_class s390_preferred_reload_class PARAMS ((rtx, enum reg_class));
|
||||
extern enum reg_class s390_secondary_input_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
|
||||
extern enum reg_class s390_secondary_output_reload_class PARAMS ((enum reg_class, enum machine_mode, rtx));
|
||||
extern int s390_plus_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
|
||||
extern void emit_symbolic_move PARAMS ((rtx *));
|
||||
|
|
|
@ -863,6 +863,42 @@ s390_extract_qi (op, mode, part)
|
|||
abort ();
|
||||
}
|
||||
|
||||
/* Check whether we can (and want to) split a double-word
|
||||
move in mode MODE from SRC to DST into two single-word
|
||||
moves, moving the subword FIRST_SUBWORD first. */
|
||||
|
||||
bool
|
||||
s390_split_ok_p (dst, src, mode, first_subword)
|
||||
rtx dst;
|
||||
rtx src;
|
||||
enum machine_mode mode;
|
||||
int first_subword;
|
||||
{
|
||||
/* Floating point registers cannot be split. */
|
||||
if (FP_REG_P (src) || FP_REG_P (dst))
|
||||
return false;
|
||||
|
||||
/* We don't need to split if operands are directly accessable. */
|
||||
if (s_operand (src, mode) || s_operand (dst, mode))
|
||||
return false;
|
||||
|
||||
/* Non-offsettable memory references cannot be split. */
|
||||
if ((GET_CODE (src) == MEM && !offsettable_memref_p (src))
|
||||
|| (GET_CODE (dst) == MEM && !offsettable_memref_p (dst)))
|
||||
return false;
|
||||
|
||||
/* Moving the first subword must not clobber a register
|
||||
needed to move the second subword. */
|
||||
if (register_operand (dst, mode))
|
||||
{
|
||||
rtx subreg = operand_subword (dst, first_subword, 0, mode);
|
||||
if (reg_overlap_mentioned_p (subreg, src))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* Change optimizations to be performed, depending on the
|
||||
optimization level.
|
||||
|
@ -1715,6 +1751,29 @@ s390_secondary_input_reload_class (class, mode, in)
|
|||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Return the register class of a scratch register needed to
|
||||
store a register of class CLASS in MODE into OUT:
|
||||
|
||||
We need a temporary when storing a double-word to a
|
||||
non-offsettable memory address. */
|
||||
|
||||
enum reg_class
|
||||
s390_secondary_output_reload_class (class, mode, out)
|
||||
enum reg_class class;
|
||||
enum machine_mode mode;
|
||||
rtx out;
|
||||
{
|
||||
if ((TARGET_64BIT ? mode == TImode
|
||||
: (mode == DImode || mode == DFmode))
|
||||
&& reg_classes_intersect_p (GENERAL_REGS, class)
|
||||
&& GET_CODE (out) == MEM
|
||||
&& !offsettable_memref_p (out)
|
||||
&& !s_operand (out, VOIDmode))
|
||||
return ADDR_REGS;
|
||||
|
||||
return NO_REGS;
|
||||
}
|
||||
|
||||
/* Return true if OP is a PLUS that is not a legitimate
|
||||
operand for the LA instruction.
|
||||
OP is the current operation.
|
||||
|
|
|
@ -460,6 +460,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
|
|||
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
|
||||
s390_secondary_input_reload_class ((CLASS), (MODE), (IN))
|
||||
|
||||
/* We need a secondary reload when storing a double-word
|
||||
to a non-offsettable memory address. */
|
||||
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, OUT) \
|
||||
s390_secondary_output_reload_class ((CLASS), (MODE), (OUT))
|
||||
|
||||
/* We need secondary memory to move data between GPRs and FPRs. */
|
||||
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
|
||||
((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
|
||||
|
|
|
@ -905,7 +905,7 @@
|
|||
|
||||
(define_insn "movti"
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,o,Q")
|
||||
(match_operand:TI 1 "general_operand" "Q,d,dKo,d,Q"))]
|
||||
(match_operand:TI 1 "general_operand" "Q,d,dKm,d,Q"))]
|
||||
"TARGET_64BIT"
|
||||
"@
|
||||
lmg\\t%0,%N0,%1
|
||||
|
@ -920,36 +920,29 @@
|
|||
[(set (match_operand:TI 0 "nonimmediate_operand" "")
|
||||
(match_operand:TI 1 "general_operand" ""))]
|
||||
"TARGET_64BIT && reload_completed
|
||||
&& !s_operand (operands[0], VOIDmode)
|
||||
&& !s_operand (operands[1], VOIDmode)
|
||||
&& (register_operand (operands[0], VOIDmode)
|
||||
|| register_operand (operands[1], VOIDmode))
|
||||
&& (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
|
||||
operands[1])
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, TImode),
|
||||
operands[1]))"
|
||||
&& s390_split_ok_p (operands[0], operands[1], TImode, 0)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
"
|
||||
{
|
||||
if (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode),
|
||||
operands[1]))
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 0, 0, TImode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, TImode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, TImode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, TImode);
|
||||
}
|
||||
else
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, TImode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, TImode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, TImode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, TImode);
|
||||
}
|
||||
}")
|
||||
operands[2] = operand_subword (operands[0], 0, 0, TImode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, TImode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, TImode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, TImode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "")
|
||||
(match_operand:TI 1 "general_operand" ""))]
|
||||
"TARGET_64BIT && reload_completed
|
||||
&& s390_split_ok_p (operands[0], operands[1], TImode, 1)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, TImode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, TImode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, TImode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, TImode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:TI 0 "register_operand" "")
|
||||
|
@ -957,12 +950,23 @@
|
|||
"TARGET_64BIT && reload_completed
|
||||
&& !s_operand (operands[1], VOIDmode)"
|
||||
[(set (match_dup 0) (match_dup 1))]
|
||||
"
|
||||
{
|
||||
rtx addr = operand_subword (operands[0], 1, 0, TImode);
|
||||
s390_load_address (addr, XEXP (operands[1], 0));
|
||||
operands[1] = replace_equiv_address (operands[1], addr);
|
||||
}")
|
||||
})
|
||||
|
||||
(define_expand "reload_outti"
|
||||
[(parallel [(match_operand:TI 0 "memory_operand" "")
|
||||
(match_operand:TI 1 "register_operand" "d")
|
||||
(match_operand:DI 2 "register_operand" "=&a")])]
|
||||
"TARGET_64BIT"
|
||||
{
|
||||
s390_load_address (operands[2], XEXP (operands[0], 0));
|
||||
operands[0] = replace_equiv_address (operands[0], operands[2]);
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
;
|
||||
; movdi instruction pattern(s).
|
||||
|
@ -1044,7 +1048,7 @@
|
|||
|
||||
(define_insn "*movdi_31"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!m,Q")
|
||||
(match_operand:DI 1 "general_operand" "Q,d,dKo,d,*f,m,*f,Q"))]
|
||||
(match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,m,*f,Q"))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
lm\\t%0,%N0,%1
|
||||
|
@ -1062,53 +1066,54 @@
|
|||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(match_operand:DI 1 "general_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& !FP_REG_P (operands[0])
|
||||
&& !FP_REG_P (operands[1])
|
||||
&& !s_operand (operands[0], VOIDmode)
|
||||
&& !s_operand (operands[1], VOIDmode)
|
||||
&& (register_operand (operands[0], VOIDmode)
|
||||
|| register_operand (operands[1], VOIDmode))
|
||||
&& (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
|
||||
operands[1])
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DImode),
|
||||
operands[1]))"
|
||||
&& s390_split_ok_p (operands[0], operands[1], DImode, 0)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
"
|
||||
{
|
||||
if (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode),
|
||||
operands[1]))
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 0, 0, DImode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, DImode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, DImode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, DImode);
|
||||
}
|
||||
else
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, DImode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, DImode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, DImode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, DImode);
|
||||
}
|
||||
}")
|
||||
operands[2] = operand_subword (operands[0], 0, 0, DImode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, DImode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, DImode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, DImode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(match_operand:DI 1 "general_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& s390_split_ok_p (operands[0], operands[1], DImode, 1)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, DImode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, DImode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, DImode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, DImode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(match_operand:DI 1 "memory_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& !FP_REG_P (operands[0])
|
||||
&& !FP_REG_P (operands[1])
|
||||
&& !s_operand (operands[1], VOIDmode)"
|
||||
[(set (match_dup 0) (match_dup 1))]
|
||||
"
|
||||
{
|
||||
rtx addr = operand_subword (operands[0], 1, 0, DImode);
|
||||
s390_load_address (addr, XEXP (operands[1], 0));
|
||||
operands[1] = replace_equiv_address (operands[1], addr);
|
||||
}")
|
||||
})
|
||||
|
||||
(define_expand "reload_outdi"
|
||||
[(parallel [(match_operand:DI 0 "memory_operand" "")
|
||||
(match_operand:DI 1 "register_operand" "d")
|
||||
(match_operand:SI 2 "register_operand" "=&a")])]
|
||||
"!TARGET_64BIT"
|
||||
{
|
||||
s390_load_address (operands[2], XEXP (operands[0], 0));
|
||||
operands[0] = replace_equiv_address (operands[0], operands[2]);
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_peephole2
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
|
@ -1354,7 +1359,7 @@
|
|||
|
||||
(define_insn "*movdf_31"
|
||||
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,o,Q")
|
||||
(match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKo,d,Q"))]
|
||||
(match_operand:DF 1 "general_operand" "f,m,f,Q,d,dKm,d,Q"))]
|
||||
"!TARGET_64BIT"
|
||||
"@
|
||||
ldr\\t%0,%1
|
||||
|
@ -1372,53 +1377,54 @@
|
|||
[(set (match_operand:DF 0 "nonimmediate_operand" "")
|
||||
(match_operand:DF 1 "general_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& !FP_REG_P (operands[0])
|
||||
&& !FP_REG_P (operands[1])
|
||||
&& !s_operand (operands[0], VOIDmode)
|
||||
&& !s_operand (operands[1], VOIDmode)
|
||||
&& (register_operand (operands[0], VOIDmode)
|
||||
|| register_operand (operands[1], VOIDmode))
|
||||
&& (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
|
||||
operands[1])
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 1, 0, DFmode),
|
||||
operands[1]))"
|
||||
&& s390_split_ok_p (operands[0], operands[1], DFmode, 0)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
"
|
||||
{
|
||||
if (!register_operand (operands[0], VOIDmode)
|
||||
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode),
|
||||
operands[1]))
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 0, 0, DFmode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, DFmode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, DFmode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, DFmode);
|
||||
}
|
||||
else
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, DFmode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, DFmode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, DFmode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, DFmode);
|
||||
}
|
||||
}")
|
||||
operands[2] = operand_subword (operands[0], 0, 0, DFmode);
|
||||
operands[3] = operand_subword (operands[0], 1, 0, DFmode);
|
||||
operands[4] = operand_subword (operands[1], 0, 0, DFmode);
|
||||
operands[5] = operand_subword (operands[1], 1, 0, DFmode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DF 0 "nonimmediate_operand" "")
|
||||
(match_operand:DF 1 "general_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& s390_split_ok_p (operands[0], operands[1], DFmode, 1)"
|
||||
[(set (match_dup 2) (match_dup 4))
|
||||
(set (match_dup 3) (match_dup 5))]
|
||||
{
|
||||
operands[2] = operand_subword (operands[0], 1, 0, DFmode);
|
||||
operands[3] = operand_subword (operands[0], 0, 0, DFmode);
|
||||
operands[4] = operand_subword (operands[1], 1, 0, DFmode);
|
||||
operands[5] = operand_subword (operands[1], 0, 0, DFmode);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DF 0 "register_operand" "")
|
||||
(match_operand:DF 1 "memory_operand" ""))]
|
||||
"!TARGET_64BIT && reload_completed
|
||||
&& !FP_REG_P (operands[0])
|
||||
&& !FP_REG_P (operands[1])
|
||||
&& !s_operand (operands[1], VOIDmode)"
|
||||
[(set (match_dup 0) (match_dup 1))]
|
||||
"
|
||||
{
|
||||
rtx addr = operand_subword (operands[0], 1, 0, DFmode);
|
||||
s390_load_address (addr, XEXP (operands[1], 0));
|
||||
operands[1] = replace_equiv_address (operands[1], addr);
|
||||
}")
|
||||
})
|
||||
|
||||
(define_expand "reload_outdf"
|
||||
[(parallel [(match_operand:DF 0 "memory_operand" "")
|
||||
(match_operand:DF 1 "register_operand" "d")
|
||||
(match_operand:SI 2 "register_operand" "=&a")])]
|
||||
"!TARGET_64BIT"
|
||||
{
|
||||
s390_load_address (operands[2], XEXP (operands[0], 0));
|
||||
operands[0] = replace_equiv_address (operands[0], operands[2]);
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
;
|
||||
; movsf instruction pattern(s).
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2003-06-27 Ulrich Weigand <uweigand@de.ibm.com>
|
||||
|
||||
* gcc.dg/20030627-1.c: New test.
|
||||
|
||||
2003-06-26 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
PR c++/11332
|
||||
|
|
20
gcc/testsuite/gcc.dg/20030627-1.c
Normal file
20
gcc/testsuite/gcc.dg/20030627-1.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* This tests whether non-offsettable memory operands are reloaded
|
||||
correctly in certain corner cases on s390 targets. */
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=gnu89" } */
|
||||
|
||||
void test_inout (char *bd, int xd, char *bs, int xs)
|
||||
{
|
||||
*(long long *)(bd + xd + 4093) = *(long long *)(bs + xs + 4093);
|
||||
}
|
||||
|
||||
void test_in (char *bd, int xd, char *bs, int xs)
|
||||
{
|
||||
*(long long *)(bd + xd) = *(long long *)(bs + xs + 4093);
|
||||
}
|
||||
|
||||
void test_out (char *bd, int xd, char *bs, int xs)
|
||||
{
|
||||
*(long long *)(bd + xd + 4093) = *(long long *)(bs + xs);
|
||||
}
|
||||
|
Loading…
Add table
Reference in a new issue