Commit dc65c307 by Ulrich Weigand Committed by Ulrich Weigand

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
parent 5bbd6c3e
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> 2003-06-27 Kazu Hirata <kazu@cs.umass.edu>
* combine.c (force_to_mode): Replace the equality comparison * combine.c (force_to_mode): Replace the equality comparison
......
...@@ -42,6 +42,7 @@ extern int s390_single_hi PARAMS ((rtx, enum machine_mode, int)); ...@@ -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_extract_hi PARAMS ((rtx, enum machine_mode, int));
extern int s390_single_qi 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 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 tls_symbolic_operand PARAMS ((rtx));
extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode)); extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
...@@ -60,6 +61,7 @@ extern rtx legitimize_pic_address PARAMS ((rtx, rtx)); ...@@ -60,6 +61,7 @@ extern rtx legitimize_pic_address PARAMS ((rtx, rtx));
extern rtx legitimize_address PARAMS ((rtx, rtx, enum machine_mode)); 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_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_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 int s390_plus_operand PARAMS ((rtx, enum machine_mode));
extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx)); extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
extern void emit_symbolic_move PARAMS ((rtx *)); extern void emit_symbolic_move PARAMS ((rtx *));
......
...@@ -863,6 +863,42 @@ s390_extract_qi (op, mode, part) ...@@ -863,6 +863,42 @@ s390_extract_qi (op, mode, part)
abort (); 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 /* Change optimizations to be performed, depending on the
optimization level. optimization level.
...@@ -1715,6 +1751,29 @@ s390_secondary_input_reload_class (class, mode, in) ...@@ -1715,6 +1751,29 @@ s390_secondary_input_reload_class (class, mode, in)
return NO_REGS; 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 /* Return true if OP is a PLUS that is not a legitimate
operand for the LA instruction. operand for the LA instruction.
OP is the current operation. OP is the current operation.
......
...@@ -460,6 +460,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; ...@@ -460,6 +460,11 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \ #define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
s390_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. */ /* We need secondary memory to move data between GPRs and FPRs. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \ #define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS)) ((CLASS1) != (CLASS2) && ((CLASS1) == FP_REGS || (CLASS2) == FP_REGS))
......
...@@ -905,7 +905,7 @@ ...@@ -905,7 +905,7 @@
(define_insn "movti" (define_insn "movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,Q,d,o,Q") [(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" "TARGET_64BIT"
"@ "@
lmg\\t%0,%N0,%1 lmg\\t%0,%N0,%1
...@@ -920,36 +920,29 @@ ...@@ -920,36 +920,29 @@
[(set (match_operand:TI 0 "nonimmediate_operand" "") [(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "general_operand" ""))] (match_operand:TI 1 "general_operand" ""))]
"TARGET_64BIT && reload_completed "TARGET_64BIT && reload_completed
&& !s_operand (operands[0], VOIDmode) && s390_split_ok_p (operands[0], operands[1], TImode, 0)"
&& !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]))"
[(set (match_dup 2) (match_dup 4)) [(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"
{ {
if (!register_operand (operands[0], VOIDmode) operands[2] = operand_subword (operands[0], 0, 0, TImode);
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, TImode), operands[3] = operand_subword (operands[0], 1, 0, TImode);
operands[1])) operands[4] = operand_subword (operands[1], 0, 0, TImode);
{ operands[5] = operand_subword (operands[1], 1, 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); (define_split
operands[5] = operand_subword (operands[1], 1, 0, TImode); [(set (match_operand:TI 0 "nonimmediate_operand" "")
} (match_operand:TI 1 "general_operand" ""))]
else "TARGET_64BIT && reload_completed
{ && s390_split_ok_p (operands[0], operands[1], TImode, 1)"
operands[2] = operand_subword (operands[0], 1, 0, TImode); [(set (match_dup 2) (match_dup 4))
operands[3] = operand_subword (operands[0], 0, 0, TImode); (set (match_dup 3) (match_dup 5))]
operands[4] = operand_subword (operands[1], 1, 0, TImode); {
operands[5] = operand_subword (operands[1], 0, 0, TImode); 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 (define_split
[(set (match_operand:TI 0 "register_operand" "") [(set (match_operand:TI 0 "register_operand" "")
...@@ -957,12 +950,23 @@ ...@@ -957,12 +950,23 @@
"TARGET_64BIT && reload_completed "TARGET_64BIT && reload_completed
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 1))]
"
{ {
rtx addr = operand_subword (operands[0], 1, 0, TImode); rtx addr = operand_subword (operands[0], 1, 0, TImode);
s390_load_address (addr, XEXP (operands[1], 0)); s390_load_address (addr, XEXP (operands[1], 0));
operands[1] = replace_equiv_address (operands[1], addr); 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). ; movdi instruction pattern(s).
...@@ -1044,7 +1048,7 @@ ...@@ -1044,7 +1048,7 @@
(define_insn "*movdi_31" (define_insn "*movdi_31"
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!m,Q") [(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" "!TARGET_64BIT"
"@ "@
lm\\t%0,%N0,%1 lm\\t%0,%N0,%1
...@@ -1062,53 +1066,54 @@ ...@@ -1062,53 +1066,54 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "") [(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))] (match_operand:DI 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& !FP_REG_P (operands[0]) && s390_split_ok_p (operands[0], operands[1], DImode, 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]))"
[(set (match_dup 2) (match_dup 4)) [(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"
{ {
if (!register_operand (operands[0], VOIDmode) operands[2] = operand_subword (operands[0], 0, 0, DImode);
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DImode), operands[3] = operand_subword (operands[0], 1, 0, DImode);
operands[1])) operands[4] = operand_subword (operands[1], 0, 0, DImode);
{ operands[5] = operand_subword (operands[1], 1, 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); (define_split
operands[5] = operand_subword (operands[1], 1, 0, DImode); [(set (match_operand:DI 0 "nonimmediate_operand" "")
} (match_operand:DI 1 "general_operand" ""))]
else "!TARGET_64BIT && reload_completed
{ && s390_split_ok_p (operands[0], operands[1], DImode, 1)"
operands[2] = operand_subword (operands[0], 1, 0, DImode); [(set (match_dup 2) (match_dup 4))
operands[3] = operand_subword (operands[0], 0, 0, DImode); (set (match_dup 3) (match_dup 5))]
operands[4] = operand_subword (operands[1], 1, 0, DImode); {
operands[5] = operand_subword (operands[1], 0, 0, DImode); 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 (define_split
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
(match_operand:DI 1 "memory_operand" ""))] (match_operand:DI 1 "memory_operand" ""))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& !FP_REG_P (operands[0]) && !FP_REG_P (operands[0])
&& !FP_REG_P (operands[1])
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 1))]
"
{ {
rtx addr = operand_subword (operands[0], 1, 0, DImode); rtx addr = operand_subword (operands[0], 1, 0, DImode);
s390_load_address (addr, XEXP (operands[1], 0)); s390_load_address (addr, XEXP (operands[1], 0));
operands[1] = replace_equiv_address (operands[1], addr); 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 (define_peephole2
[(set (match_operand:DI 0 "register_operand" "") [(set (match_operand:DI 0 "register_operand" "")
...@@ -1354,7 +1359,7 @@ ...@@ -1354,7 +1359,7 @@
(define_insn "*movdf_31" (define_insn "*movdf_31"
[(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,m,d,Q,d,o,Q") [(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" "!TARGET_64BIT"
"@ "@
ldr\\t%0,%1 ldr\\t%0,%1
...@@ -1372,53 +1377,54 @@ ...@@ -1372,53 +1377,54 @@
[(set (match_operand:DF 0 "nonimmediate_operand" "") [(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))] (match_operand:DF 1 "general_operand" ""))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& !FP_REG_P (operands[0]) && s390_split_ok_p (operands[0], operands[1], DFmode, 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]))"
[(set (match_dup 2) (match_dup 4)) [(set (match_dup 2) (match_dup 4))
(set (match_dup 3) (match_dup 5))] (set (match_dup 3) (match_dup 5))]
"
{ {
if (!register_operand (operands[0], VOIDmode) operands[2] = operand_subword (operands[0], 0, 0, DFmode);
|| !reg_overlap_mentioned_p (operand_subword (operands[0], 0, 0, DFmode), operands[3] = operand_subword (operands[0], 1, 0, DFmode);
operands[1])) operands[4] = operand_subword (operands[1], 0, 0, DFmode);
{ operands[5] = operand_subword (operands[1], 1, 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); (define_split
operands[5] = operand_subword (operands[1], 1, 0, DFmode); [(set (match_operand:DF 0 "nonimmediate_operand" "")
} (match_operand:DF 1 "general_operand" ""))]
else "!TARGET_64BIT && reload_completed
{ && s390_split_ok_p (operands[0], operands[1], DFmode, 1)"
operands[2] = operand_subword (operands[0], 1, 0, DFmode); [(set (match_dup 2) (match_dup 4))
operands[3] = operand_subword (operands[0], 0, 0, DFmode); (set (match_dup 3) (match_dup 5))]
operands[4] = operand_subword (operands[1], 1, 0, DFmode); {
operands[5] = operand_subword (operands[1], 0, 0, DFmode); 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 (define_split
[(set (match_operand:DF 0 "register_operand" "") [(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "memory_operand" ""))] (match_operand:DF 1 "memory_operand" ""))]
"!TARGET_64BIT && reload_completed "!TARGET_64BIT && reload_completed
&& !FP_REG_P (operands[0]) && !FP_REG_P (operands[0])
&& !FP_REG_P (operands[1])
&& !s_operand (operands[1], VOIDmode)" && !s_operand (operands[1], VOIDmode)"
[(set (match_dup 0) (match_dup 1))] [(set (match_dup 0) (match_dup 1))]
"
{ {
rtx addr = operand_subword (operands[0], 1, 0, DFmode); rtx addr = operand_subword (operands[0], 1, 0, DFmode);
s390_load_address (addr, XEXP (operands[1], 0)); s390_load_address (addr, XEXP (operands[1], 0));
operands[1] = replace_equiv_address (operands[1], addr); 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). ; movsf instruction pattern(s).
......
2003-06-27 Ulrich Weigand <uweigand@de.ibm.com>
* gcc.dg/20030627-1.c: New test.
2003-06-26 Mark Mitchell <mark@codesourcery.com> 2003-06-26 Mark Mitchell <mark@codesourcery.com>
PR c++/11332 PR c++/11332
......
/* 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);
}
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