aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2003-08-23 00:17:35 +0000
committerUlrich Weigand <uweigand@gcc.gnu.org>2003-08-23 00:17:35 +0000
commit416cf582d382973bda9dd516b9044e60d107dd43 (patch)
tree38bcf08d7c2ad37558a5a82bec5bdd21862c3f61 /gcc
parent27a9da797e245696cf705795f81b20602e884792 (diff)
downloadgcc-416cf582d382973bda9dd516b9044e60d107dd43.zip
gcc-416cf582d382973bda9dd516b9044e60d107dd43.tar.gz
gcc-416cf582d382973bda9dd516b9044e60d107dd43.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog23
-rw-r--r--gcc/config/s390/s390-protos.h2
-rw-r--r--gcc/config/s390/s390.c144
-rw-r--r--gcc/config/s390/s390.md101
4 files changed, 93 insertions, 177 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85e8b87..cc8bd09 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,26 @@
+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.
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index c64e974..40026d3 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -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);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 55e5149..568a35b 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -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);
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 4376b38..d466409 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -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 "";
}