Commit 416cf582 by Ulrich Weigand Committed by Ulrich Weigand

s390-protos.h (s390_output_pool_entry): Declare.

	* config/s390/s390-protos.h (s390_output_pool_entry): Declare.
	* config/s390/s390.c (gen_consttable): Remove.
	(s390_dump_pool): Use UNSPECV_POOL_ENTRY for pool entry insns.
	(s390_output_pool_entry): New function.
	* config/s390/s390.md (UNSPECV_POOL_QI, UNSPECV_POOL_HI,
	UNSPECV_POOL_SI, UNSPECV_POOL_DI, UNSPECV_POOL_TI,
	UNSPECV_POOL_SF, UNSPECV_POOL_DF): Remove, replace by ...
	(UNSPECV_POOL_ENTRY): ... this new constant.
	("consttable_qi", "consttable_hi", "consttable_si", "consttable_di",
	"consttable_ti", "consttable_sf", "consttable_df"): Remove ...
	("*pool_entry"): ... and replace by this new insn.
	("literal_pool_31"): Do not emit anchor label if pool empty.

	* config/s390/s390.c (struct machine_function): Add save_return_addr_p.
	(s390_optimize_prolog): Save RETURN_REGNUM if save_return_addr_p.
	(s390_fixup_clobbered_return_reg): Remove.
	(s390_reorg): Don't call s390_fixup_clobbered_return_reg.
	(s390_return_addr_rtx): Always retrieve return address from save area
	slot.  Use save_return_addr_p to force slot to be filled.
	(s390_emit_prologue): Remove has_hard_reg_initial_val test.

