This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
S/390: Simplify literal pool overflow case further
- From: "Ulrich Weigand" <weigand at i1 dot informatik dot uni-erlangen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sat, 23 Aug 2003 02:23:33 +0200 (CEST)
- Subject: S/390: Simplify literal pool overflow case further
Hello,
this further simplifies the literal pool overflow case by removing
the s390_fixup_clobbered_return_reg hack; this can be done by always
loading the return address from its save area slot even for
__builtin_return_address (0).
The patch also merges the various consttable_ insns into a single
one, and removes a now superfluous special case in literal_pool_31.
Bootstrapped/regtested (both as-is and with artifically reduced
literal pool size) on s390-ibm-linux and s390x-ibm-linux.
Bye,
Ulrich
ChangeLog:
* 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.
Index: gcc/config/s390/s390-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390-protos.h,v
retrieving revision 1.35
diff -c -p -r1.35 s390-protos.h
*** gcc/config/s390/s390-protos.h 17 Aug 2003 10:00:03 -0000 1.35
--- gcc/config/s390/s390-protos.h 22 Aug 2003 17:54:19 -0000
*************** extern void s390_output_symbolic_const (
*** 80,85 ****
--- 80,87 ----
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);
Index: gcc/config/s390/s390.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.c,v
retrieving revision 1.107
diff -c -p -r1.107 s390.c
*** gcc/config/s390/s390.c 17 Aug 2003 10:00:03 -0000 1.107
--- gcc/config/s390/s390.c 22 Aug 2003 17:54:21 -0000
*************** struct machine_function GTY(())
*** 189,194 ****
--- 189,198 ----
/* 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;
*************** static void replace_constant_pool_ref (r
*** 220,226 ****
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);
--- 224,229 ----
*************** enum machine_mode constant_modes[NR_C_MO
*** 4049,4059 ****
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;
--- 4052,4057 ----
*************** s390_dump_pool (struct constant_pool *po
*** 4249,4255 ****
insn = emit_label_after (c->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
! insn = emit_insn_after (gen_consttable[i] (value), insn);
INSN_ADDRESSES_NEW (insn, -1);
}
--- 4247,4257 ----
insn = emit_label_after (c->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
!
! 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);
}
*************** s390_output_constant_pool (rtx start_lab
*** 4717,4722 ****
--- 4719,4764 ----
}
}
+ /* 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
*************** s390_optimize_prolog (int temp_regno)
*** 4742,4749 ****
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)
regs_ever_live[RETURN_REGNUM] = 1;
/* We need to save/restore the temporary register. */
--- 4784,4794 ----
regs_ever_live[BASE_REGISTER] = 1;
/* In non-leaf functions, the prolog/epilog code relies
! 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. */
*************** s390_optimize_prolog (int temp_regno)
*** 4868,4935 ****
}
}
- /* 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;
--- 4913,4923 ----
*************** s390_reorg (void)
*** 4985,5005 ****
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)
--- 4973,4978 ----
*************** s390_return_addr_rtx (int count, rtx fra
*** 5021,5033 ****
{
rtx addr;
! /* For the current frame, we use the initial value of RETURN_REGNUM.
! This works both in leaf and non-leaf functions. */
if (count == 0)
! return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
! /* For frames farther back, we read the stack slot where the
corresponding RETURN_REGNUM value was saved. */
addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
--- 4994,5006 ----
{
rtx addr;
! /* For the current frame, we need to make sure the initial
! value of RETURN_REGNUM is actually saved. */
if (count == 0)
! cfun->machine->save_return_addr_p = true;
! /* 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);
*************** s390_emit_prologue (void)
*** 5343,5349 ****
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);
--- 5316,5321 ----
Index: gcc/config/s390/s390.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/s390/s390.md,v
retrieving revision 1.67
diff -c -p -r1.67 s390.md
*** gcc/config/s390/s390.md 7 Aug 2003 11:05:54 -0000 1.67
--- gcc/config/s390/s390.md 22 Aug 2003 17:54:24 -0000
***************
*** 92,104 ****
(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_MAIN_POOL 300)
; TLS support
--- 92,98 ----
(UNSPECV_POOL 200)
(UNSPECV_POOL_START 201)
(UNSPECV_POOL_END 202)
! (UNSPECV_POOL_ENTRY 203)
(UNSPECV_MAIN_POOL 300)
; TLS support
***************
*** 7058,7145 ****
; Special literal pool access instruction pattern(s).
;
! (define_insn "consttable_qi"
! [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "X")]
! UNSPECV_POOL_QI)]
""
{
! assemble_integer (operands[0], 1, BITS_PER_UNIT, 1);
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")])
(define_insn "pool_start_31"
[(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
--- 7052,7070 ----
; Special literal pool access instruction pattern(s).
;
! (define_insn "*pool_entry"
! [(unspec_volatile [(match_operand 0 "consttable_operand" "X")]
! UNSPECV_POOL_ENTRY)]
""
{
! 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")
! (symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
(define_insn "pool_start_31"
[(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
***************
*** 7238,7249 ****
{
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 "";
--- 7163,7168 ----
--
Dr. Ulrich Weigand
weigand@informatik.uni-erlangen.de