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>
* 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))
......
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
......
/* 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