Commit f3e9edff by Ulrich Weigand Committed by Ulrich Weigand

s390-protos.h (legitimize_la_operand, [...]): Add prototypes.

	* config/s390/s390-protos.h (legitimize_la_operand,
	s390_secondary_input_reload_class, s390_plus_operand,
	s390_expand_plus_operand): Add prototypes.

	config/s390/s390.c (s390_secondary_input_reload_class,
	s390_plus_operand, s390_expand_plus_operand): New functions.

	(struct s390_address): New member 'pointer'.
	(s390_decompose_address): Compute it.
	(legitimate_la_operand_p): Use it.
	(legitimize_la_operand): New function.
	(movti, movdi, movdf splitters): Call it.

	config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define.
	(PREDICATE_CODES): Add s390_plus_operand.

	config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete.
	(la_ccclobber): Allow GENERAL_REGS as output operand.

	(reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0,
	*reload_la_64, *reload_la_31 and splitters): Delete, replace by ...
	(*la_64, *la_31, reload_indi, reload_insi): ... these.

From-SVN: r49476
parent 3c9a08ec
2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390-protos.h (legitimize_la_operand,
s390_secondary_input_reload_class, s390_plus_operand,
s390_expand_plus_operand): Add prototypes.
config/s390/s390.c (s390_secondary_input_reload_class,
s390_plus_operand, s390_expand_plus_operand): New functions.
(struct s390_address): New member 'pointer'.
(s390_decompose_address): Compute it.
(legitimate_la_operand_p): Use it.
(legitimize_la_operand): New function.
(movti, movdi, movdf splitters): Call it.
config/s390/s390.h (SECONDARY_INPUT_RELOAD_CLASS): Define.
(PREDICATE_CODES): Add s390_plus_operand.
config/s390/s390.md (adddi3_inv_64, addaddr_ccclobber): Delete.
(la_ccclobber): Allow GENERAL_REGS as output operand.
(reload_load_address, *reload_load_address_reg_0, *la, *do_la_reg_0,
*reload_la_64, *reload_la_31 and splitters): Delete, replace by ...
(*la_64, *la_31, reload_indi, reload_insi): ... these.
2002-02-04 Ulrich Weigand <uweigand@de.ibm.com>
* gcc/config/s390/s390.h (CRT_CALL_STATIC_FUNCTION): Fixed
register names for regular asm () construct.
......
......@@ -48,6 +48,7 @@ extern int s390_match_ccmode PARAMS ((rtx, enum machine_mode));
extern enum machine_mode s390_select_ccmode PARAMS ((enum rtx_code, rtx, rtx));
extern int symbolic_reference_mentioned_p PARAMS ((rtx));
extern int legitimate_la_operand_p PARAMS ((rtx));
extern rtx legitimize_la_operand PARAMS ((rtx));
extern int legitimate_pic_operand_p PARAMS ((rtx));
extern int legitimate_constant_p PARAMS ((rtx));
extern int legitimate_reload_constant_p PARAMS ((rtx));
......@@ -55,6 +56,9 @@ extern int legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
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 int s390_plus_operand PARAMS ((rtx, enum machine_mode));
extern void s390_expand_plus_operand PARAMS ((rtx, rtx, rtx));
extern void emit_pic_move PARAMS ((rtx *, enum machine_mode));
extern void s390_output_symbolic_const PARAMS ((FILE *, rtx));
......
......@@ -103,6 +103,7 @@ struct s390_address
rtx base;
rtx indx;
rtx disp;
int pointer;
};
/* Structure containing information for prologue and epilogue. */
......@@ -1125,6 +1126,107 @@ s390_preferred_reload_class (op, class)
return class;
}
/* Return the register class of a scratch register needed to
load IN into a register of class CLASS in MODE.
We need a temporary when loading a PLUS expression which
is not a legitimate operand of the LOAD ADDRESS instruction. */
enum reg_class
s390_secondary_input_reload_class (class, mode, in)
enum reg_class class ATTRIBUTE_UNUSED;
enum machine_mode mode;
rtx in;
{
if (s390_plus_operand (in, mode))
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.
MODE is the current operation mode. */
int
s390_plus_operand (op, mode)
register rtx op;
enum machine_mode mode;
{
if (!check_mode (op, &mode) || mode != Pmode)
return FALSE;
if (GET_CODE (op) != PLUS)
return FALSE;
if (legitimate_la_operand_p (op))
return FALSE;
return TRUE;
}
/* Generate code to load SRC, which is PLUS that is not a
legitimate operand for the LA instruction, into TARGET.
SCRATCH may be used as scratch register. */
void
s390_expand_plus_operand (target, src, scratch)
register rtx target;
register rtx src;
register rtx scratch;
{
/* src must be a PLUS; get its two operands. */
rtx sum1, sum2;
if (GET_CODE (src) != PLUS || GET_MODE (src) != Pmode)
abort ();
sum1 = XEXP (src, 0);
sum2 = XEXP (src, 1);
/* If one of the two operands is equal to the target,
make it the first one. */
if (rtx_equal_p (target, sum2))
{
sum2 = XEXP (src, 0);
sum1 = XEXP (src, 1);
}
/* If the first operand is not an address register,
we reload it into the target. */
if (true_regnum (sum1) < 1 || true_regnum (sum1) > 15)
{
emit_move_insn (target, sum1);
sum1 = target;
}
/* Likewise for the second operand. However, take
care not to clobber the target if we already used
it for the first operand. Use the scratch instead. */
if (true_regnum (sum2) < 1 || true_regnum (sum2) > 15)
{
if (!rtx_equal_p (target, sum1))
{
emit_move_insn (target, sum2);
sum2 = target;
}
else
{
emit_move_insn (scratch, sum2);
sum2 = scratch;
}
}
/* Emit the LOAD ADDRESS pattern. Note that reload of PLUS
is only ever performed on addresses, so we can mark the
sum as legitimate for LA in any case. */
src = gen_rtx_PLUS (Pmode, sum1, sum2);
src = legitimize_la_operand (src);
emit_insn (gen_rtx_SET (VOIDmode, target, src));
}
/* Decompose a RTL expression ADDR for a memory address into
its components, returned in OUT. The boolean STRICT
specifies whether strict register checking applies.
......@@ -1145,6 +1247,7 @@ s390_decompose_address (addr, out, strict)
rtx base = NULL_RTX;
rtx indx = NULL_RTX;
rtx disp = NULL_RTX;
int pointer = FALSE;
/* Decompose address into base + index + displacement. */
......@@ -1198,6 +1301,7 @@ s390_decompose_address (addr, out, strict)
if (XVECLEN (base, 0) != 1 || XINT (base, 1) != 101)
return FALSE;
base = XVECEXP (base, 0, 0);
pointer = TRUE;
}
if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
......@@ -1206,6 +1310,16 @@ s390_decompose_address (addr, out, strict)
if ((strict && ! REG_OK_FOR_BASE_STRICT_P (base))
|| (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (base)))
return FALSE;
if (REGNO (base) == BASE_REGISTER
|| REGNO (base) == STACK_POINTER_REGNUM
|| REGNO (base) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
&& REGNO (base) == HARD_FRAME_POINTER_REGNUM)
|| (flag_pic
&& REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE;
}
/* Validate index register. */
......@@ -1216,6 +1330,7 @@ s390_decompose_address (addr, out, strict)
if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != 101)
return FALSE;
indx = XVECEXP (indx, 0, 0);
pointer = TRUE;
}
if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
......@@ -1224,6 +1339,16 @@ s390_decompose_address (addr, out, strict)
if ((strict && ! REG_OK_FOR_BASE_STRICT_P (indx))
|| (! strict && ! REG_OK_FOR_BASE_NONSTRICT_P (indx)))
return FALSE;
if (REGNO (indx) == BASE_REGISTER
|| REGNO (indx) == STACK_POINTER_REGNUM
|| REGNO (indx) == FRAME_POINTER_REGNUM
|| ((reload_completed || reload_in_progress)
&& frame_pointer_needed
&& REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
|| (flag_pic
&& REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
pointer = TRUE;
}
/* Validate displacement. */
......@@ -1244,6 +1369,8 @@ s390_decompose_address (addr, out, strict)
{
if (flag_pic != 1)
return FALSE;
pointer = TRUE;
}
/* We can convert literal pool addresses to
......@@ -1295,14 +1422,20 @@ s390_decompose_address (addr, out, strict)
if (offset)
disp = plus_constant (disp, offset);
pointer = TRUE;
}
}
if (!base && !indx)
pointer = TRUE;
if (out)
{
out->base = base;
out->indx = indx;
out->disp = disp;
out->pointer = pointer;
}
return TRUE;
......@@ -1332,28 +1465,36 @@ legitimate_la_operand_p (op)
if (!s390_decompose_address (op, &addr, FALSE))
return FALSE;
if (TARGET_64BIT)
if (TARGET_64BIT || addr.pointer)
return TRUE;
/* Use of the base or stack pointer implies address. */
return FALSE;
}
if (addr.base && GET_CODE (addr.base) == REG)
{
if (REGNO (addr.base) == BASE_REGISTER
|| REGNO (addr.base) == STACK_POINTER_REGNUM
|| REGNO (addr.base) == FRAME_POINTER_REGNUM)
return TRUE;
}
/* Return a modified variant of OP that is guaranteed to
be accepted by legitimate_la_operand_p. */
if (addr.indx && GET_CODE (addr.indx) == REG)
{
if (REGNO (addr.indx) == BASE_REGISTER
|| REGNO (addr.indx) == STACK_POINTER_REGNUM
|| REGNO (addr.base) == FRAME_POINTER_REGNUM)
return TRUE;
}
rtx
legitimize_la_operand (op)
register rtx op;
{
struct s390_address addr;
if (!s390_decompose_address (op, &addr, FALSE))
abort ();
return FALSE;
if (TARGET_64BIT || addr.pointer)
return op;
if (!addr.base)
abort ();
op = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr.base), 101);
if (addr.indx)
op = gen_rtx_PLUS (Pmode, op, addr.indx);
if (addr.disp)
op = gen_rtx_PLUS (Pmode, op, addr.disp);
return op;
}
/* Return a legitimate reference for ORIG (an address) using the
......
......@@ -577,6 +577,12 @@ extern enum reg_class regclass_map[FIRST_PSEUDO_REGISTER]; /* smalled class cont
(GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
(GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* We need a secondary reload when loading a PLUS which is
not a valid operand for LOAD ADDRESS. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, IN) \
s390_secondary_input_reload_class ((CLASS), (MODE), (IN))
/* If we are copying between FP registers and anything else, we need a memory
location. */
......@@ -1293,7 +1299,8 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
{"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \
{"load_multiple_operation", {PARALLEL}}, \
{"store_multiple_operation", {PARALLEL}}, \
{"const0_operand", { CONST_INT, CONST_DOUBLE }},
{"const0_operand", { CONST_INT, CONST_DOUBLE }}, \
{"s390_plus_operand", { PLUS }},
/* S/390 constant pool breaks the devices in crtstuff.c to control section
......
......@@ -867,7 +867,7 @@
[(set (match_dup 2) (match_dup 3))
(set (match_dup 0) (mem:TI (match_dup 2)))]
"operands[2] = operand_subword (operands[0], 1, 0, TImode);
operands[3] = XEXP (operands[1], 0);")
operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
;
; movdi instruction pattern(s).
......@@ -1022,7 +1022,7 @@
[(set (match_dup 2) (match_dup 3))
(set (match_dup 0) (mem:DI (match_dup 2)))]
"operands[2] = operand_subword (operands[0], 1, 0, DImode);
operands[3] = XEXP (operands[1], 0);")
operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
;
; movsi instruction pattern(s).
......@@ -1305,7 +1305,7 @@
[(set (match_dup 2) (match_dup 3))
(set (match_dup 0) (mem:DI (match_dup 2)))]
"operands[2] = operand_subword (operands[0], 1, 0, DFmode);
operands[3] = XEXP (operands[1], 0);")
operands[3] = legitimize_la_operand (XEXP (operands[1], 0));")
;
; movsf instruction pattern(s).
......@@ -3093,23 +3093,6 @@
[(set_attr "op_type" "RRE,RI,RXE")
(set_attr "atype" "reg,reg,mem")])
;
; For weakness of reload, need (set (reg x) (plus (reg y) (reg x)))
;
(define_insn "adddi3_inv_64"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
(plus:DI (match_operand:DI 1 "general_operand" "%d,K,m")
(match_operand:DI 2 "register_operand" "0,0,0") ) )
(clobber (reg:CC 33))]
"TARGET_64BIT"
"@
agr\\t%0,%1
aghi\\t%0,%h1
ag\\t%0,%1"
[(set_attr "op_type" "RRE,RI,RXE")
(set_attr "atype" "reg,reg,mem")])
(define_insn "adddi3_31"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(plus:DI (match_operand:DI 1 "register_operand" "0,0")
......@@ -3156,8 +3139,8 @@
DONE;
}")
(define_insn "reload_load_address"
[(set (match_operand:DI 0 "register_operand" "=a")
(define_insn "*la_64"
[(set (match_operand:DI 0 "register_operand" "=d")
(match_operand:QI 1 "address_operand" "p"))]
"TARGET_64BIT"
"la\\t%0,%a1"
......@@ -3165,65 +3148,24 @@
(set_attr "atype" "mem")
(set_attr "type" "la")])
(define_insn "*reload_load_address_reg_0"
[(set (match_operand:DI 0 "register_operand" "=d")
(plus:DI (match_operand:DI 1 "register_operand" "%0")
(match_operand:DI 2 "register_operand" "d")))]
(define_expand "reload_indi"
[(parallel [(match_operand:DI 0 "register_operand" "=a")
(match_operand:DI 1 "s390_plus_operand" "")
(match_operand:DI 2 "register_operand" "=&a")])]
"TARGET_64BIT"
"brxlg\\t%0,%2,.+6"
[(set_attr "op_type" "RIE")
(set_attr "atype" "reg")])
(define_insn "*reload_la_64"
[(set (match_operand:DI 0 "register_operand" "=d")
(plus:DI (match_operand:DI 1 "general_operand" "g")
(match_operand:DI 2 "general_operand" "g")))]
"TARGET_64BIT && reload_in_progress
&& !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
"#")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "general_operand" "")
(match_operand:DI 2 "register_operand" "")))]
"TARGET_64BIT && reload_completed
&& !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
"
{
if (CONSTANT_P (operands[1])
&& !legitimate_reload_constant_p (operands[1]))
operands[1] = force_const_mem (DImode, operands[1]);
s390_expand_plus_operand (operands[0], operands[1], operands[2]);
DONE;
}")
(define_split
[(set (match_operand:DI 0 "register_operand" "")
(plus:DI (match_operand:DI 1 "register_operand" "")
(match_operand:DI 2 "general_operand" "")))]
"TARGET_64BIT && reload_completed
&& !address_operand (gen_rtx_PLUS (DImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))]
"
{
if (CONSTANT_P (operands[2])
&& !legitimate_reload_constant_p (operands[2]))
operands[2] = force_const_mem (DImode, operands[2]);
}")
;
; addsi3 instruction pattern(s).
;
(define_insn "*la_ccclobber"
[(set (match_operand:SI 0 "register_operand" "=a")
[(set (match_operand:SI 0 "register_operand" "=d")
(match_operand:QI 1 "address_operand" "p"))
(clobber (reg:CC 33))]
"legitimate_la_operand_p (operands[1])"
......@@ -3232,23 +3174,6 @@
(set_attr "atype" "mem")
(set_attr "type" "la")])
(define_insn "*addaddr_ccclobber"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(plus:SI (match_operand:SI 1 "register_operand" "%a,a")
(match_operand:SI 2 "nonmemory_operand" "J,a")))
(clobber (reg:CC 33))]
"(((REGNO (operands[1]) == STACK_POINTER_REGNUM ) ||
(REGNO (operands[1]) == FRAME_POINTER_REGNUM ) ||
(REGNO (operands[1]) == BASE_REGISTER)) &&
(GET_CODE (operands[2]) == REG ||
CONST_OK_FOR_LETTER_P (INTVAL (operands[2]),'J')))"
"@
la\\t%0,%c2(,%1)
la\\t%0,0(%1,%2)"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")
(set_attr "type" "la")])
(define_insn "*addsi3_cc"
[(set (reg 33)
(compare (plus:SI (match_operand:SI 1 "register_operand" "%0,0")
......@@ -3301,67 +3226,24 @@
[(set_attr "op_type" "RR,RI,RX")
(set_attr "atype" "reg,reg,mem")])
(define_insn "*la"
[(set (match_operand:SI 0 "register_operand" "=a")
(define_insn "*la_31"
[(set (match_operand:SI 0 "register_operand" "=d")
(match_operand:QI 1 "address_operand" "p"))]
"reload_in_progress || reload_completed
|| legitimate_la_operand_p (operands[1])"
"legitimate_la_operand_p (operands[1])"
"la\\t%0,%a1"
[(set_attr "op_type" "RX")
(set_attr "atype" "mem")
(set_attr "type" "la")])
(define_insn "*do_la_reg_0"
[(set (match_operand:SI 0 "register_operand" "=d")
(plus:SI (match_operand:SI 1 "register_operand" "%0")
(match_operand:SI 2 "register_operand" "d")))]
"reload_in_progress || reload_completed"
"brxle\\t%0,%2,.+4"
[(set_attr "op_type" "RSI")
(set_attr "atype" "reg")])
(define_insn "*reload_la_31"
[(set (match_operand:SI 0 "register_operand" "=d")
(plus:SI (match_operand:SI 1 "general_operand" "g")
(match_operand:SI 2 "general_operand" "g")))]
"reload_in_progress
&& !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
"#")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "register_operand" "")))]
"reload_completed
&& !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
"
{
if (CONSTANT_P (operands[1])
&& !legitimate_reload_constant_p (operands[1]))
operands[1] = force_const_mem (SImode, operands[1]);
}")
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(plus:SI (match_operand:SI 1 "register_operand" "")
(match_operand:SI 2 "general_operand" "")))]
"reload_completed
&& !address_operand (gen_rtx_PLUS (SImode, operands[1], operands[2]), QImode)
&& !rtx_equal_p (operands[0], operands[1])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
(define_expand "reload_insi"
[(parallel [(match_operand:SI 0 "register_operand" "=a")
(match_operand:SI 1 "s390_plus_operand" "")
(match_operand:SI 2 "register_operand" "=&a")])]
"!TARGET_64BIT"
"
{
if (CONSTANT_P (operands[2])
&& !legitimate_reload_constant_p (operands[2]))
operands[2] = force_const_mem (SImode, operands[2]);
s390_expand_plus_operand (operands[0], operands[1], operands[2]);
DONE;
}")
......
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