From 5af2f3d3ff87a08c4292f6dcbf60a6d1b7039e6c Mon Sep 17 00:00:00 2001 From: Ulrich Weigand <uweigand@de.ibm.com> Date: Wed, 27 Aug 2003 18:50:37 +0000 Subject: [PATCH] s390.c (struct machine_function): Remove member literal_pool_label. * config/s390/s390.c (struct machine_function): Remove member literal_pool_label. (s390_optimize_prolog): Replace TEMP_REG argument with TEMP_USED and BASE_USED. Do not check get_pool_size (). (general_s_operand): Accept all immediates before reload if ALLOW_IMMEDIATE. If not ALLOW_IMMEDIATE, reject literal pool references. (s390_output_symbolic_const): Remove UNSPEC_LTREL_OFFSET handling. (find_constant_pool_ref): Ignore UNSPECV_POOL_ENTRY insns. (s390_alloc_pool): New function. (s390_new_pool): Call it. (s390_dump_pool): Add REMOTE_LABEL argument. (s390_chunkify_start): Add BASE_REG argument. Do not check get_pool_size (). (s390_chunkify_finish): Add BASE_REG argument. Adapt s390_dump_pool call. (s390_pool_count, s390_nr_constants): Remove. (s390_output_constant_pool): Remove. (s390_mainpool_start): New function. (s390_mainpool_finish): New function. (s390_mainpool_cancel): New function. (s390_reorg): Implement main literal pool handling. (s390_emit_prologue): Emit main_pool placeholder instead of literal_pool_31 / literal_pool_64 insns. * config/s390/s390.h (s390_pool_count, s390_nr_constants): Remove. (ASM_OUTPUT_POOL_PROLOGUE, ASM_OUTPUT_SPECIAL_POOL_ENTRY): Remove. * config/s390/s390.md (UNSPEC_MAIN_BASE): New symbolic constant. ("main_base_31_small", "main_base_31_large"): New insns. ("main_base_64", "main_pool"): New insns. ("literal_pool_31", "literal_pool_64"): Remove. From-SVN: r70853 --- gcc/ChangeLog | 33 ++++ gcc/config/s390/s390.c | 416 +++++++++++++++++++++++++++------------- gcc/config/s390/s390.h | 29 --- gcc/config/s390/s390.md | 67 +++---- 4 files changed, 347 insertions(+), 198 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a37591d4b4b..03b535a4b48 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2003-08-27 Ulrich Weigand <uweigand@de.ibm.com> + + * config/s390/s390.c (struct machine_function): Remove member + literal_pool_label. + (s390_optimize_prolog): Replace TEMP_REG argument with + TEMP_USED and BASE_USED. Do not check get_pool_size (). + (general_s_operand): Accept all immediates before reload if + ALLOW_IMMEDIATE. If not ALLOW_IMMEDIATE, reject literal pool + references. + (s390_output_symbolic_const): Remove UNSPEC_LTREL_OFFSET handling. + (find_constant_pool_ref): Ignore UNSPECV_POOL_ENTRY insns. + (s390_alloc_pool): New function. + (s390_new_pool): Call it. + (s390_dump_pool): Add REMOTE_LABEL argument. + (s390_chunkify_start): Add BASE_REG argument. Do not check + get_pool_size (). + (s390_chunkify_finish): Add BASE_REG argument. Adapt + s390_dump_pool call. + (s390_pool_count, s390_nr_constants): Remove. + (s390_output_constant_pool): Remove. + (s390_mainpool_start): New function. + (s390_mainpool_finish): New function. + (s390_mainpool_cancel): New function. + (s390_reorg): Implement main literal pool handling. + (s390_emit_prologue): Emit main_pool placeholder instead of + literal_pool_31 / literal_pool_64 insns. + * config/s390/s390.h (s390_pool_count, s390_nr_constants): Remove. + (ASM_OUTPUT_POOL_PROLOGUE, ASM_OUTPUT_SPECIAL_POOL_ENTRY): Remove. + * config/s390/s390.md (UNSPEC_MAIN_BASE): New symbolic constant. + ("main_base_31_small", "main_base_31_large"): New insns. + ("main_base_64", "main_pool"): New insns. + ("literal_pool_31", "literal_pool_64"): Remove. + 2003-08-27 Nathanael Nerode <neroden@gcc.gnu.org> * fixinc/inclhack.def (ptx_netswap): New disabled fix, ported from diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index c318d4770a3..bd3fc655890 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -183,9 +183,6 @@ const char *s390_arch_string; /* for -march=<xxx> */ struct machine_function GTY(()) { - /* Label of start of initial literal pool. */ - rtx literal_pool_label; - /* Set, if some of the fprs 8-15 need to be saved (64 bit abi). */ int save_fprs_p; @@ -223,7 +220,7 @@ static void find_constant_pool_ref (rtx, rtx *); 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 void s390_optimize_prolog (bool, bool); static int find_unused_clobbered_reg (void); static void s390_frame_info (void); static rtx save_fpr (rtx, int, int); @@ -1139,30 +1136,30 @@ general_s_operand (register rtx op, enum machine_mode mode, switch (GET_CODE (op)) { - /* Constants that we are sure will be forced to the - literal pool in reload are OK as s-operand. Note - that we cannot call s390_preferred_reload_class here - because it might not be known yet at this point - whether the current function is a leaf or not. */ + /* Constants are OK as s-operand if ALLOW_IMMEDIATE + is true and we are still before reload. */ case CONST_INT: case CONST_DOUBLE: if (!allow_immediate || reload_completed) - break; - if (!legitimate_reload_constant_p (op)) - return 1; - if (!TARGET_64BIT) - return 1; - break; + return 0; + return 1; /* Memory operands are OK unless they already use an index register. */ case MEM: if (GET_CODE (XEXP (op, 0)) == ADDRESSOF) return 1; - if (s390_decompose_address (XEXP (op, 0), &addr) - && !addr.indx) - return 1; - break; + if (!s390_decompose_address (XEXP (op, 0), &addr)) + return 0; + if (addr.indx) + return 0; + /* Do not allow literal pool references unless ALLOW_IMMEDIATE + is true. This prevents compares between two literal pool + entries from being accepted. */ + if (!allow_immediate + && addr.base && REGNO (addr.base) == BASE_REGISTER) + return 0; + return 1; default: break; @@ -3278,11 +3275,6 @@ s390_output_symbolic_const (FILE *file, rtx x) output_operand_lossage ("invalid UNSPEC as operand (1)"); switch (XINT (x, 1)) { - case UNSPEC_LTREL_OFFSET: - s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "-"); - s390_output_symbolic_const (file, cfun->machine->literal_pool_label); - break; case UNSPEC_GOTENT: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@GOTENT"); @@ -3876,6 +3868,10 @@ find_constant_pool_ref (rtx x, rtx *ref) if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREL_BASE) return; + /* Likewise POOL_ENTRY insns. */ + if (GET_CODE (x) == UNSPEC_VOLATILE + && XINT (x, 1) == UNSPECV_POOL_ENTRY) + return; if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) @@ -4071,8 +4067,12 @@ struct constant_pool int size; }; -static struct constant_pool * s390_chunkify_start (void); -static void s390_chunkify_finish (struct constant_pool *); +static struct constant_pool * s390_mainpool_start (void); +static void s390_mainpool_finish (struct constant_pool *, rtx base_reg); +static void s390_mainpool_cancel (struct constant_pool *); + +static struct constant_pool * s390_chunkify_start (rtx base_reg); +static void s390_chunkify_finish (struct constant_pool *, rtx base_reg); static void s390_chunkify_cancel (struct constant_pool *); static struct constant_pool *s390_start_pool (struct constant_pool **, rtx); @@ -4081,7 +4081,8 @@ static void s390_add_pool_insn (struct constant_pool *, rtx); static struct constant_pool *s390_find_pool (struct constant_pool *, rtx); static void s390_add_constant (struct constant_pool *, rtx, enum machine_mode); static rtx s390_find_constant (struct constant_pool *, rtx, enum machine_mode); -static rtx s390_dump_pool (struct constant_pool *); +static rtx s390_dump_pool (struct constant_pool *, bool); +static struct constant_pool *s390_alloc_pool (void); static void s390_free_pool (struct constant_pool *); /* Create new constant pool covering instructions starting at INSN @@ -4091,18 +4092,9 @@ static struct constant_pool * s390_start_pool (struct constant_pool **pool_list, rtx insn) { struct constant_pool *pool, **prev; - int i; - pool = (struct constant_pool *) xmalloc (sizeof *pool); - pool->next = NULL; - for (i = 0; i < NR_C_MODES; i++) - pool->constants[i] = NULL; - - pool->label = gen_label_rtx (); + pool = s390_alloc_pool (); pool->first_insn = insn; - pool->pool_insn = NULL_RTX; - pool->insns = BITMAP_XMALLOC (); - pool->size = 0; for (prev = pool_list; *prev; prev = &(*prev)->next) ; @@ -4208,10 +4200,11 @@ s390_find_constant (struct constant_pool *pool, rtx val, return offset; } -/* Dump out the constants in POOL. */ +/* Dump out the constants in POOL. If REMOTE_LABEL is true, + do not emit the pool base label. */ static rtx -s390_dump_pool (struct constant_pool *pool) +s390_dump_pool (struct constant_pool *pool, bool remote_label) { struct constant *c; rtx insn; @@ -4225,8 +4218,11 @@ s390_dump_pool (struct constant_pool *pool) insn = emit_insn_after (gen_pool_start_31 (), pool->pool_insn); INSN_ADDRESSES_NEW (insn, -1); - insn = emit_label_after (pool->label, insn); - INSN_ADDRESSES_NEW (insn, -1); + if (!remote_label) + { + insn = emit_label_after (pool->label, insn); + INSN_ADDRESSES_NEW (insn, -1); + } /* Dump constants in descending alignment requirement order, ensuring proper alignment for every constant. */ @@ -4272,6 +4268,28 @@ s390_dump_pool (struct constant_pool *pool) return insn; } +/* Allocate new constant_pool structure. */ + +static struct constant_pool * +s390_alloc_pool (void) +{ + struct constant_pool *pool; + int i; + + pool = (struct constant_pool *) xmalloc (sizeof *pool); + pool->next = NULL; + for (i = 0; i < NR_C_MODES; i++) + pool->constants[i] = NULL; + + pool->label = gen_label_rtx (); + pool->first_insn = NULL_RTX; + pool->pool_insn = NULL_RTX; + pool->insns = BITMAP_XMALLOC (); + pool->size = 0; + + return pool; +} + /* Free all memory used by POOL. */ static void @@ -4295,16 +4313,182 @@ s390_free_pool (struct constant_pool *pool) } -/* Chunkify the literal pool if required. */ +/* Collect main literal pool. Return NULL on overflow. */ + +static struct constant_pool * +s390_mainpool_start (void) +{ + struct constant_pool *pool; + rtx insn; + + pool = s390_alloc_pool (); + + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + if (GET_CODE (insn) == INSN + && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE + && XINT (PATTERN (insn), 1) == UNSPECV_MAIN_POOL) + { + if (pool->pool_insn) + abort (); + pool->pool_insn = insn; + } + + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN) + { + rtx pool_ref = NULL_RTX; + find_constant_pool_ref (PATTERN (insn), &pool_ref); + if (pool_ref) + { + rtx constant = get_pool_constant (pool_ref); + enum machine_mode mode = get_pool_mode (pool_ref); + s390_add_constant (pool, constant, mode); + } + } + } + + if (!pool->pool_insn) + abort (); + + if (pool->size >= 4096) + { + s390_free_pool (pool); + pool = NULL; + } + + return pool; +} + +/* POOL holds the main literal pool as collected by s390_mainpool_start. + Modify the current function to output the pool constants as well as + the pool register setup instruction. BASE_REG is the register to + be used as pool base register. */ + +static void +s390_mainpool_finish (struct constant_pool *pool, rtx base_reg) +{ + rtx insn; + + /* If the pool is empty, we're done. */ + if (pool->size == 0) + { + remove_insn (pool->pool_insn); + s390_free_pool (pool); + return; + } + + /* We need correct insn addresses. */ + shorten_branches (get_insns ()); + + /* In 64-bit, we use a LARL to load the pool register. The pool is + located in the .rodata section, so we emit it after the function. */ + if (TARGET_64BIT) + { + insn = gen_main_base_64 (base_reg, pool->label); + insn = emit_insn_after (insn, pool->pool_insn); + INSN_ADDRESSES_NEW (insn, -1); + remove_insn (pool->pool_insn); + + insn = get_last_insn (); + pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn); + INSN_ADDRESSES_NEW (pool->pool_insn, -1); + + s390_dump_pool (pool, 0); + } + + /* In 31-bit, if the total size of the function's code plus literal pool + does not exceed 4096 bytes, we use BASR to set up a function base + pointer, and emit the literal pool at the end of the function. */ + else if (INSN_ADDRESSES (INSN_UID (get_last_insn ())) + + pool->size + 8 /* alignment slop */ < 4096) + { + insn = gen_main_base_31_small (base_reg, pool->label); + insn = emit_insn_after (insn, pool->pool_insn); + INSN_ADDRESSES_NEW (insn, -1); + remove_insn (pool->pool_insn); + + insn = emit_label_after (pool->label, insn); + INSN_ADDRESSES_NEW (insn, -1); + + insn = get_last_insn (); + pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn); + INSN_ADDRESSES_NEW (pool->pool_insn, -1); + + s390_dump_pool (pool, 1); + } + + /* Otherwise, we emit an inline literal pool and use BASR to branch + over it, setting up the pool register at the same time. */ + else + { + rtx pool_end = gen_label_rtx (); + + insn = gen_main_base_31_large (base_reg, pool->label, pool_end); + insn = emit_insn_after (insn, pool->pool_insn); + INSN_ADDRESSES_NEW (insn, -1); + remove_insn (pool->pool_insn); + + insn = emit_label_after (pool->label, insn); + INSN_ADDRESSES_NEW (insn, -1); + + pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn); + INSN_ADDRESSES_NEW (pool->pool_insn, -1); + + insn = emit_label_after (pool_end, pool->pool_insn); + INSN_ADDRESSES_NEW (insn, -1); + + s390_dump_pool (pool, 1); + } + + + /* Replace all literal pool references. */ + + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + { + if (INSN_P (insn)) + replace_ltrel_base (&PATTERN (insn), base_reg); + + if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN) + { + rtx addr, pool_ref = NULL_RTX; + find_constant_pool_ref (PATTERN (insn), &pool_ref); + if (pool_ref) + { + addr = s390_find_constant (pool, get_pool_constant (pool_ref), + get_pool_mode (pool_ref)); + addr = gen_rtx_PLUS (Pmode, base_reg, addr); + replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr); + INSN_CODE (insn) = -1; + } + } + } + + + /* Free the pool. */ + s390_free_pool (pool); +} + +/* POOL holds the main literal pool as collected by s390_mainpool_start. + We have decided we cannot use this pool, so revert all changes + to the current function that were done by s390_mainpool_start. */ +static void +s390_mainpool_cancel (struct constant_pool *pool) +{ + /* We didn't actually change the instruction stream, so simply + free the pool memory. */ + s390_free_pool (pool); +} + + +/* Chunkify the literal pool. BASE_REG is to be used as pool + register. */ #define S390_POOL_CHUNK_MIN 0xc00 #define S390_POOL_CHUNK_MAX 0xe00 static struct constant_pool * -s390_chunkify_start (void) +s390_chunkify_start (rtx base_reg) { - rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER); - struct constant_pool *curr_pool = NULL, *pool_list = NULL; int extra_size = 0; bitmap far_labels; @@ -4315,11 +4499,6 @@ s390_chunkify_start (void) TARGET_64BIT? gen_reload_base_64 : gen_reload_base_31; - /* Do we need to chunkify the literal pool? */ - - if (get_pool_size () < S390_POOL_CHUNK_MAX) - return NULL; - /* We need correct insn addresses. */ shorten_branches (get_insns ()); @@ -4568,12 +4747,12 @@ s390_chunkify_start (void) /* POOL_LIST is a chunk list as prepared by s390_chunkify_start. After we have decided to use this list, finish implementing - all changes to the current function as required. */ + all changes to the current function as required. BASE_REG is + to be used as pool base register. */ static void -s390_chunkify_finish (struct constant_pool *pool_list) +s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg) { - rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER); struct constant_pool *curr_pool = NULL; rtx insn; @@ -4607,7 +4786,7 @@ s390_chunkify_finish (struct constant_pool *pool_list) /* Dump out all literal pools. */ for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next) - s390_dump_pool (curr_pool); + s390_dump_pool (curr_pool, 0); /* Free pool list. */ @@ -4680,45 +4859,6 @@ s390_chunkify_cancel (struct constant_pool *pool_list) } -/* Index of constant pool chunk that is currently being processed. - Set to -1 before function output has started. */ -int s390_pool_count = -1; - -/* Number of elements of current constant pool. */ -int s390_nr_constants; - -/* Output main constant pool to stdio stream FILE. */ - -void -s390_output_constant_pool (rtx start_label, rtx end_label) -{ - if (TARGET_64BIT) - { - readonly_data_section (); - ASM_OUTPUT_ALIGN (asm_out_file, 3); - targetm.asm_out.internal_label (asm_out_file, "L", - CODE_LABEL_NUMBER (start_label)); - } - else - { - targetm.asm_out.internal_label (asm_out_file, "L", - CODE_LABEL_NUMBER (start_label)); - ASM_OUTPUT_ALIGN (asm_out_file, 2); - } - - s390_pool_count = 0; - output_constant_pool (current_function_name, current_function_decl); - s390_pool_count = -1; - if (TARGET_64BIT) - function_section (current_function_decl); - else - { - ASM_OUTPUT_ALIGN (asm_out_file, 1); - targetm.asm_out.internal_label (asm_out_file, "L", - CODE_LABEL_NUMBER (end_label)); - } -} - /* Output to FILE the constant pool entry EXP in mode MODE with alignment ALIGN. */ @@ -4760,29 +4900,23 @@ s390_output_pool_entry (FILE *file, rtx exp, enum machine_mode mode, /* 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 - as temporary scratch register by code emitted during - machine dependent reorg. */ + registers unnecessarily. BASE_USED specifies whether + the literal pool base register needs to be saved, + TEMP_USED specifies whether the return register needs + to be saved. */ static void -s390_optimize_prolog (int temp_regno) +s390_optimize_prolog (bool base_used, bool temp_used) { int save_first, save_last, restore_first, restore_last; int i, j; rtx insn, new_insn, next_insn; /* Recompute regs_ever_live data for special registers. */ - regs_ever_live[BASE_REGISTER] = 0; - regs_ever_live[RETURN_REGNUM] = 0; + regs_ever_live[BASE_REGISTER] = base_used; + regs_ever_live[RETURN_REGNUM] = temp_used; regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0; - /* If there is (possibly) any pool entry, we need to - load the base register. - ??? FIXME: this should be more precise. */ - if (get_pool_size ()) - 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) @@ -4791,10 +4925,6 @@ s390_optimize_prolog (int temp_regno) || cfun->machine->save_return_addr_p) regs_ever_live[RETURN_REGNUM] = 1; - /* We need to save/restore the temporary register. */ - if (temp_regno >= 0) - regs_ever_live[temp_regno] = 1; - /* Find first and last gpr to be saved. */ @@ -4919,14 +5049,27 @@ static void s390_reorg (void) { rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM); - bool temp_used = 0; + rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER); + bool temp_used = false; + bool base_used = false; + bool pool_overflow = false; /* Make sure all splits have been performed; splits after machine_dependent_reorg might confuse insn length counts. */ split_all_insns_noflow (); - /* There are two problematic situations we need to correct: + /* In small leaf functions, try to use an unused call-clobbered + register as base register to avoid save/restore overhead. */ + if (current_function_is_leaf && !regs_ever_live[5]) + base_reg = gen_rtx_REG (Pmode, 5); + + + /* Install the main literal pool and the associated base + register load insns. + + In addition, there are two problematic situations we need + to correct: - the literal pool might be > 4096 bytes in size, so that some of its elements cannot be directly accessed @@ -4957,31 +5100,48 @@ s390_reorg (void) for (;;) { - struct constant_pool *pool_list; + struct constant_pool *pool = NULL; - /* Try to chunkify the literal pool. */ - pool_list = s390_chunkify_start (); + /* Collect the literal pool. */ + if (!pool_overflow) + { + pool = s390_mainpool_start (); + if (!pool) + pool_overflow = true; + } + + /* If literal pool overflowed, start to chunkify it. */ + if (pool_overflow) + pool = s390_chunkify_start (base_reg); /* Split out-of-range branches. If this has created new literal pool entries, cancel current chunk list and recompute it. */ if (s390_split_branches (temp_reg, &temp_used)) { - if (pool_list) - s390_chunkify_cancel (pool_list); + if (pool_overflow) + s390_chunkify_cancel (pool); + else + s390_mainpool_cancel (pool); continue; } /* If we made it up to here, both conditions are satisfied. - Finish up pool chunkification if required. */ - if (pool_list) - s390_chunkify_finish (pool_list); + Finish up literal pool related changes. */ + if ((pool_overflow || pool->size > 0) + && REGNO (base_reg) == BASE_REGISTER) + base_used = true; + + if (pool_overflow) + s390_chunkify_finish (pool, base_reg); + else + s390_mainpool_finish (pool, base_reg); break; } - s390_optimize_prolog (temp_used? RETURN_REGNUM : -1); + s390_optimize_prolog (base_used, temp_used); } @@ -5305,7 +5465,6 @@ s390_emit_prologue (void) { rtx insn, addr; rtx temp_reg; - rtx pool_start_label, pool_end_label; int i; /* Compute frame_info. */ @@ -5327,18 +5486,9 @@ s390_emit_prologue (void) cfun->machine->first_save_gpr, cfun->machine->last_save_gpr); emit_insn (insn); - /* Dump constant pool and set constant pool register. */ + /* Dummy insn to mark literal pool slot. */ - pool_start_label = gen_label_rtx(); - pool_end_label = gen_label_rtx(); - cfun->machine->literal_pool_label = pool_start_label; - - if (TARGET_64BIT) - insn = emit_insn (gen_literal_pool_64 (gen_rtx_REG (Pmode, BASE_REGISTER), - pool_start_label, pool_end_label)); - else - insn = emit_insn (gen_literal_pool_31 (gen_rtx_REG (Pmode, BASE_REGISTER), - pool_start_label, pool_end_label)); + emit_insn (gen_main_pool ()); /* Save fprs for variable args. */ diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h index 541d6892f8a..5cd1d46d666 100644 --- a/gcc/config/s390/s390.h +++ b/gcc/config/s390/s390.h @@ -1012,35 +1012,6 @@ do { \ } while (0) -/* Constant Pool for all symbols operands which are changed with - force_const_mem during insn generation (expand_insn). */ - -extern int s390_pool_count; -extern int s390_nr_constants; - -#define ASM_OUTPUT_POOL_PROLOGUE(FILE, FUNNAME, fndecl, size) \ -{ \ - struct pool_constant *pool; \ - \ - if (s390_pool_count == -1) \ - { \ - s390_nr_constants = 0; \ - for (pool = first_pool; pool; pool = pool->next) \ - if (pool->mark) s390_nr_constants++; \ - return; \ - } \ -} - -#define ASM_OUTPUT_SPECIAL_POOL_ENTRY(FILE, EXP, MODE, ALIGN, LABELNO, WIN) \ -{ \ - fprintf (FILE, ".LC%d:\n", LABELNO); \ - s390_output_pool_entry (FILE, EXP, MODE, ALIGN); \ - if (GET_MODE_SIZE (MODE) == 1) \ - ASM_OUTPUT_SKIP ((FILE), (unsigned HOST_WIDE_INT)1); \ - goto WIN; \ -} - - /* Miscellaneous parameters. */ /* Define the codes that are matched by predicates in aux-output.c. */ diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index fa7203df47a..4cda1480cab 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -65,6 +65,7 @@ ; Literal pool (UNSPEC_RELOAD_BASE 210) + (UNSPEC_MAIN_BASE 211) ; TLS relocation specifiers (UNSPEC_TLSGD 500) @@ -7232,6 +7233,36 @@ [(set_attr "op_type" "NN") (set_attr "length" "0")]) +(define_insn "main_base_31_small" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))] + "!TARGET_64BIT" + "basr\t%0,0" + [(set_attr "op_type" "RR") + (set_attr "type" "la")]) + +(define_insn "main_base_31_large" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE)) + (set (pc) (label_ref (match_operand 2 "" "")))] + "!TARGET_64BIT" + "bras\t%0,%2" + [(set_attr "op_type" "RI")]) + +(define_insn "main_base_64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec:DI [(label_ref (match_operand 1 "" ""))] UNSPEC_MAIN_BASE))] + "TARGET_64BIT" + "larl\t%0,%1" + [(set_attr "op_type" "RIL") + (set_attr "type" "larl")]) + +(define_insn "main_pool" + [(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL)] + "" + "* abort ();" + [(set_attr "op_type" "NN")]) + (define_insn "reload_base_31" [(set (match_operand:SI 0 "register_operand" "=a") (unspec:SI [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))] @@ -7290,42 +7321,6 @@ (set_attr "type" "jsr") (set_attr "atype" "agen")]) -(define_insn "literal_pool_31" - [(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL) - (set (match_operand:SI 0 "register_operand" "=a") - (label_ref (match_operand 1 "" ""))) - (use (label_ref (match_operand 2 "" "")))] - "" -{ - if (s390_nr_constants) - { - output_asm_insn ("bras\t%0,%2", operands); - s390_output_constant_pool (operands[1], operands[2]); - } - - return ""; -} - [(set_attr "op_type" "NN") - (set_attr "type" "larl")]) - -(define_insn "literal_pool_64" - [(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL) - (set (match_operand:DI 0 "register_operand" "=a") - (label_ref (match_operand 1 "" ""))) - (use (label_ref (match_operand 2 "" "")))] - "" -{ - if (s390_nr_constants) - { - output_asm_insn ("larl\t%0,%1", operands); - s390_output_constant_pool (operands[1], operands[2]); - } - - return ""; -} - [(set_attr "op_type" "NN") - (set_attr "type" "larl")]) - ;; Instruction definition to extend a 31-bit pointer into a 64-bit ;; pointer. This is used for compatability.