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:
Ulrich Weigand 2003-06-27 21:10:17 +00:00 committed by Ulrich Weigand
parent 5bbd6c3ee0
commit dc65c307c8
7 changed files with 208 additions and 96 deletions

View file

@ -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

View file

@ -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 *));

View file

@ -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.

View file

@ -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))

View file

@ -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).

View file

@ -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

View 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);
}