From: uweigand Date: Sat, 23 Aug 2003 00:17:35 +0000 (+0000) Subject: * config/s390/s390-protos.h (s390_output_pool_entry): Declare. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=df82fb764e6049f077f12fe96bc1059f25fb1acd;p=thirdparty%2Fgcc.git * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@70714 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85e8b8778e06..cc8bd095b276 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2003-08-23 Ulrich Weigand + + * 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 * 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 c64e97413188..40026d3b85f6 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 55e5149cbd11..568a35b888e6 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 4376b38ea6d0..d4664092f69a 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 ""; }