From-SVN: r70714
parent 27a9da79
2003-08-23 Ulrich Weigand <uweigand@de.ibm.com>
* config/s390/s390-protos.h (s390_output_pool_entry): Declare.
* config/s390/s390.c (gen_consttable): Remove.
(s390_dump_pool): Use UNSPECV_POOL_ENTRY for pool entry insns.
(s390_output_pool_entry): New function.
* config/s390/s390.md (UNSPECV_POOL_QI, UNSPECV_POOL_HI,
UNSPECV_POOL_SI, UNSPECV_POOL_DI, UNSPECV_POOL_TI,
UNSPECV_POOL_SF, UNSPECV_POOL_DF): Remove, replace by ...
(UNSPECV_POOL_ENTRY): ... this new constant.
("consttable_qi", "consttable_hi", "consttable_si", "consttable_di",
"consttable_ti", "consttable_sf", "consttable_df"): Remove ...
("*pool_entry"): ... and replace by this new insn.
("literal_pool_31"): Do not emit anchor label if pool empty.
* config/s390/s390.c (struct machine_function): Add save_return_addr_p.
(s390_optimize_prolog): Save RETURN_REGNUM if save_return_addr_p.
(s390_fixup_clobbered_return_reg): Remove.
(s390_reorg): Don't call s390_fixup_clobbered_return_reg.
(s390_return_addr_rtx): Always retrieve return address from save area
slot. Use save_return_addr_p to force slot to be filled.
(s390_emit_prologue): Remove has_hard_reg_initial_val test.
2003-08-22 Chris Demetriou <cgd@broadcom.com>
* config/mips/mips.h (MASK_FIX_SB1, TARGET_FIX_SB1): New defines.
......
......@@ -80,6 +80,8 @@ extern void s390_output_symbolic_const (FILE *, rtx);
extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
extern void s390_output_constant_pool (rtx, rtx);
extern void s390_output_pool_entry (FILE *, rtx, enum machine_mode,
unsigned int);
extern void s390_trampoline_template (FILE *);
extern void s390_initialize_trampoline (rtx, rtx, rtx);
extern rtx s390_gen_rtx_const_DI (int, int);
......
......@@ -189,6 +189,10 @@ struct machine_function GTY(())
/* Set, if some of the fprs 8-15 need to be saved (64 bit abi). */
int save_fprs_p;
/* Set if return address needs to be saved because the current
function uses __builtin_return_addr (0). */
bool save_return_addr_p;
/* Number of first and last gpr to be saved, restored. */
int first_save_gpr;
int first_restore_gpr;
......@@ -220,7 +224,6 @@ static void replace_constant_pool_ref (rtx *, rtx, rtx);
static rtx find_ltrel_base (rtx);
static void replace_ltrel_base (rtx *, rtx);
static void s390_optimize_prolog (int);
static bool s390_fixup_clobbered_return_reg (rtx);
static int find_unused_clobbered_reg (void);
static void s390_frame_info (void);
static rtx save_fpr (rtx, int, int);
......@@ -4049,11 +4052,6 @@ enum machine_mode constant_modes[NR_C_MODES] =
QImode
};
rtx (*gen_consttable[NR_C_MODES])(rtx) =
{
gen_consttable_ti, gen_consttable_df, gen_consttable_di, gen_consttable_sf, gen_consttable_si, gen_consttable_hi, gen_consttable_qi
};
struct constant
{
struct constant *next;
......@@ -4249,7 +4247,11 @@ s390_dump_pool (struct constant_pool *pool)
insn = emit_label_after (c->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
insn = emit_insn_after (gen_consttable[i] (value), insn);
value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i],
gen_rtvec (1, value),
UNSPECV_POOL_ENTRY);
insn = emit_insn_after (value, insn);
INSN_ADDRESSES_NEW (insn, -1);
}
......@@ -4717,6 +4719,46 @@ s390_output_constant_pool (rtx start_label, rtx end_label)
}
}
/* Output to FILE the constant pool entry EXP in mode MODE
with alignment ALIGN. */
void
s390_output_pool_entry (FILE *file, rtx exp, enum machine_mode mode,
unsigned int align)
{
REAL_VALUE_TYPE r;
switch (GET_MODE_CLASS (mode))
{
case MODE_FLOAT:
if (GET_CODE (exp) != CONST_DOUBLE)
abort ();
REAL_VALUE_FROM_CONST_DOUBLE (r, exp);
assemble_real (r, mode, align);
break;
case MODE_INT:
if (GET_CODE (exp) == CONST
|| GET_CODE (exp) == SYMBOL_REF
|| GET_CODE (exp) == LABEL_REF)
{
fputs (integer_asm_op (GET_MODE_SIZE (mode), TRUE), file);
s390_output_symbolic_const (file, exp);
fputc ('\n', file);
}
else
{
assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
}
break;
default:
abort ();
}
}
/* Rework the prolog/epilog to avoid saving/restoring
registers unnecessarily. If TEMP_REGNO is nonnegative,
it specifies the number of a caller-saved register used
......@@ -4742,8 +4784,11 @@ s390_optimize_prolog (int temp_regno)
regs_ever_live[BASE_REGISTER] = 1;
/* In non-leaf functions, the prolog/epilog code relies
on RETURN_REGNUM being saved in any case. */
if (!current_function_is_leaf)
on RETURN_REGNUM being saved in any case. We also need
to save the return register if __builtin_return_address (0)
was used in the current function. */
if (!current_function_is_leaf
|| cfun->machine->save_return_addr_p)
regs_ever_live[RETURN_REGNUM] = 1;
/* We need to save/restore the temporary register. */
......@@ -4868,68 +4913,11 @@ s390_optimize_prolog (int temp_regno)
}
}
/* Check whether any insn in the function makes use of the original
value of RETURN_REG (e.g. for __builtin_return_address).
If so, insert an insn reloading that value.
Return true if any such insn was found. */
static bool
s390_fixup_clobbered_return_reg (rtx return_reg)
{
bool replacement_done = 0;
rtx insn;
/* If we never called __builtin_return_address, register 14
might have been used as temp during the prolog; we do
not want to touch those uses. */
if (!has_hard_reg_initial_val (Pmode, REGNO (return_reg)))
return false;
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx reg, off, new_insn;
if (GET_CODE (insn) != INSN)
continue;
if (!reg_referenced_p (return_reg, PATTERN (insn)))
continue;
if (GET_CODE (PATTERN (insn)) == PARALLEL
&& store_multiple_operation (PATTERN (insn), VOIDmode))
continue;
if (frame_pointer_needed)
reg = hard_frame_pointer_rtx;
else
reg = stack_pointer_rtx;
off = GEN_INT (cfun->machine->frame_size + REGNO (return_reg) * UNITS_PER_WORD);
if (!DISP_IN_RANGE (INTVAL (off)))
{
off = force_const_mem (Pmode, off);
new_insn = gen_rtx_SET (Pmode, return_reg, off);
new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1);
off = return_reg;
}
new_insn = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, reg, off));
new_insn = gen_rtx_SET (Pmode, return_reg, new_insn);
new_insn = emit_insn_before (new_insn, insn);
INSN_ADDRESSES_NEW (new_insn, -1);
replacement_done = 1;
}
return replacement_done;
}
/* Perform machine-dependent processing. */
static void
s390_reorg (void)
{
bool fixed_up_clobbered_return_reg = 0;
rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
bool temp_used = 0;
......@@ -4985,21 +4973,6 @@ s390_reorg (void)
continue;
}
/* Check whether we have clobbered a use of the return
register (e.g. for __builtin_return_address). If so,
add insns reloading the register where necessary. */
if (temp_used && !fixed_up_clobbered_return_reg
&& s390_fixup_clobbered_return_reg (temp_reg))
{
fixed_up_clobbered_return_reg = 1;
/* The fixup insns might have caused a jump to overflow. */
if (pool_list)
s390_chunkify_cancel (pool_list);
continue;
}
/* If we made it up to here, both conditions are satisfied.
Finish up pool chunkification if required. */
if (pool_list)
......@@ -5021,13 +4994,13 @@ s390_return_addr_rtx (int count, rtx frame)
{
rtx addr;
/* For the current frame, we use the initial value of RETURN_REGNUM.
This works both in leaf and non-leaf functions. */
/* For the current frame, we need to make sure the initial
value of RETURN_REGNUM is actually saved. */
if (count == 0)
return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
cfun->machine->save_return_addr_p = true;
/* For frames farther back, we read the stack slot where the
/* To retrieve the return address we read the stack slot where the
corresponding RETURN_REGNUM value was saved. */
addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
......@@ -5343,7 +5316,6 @@ s390_emit_prologue (void)
See below for why TPF must use the register 1. */
if (!current_function_is_leaf
&& !has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
&& get_pool_size () < S390_POOL_CHUNK_MAX / 2
&& !TARGET_TPF)
temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
......
......@@ -92,13 +92,7 @@
(UNSPECV_POOL 200)
(UNSPECV_POOL_START 201)
(UNSPECV_POOL_END 202)
(UNSPECV_POOL_QI 203)
(UNSPECV_POOL_HI 204)
(UNSPECV_POOL_SI 205)
(UNSPECV_POOL_DI 206)
(UNSPECV_POOL_TI 207)
(UNSPECV_POOL_SF 208)
(UNSPECV_POOL_DF 209)
(UNSPECV_POOL_ENTRY 203)
(UNSPECV_MAIN_POOL 300)
; TLS support
......@@ -7058,88 +7052,19 @@
; Special literal pool access instruction pattern(s).
;
(define_insn "consttable_qi"
[(unspec_volatile [(match_operand:QI 0 "consttable_operand" "X")]
UNSPECV_POOL_QI)]
(define_insn "*pool_entry"
[(unspec_volatile [(match_operand 0 "consttable_operand" "X")]
UNSPECV_POOL_ENTRY)]
""
{
assemble_integer (operands[0], 1, BITS_PER_UNIT, 1);
enum machine_mode mode = GET_MODE (PATTERN (insn));
unsigned int align = GET_MODE_BITSIZE (mode);
s390_output_pool_entry (asm_out_file, operands[0], mode, align);
return "";
}
[(set_attr "op_type" "NN")
(set_attr "length" "1")])
(define_insn "consttable_hi"
[(unspec_volatile [(match_operand:HI 0 "consttable_operand" "X")]
UNSPECV_POOL_HI)]
""
{
assemble_integer (operands[0], 2, 2*BITS_PER_UNIT, 1);
return "";
}
[(set_attr "op_type" "NN")
(set_attr "length" "2")])
(define_insn "consttable_si"
[(unspec_volatile [(match_operand:SI 0 "consttable_operand" "X")]
UNSPECV_POOL_SI)]
""
".long\t%0"
[(set_attr "op_type" "NN")
(set_attr "length" "4")])
(define_insn "consttable_di"
[(unspec_volatile [(match_operand:DI 0 "consttable_operand" "X")]
UNSPECV_POOL_DI)]
""
".quad\t%0"
[(set_attr "op_type" "NN")
(set_attr "length" "8")])
(define_insn "consttable_ti"
[(unspec_volatile [(match_operand:TI 0 "consttable_operand" "X")]
UNSPECV_POOL_TI)]
""
{
assemble_integer (operands[0], 16, 16*BITS_PER_UNIT, 1);
return "";
}
[(set_attr "op_type" "NN")
(set_attr "length" "16")])
(define_insn "consttable_sf"
[(unspec_volatile [(match_operand:SF 0 "consttable_operand" "X")]
UNSPECV_POOL_SF)]
""
{
REAL_VALUE_TYPE r;
if (GET_CODE (operands[0]) != CONST_DOUBLE)
abort ();
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
assemble_real (r, SFmode, 4*BITS_PER_UNIT);
return "";
}
[(set_attr "op_type" "NN")
(set_attr "length" "4")])
(define_insn "consttable_df"
[(unspec_volatile [(match_operand:DF 0 "consttable_operand" "X")]
UNSPECV_POOL_DF)]
""
{
REAL_VALUE_TYPE r;
if (GET_CODE (operands[0]) != CONST_DOUBLE)
abort ();
REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]);
assemble_real (r, DFmode, 8*BITS_PER_UNIT);
return "";
}
[(set_attr "op_type" "NN")
(set_attr "length" "8")])
[(set_attr "op_type" "NN")
(set (attr "length")
(symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
(define_insn "pool_start_31"
[(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
......@@ -7239,12 +7164,6 @@
output_asm_insn ("bras\t%0,%2", operands);
s390_output_constant_pool (operands[1], operands[2]);
}
else if (flag_pic)
{
/* We need the anchor label in any case. */
(*targetm.asm_out.internal_label) (asm_out_file, "L",
CODE_LABEL_NUMBER (operands[1]));
}
return "";
}
......
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