From: Ulrich Weigand Date: Sat, 19 Jul 2003 16:06:52 +0000 (+0000) Subject: s390.c (legitimize_pic_address): Access local symbols relative to the GOT instead... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=fd7643fbe49e24ba9553f28b0548f4e525b43001;p=gcc.git s390.c (legitimize_pic_address): Access local symbols relative to the GOT instead of relative to the literal... * config/s390/s390.c (legitimize_pic_address): Access local symbols relative to the GOT instead of relative to the literal pool base. (s390_output_symbolic_const): Handle new GOT-relative accesses. * config/s390/s390.md ("call"): Access local functions and PLT stubs relative to the GOT instead of relative to the literal pool base. ("call_value"): Likewise. ("call_value_tls"): Likewise. * config/s390/s390.c (s390_chunkify_start): Remove pool anchor reloading. Support LTREL_BASE / LTREL_OFFSET construct. (s390_chunkify_finish): Likewise. (s390_chunkify_cancel): Likewise. (s390_reorg): Adapt caller. (find_base_register_in_addr, find_base_register_ref, replace_base_register_ref): Delete. (find_ltrel_base, replace_ltrel_base): New functions. (find_constant_pool_ref): Handle LTREL_BASE unspecs. (s390_decompose_address): Handle LTREL_BASE unspecs. Optimize base vs. index register usage. (struct constant_pool): Remove 'anchor'. (s390_add_anchor): Delete. (s390_dump_pool): Remove anchor handling. * config/s390/s390.md ("reload_anchor"): Remove. * config/s390/s390.c (s390_split_branches): Use LTREL_BASE/OFFSET. (s390_load_got): New function. Use LTREL_BASE/OFFSET. (s390_emit_prologue): Use it. * config/s390/s390.md ("builtin_longjmp", "builtin_setjmp_setup", "builtin_setjmp_receiver"): Cleanup. Use s390_load_got. Do not hard-code register 14. * config/s390/s390-protos.h (s390_load_got): Declare. * config/s390/s390.c (NR_C_MODES, constant_modes, gen_consttable): Support TImode constants. * config/s390/s390.md ("consttable_ti"): New. ("consttable_si", "consttable_di"): Handle TLS symbols correctly. * config/s390/s390.md (UNSPEC_LTREL_OFFSET, UNSPEC_LTREL_BASE, UNSPEC_GOTENT, UNSPEC_GOT, UNSPEC_GOTOFF, UNSPEC_PLT, UNSPEC_PLTOFF, UNSPEC_RELOAD_BASE, UNSPECV_POOL, UNSPECV_POOL_START, UNSPECV_POOL_END, UNSPECV_POOL_QI, UNSPECV_POOL_HI, UNSPECV_POOL_SI, UNSPECV_POOL_DI, UNSPECV_POOL_TI, UNSPECV_POOL_SF, UNSPECV_POOL_DF, UNSPECV_MAIN_POOL): New symbolic constants. ("consttable_qi", "consttable_hi", "consttable_si", "consttable_di", "consttable_sf", "consttable_df", "pool_start_31", "pool_end_31", "pool_start_64", "pool_end_64", "reload_base_31", "reload_base_64", "pool", "literal_pool_31", "literal_pool_64"): Cleanup. Use symbolic UNSPEC values. * config/s390/s390.c (larl_operand, s390_short_displacement, bras_sym_operand, s390_cannot_force_const_mem, s390_delegitimize_address, s390_decompose_address, legitimize_pic_address, s390_output_symbolic_const, s390_function_profiler): Use symbolic UNSPEC values. From-SVN: r69592 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6bb655ae09f..99f56e6c69e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,59 @@ +2003-07-19 Ulrich Weigand + + * config/s390/s390.c (legitimize_pic_address): Access local symbols + relative to the GOT instead of relative to the literal pool base. + (s390_output_symbolic_const): Handle new GOT-relative accesses. + * config/s390/s390.md ("call"): Access local functions and PLT stubs + relative to the GOT instead of relative to the literal pool base. + ("call_value"): Likewise. + ("call_value_tls"): Likewise. + + * config/s390/s390.c (s390_chunkify_start): Remove pool anchor + reloading. Support LTREL_BASE / LTREL_OFFSET construct. + (s390_chunkify_finish): Likewise. + (s390_chunkify_cancel): Likewise. + (s390_reorg): Adapt caller. + (find_base_register_in_addr, + find_base_register_ref, replace_base_register_ref): Delete. + (find_ltrel_base, replace_ltrel_base): New functions. + (find_constant_pool_ref): Handle LTREL_BASE unspecs. + (s390_decompose_address): Handle LTREL_BASE unspecs. Optimize + base vs. index register usage. + (struct constant_pool): Remove 'anchor'. + (s390_add_anchor): Delete. + (s390_dump_pool): Remove anchor handling. + * config/s390/s390.md ("reload_anchor"): Remove. + + * config/s390/s390.c (s390_split_branches): Use LTREL_BASE/OFFSET. + (s390_load_got): New function. Use LTREL_BASE/OFFSET. + (s390_emit_prologue): Use it. + * config/s390/s390.md ("builtin_longjmp", "builtin_setjmp_setup", + "builtin_setjmp_receiver"): Cleanup. Use s390_load_got. Do not + hard-code register 14. + * config/s390/s390-protos.h (s390_load_got): Declare. + + * config/s390/s390.c (NR_C_MODES, constant_modes, gen_consttable): + Support TImode constants. + * config/s390/s390.md ("consttable_ti"): New. + ("consttable_si", "consttable_di"): Handle TLS symbols correctly. + + * config/s390/s390.md (UNSPEC_LTREL_OFFSET, UNSPEC_LTREL_BASE, + UNSPEC_GOTENT, UNSPEC_GOT, UNSPEC_GOTOFF, UNSPEC_PLT, UNSPEC_PLTOFF, + UNSPEC_RELOAD_BASE, UNSPECV_POOL, UNSPECV_POOL_START, UNSPECV_POOL_END, + UNSPECV_POOL_QI, UNSPECV_POOL_HI, UNSPECV_POOL_SI, UNSPECV_POOL_DI, + UNSPECV_POOL_TI, UNSPECV_POOL_SF, UNSPECV_POOL_DF, UNSPECV_MAIN_POOL): + New symbolic constants. + ("consttable_qi", "consttable_hi", "consttable_si", "consttable_di", + "consttable_sf", "consttable_df", "pool_start_31", "pool_end_31", + "pool_start_64", "pool_end_64", "reload_base_31", "reload_base_64", + "pool", "literal_pool_31", "literal_pool_64"): Cleanup. Use + symbolic UNSPEC values. + * config/s390/s390.c (larl_operand, s390_short_displacement, + bras_sym_operand, s390_cannot_force_const_mem, + s390_delegitimize_address, s390_decompose_address, + legitimize_pic_address, s390_output_symbolic_const, + s390_function_profiler): Use symbolic UNSPEC values. + 2003-07-19 Kaveh R. Ghazi * alias.c alloc-pool.c bitmap.c bitmap.h bt-load.c builtins.c diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h index 3d3f53a4bc2..a6ed004ffbf 100644 --- a/gcc/config/s390/s390-protos.h +++ b/gcc/config/s390/s390-protos.h @@ -24,6 +24,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA extern void optimization_options PARAMS ((int, int)); extern void override_options PARAMS ((void)); extern int s390_arg_frame_offset PARAMS ((void)); +extern void s390_load_got PARAMS ((int)); extern void s390_emit_prologue PARAMS ((void)); extern void s390_emit_epilogue PARAMS ((void)); extern void s390_function_profiler PARAMS ((FILE *, int)); diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c index 07d30326a9e..91e1a29d0a1 100644 --- a/gcc/config/s390/s390.c +++ b/gcc/config/s390/s390.c @@ -215,9 +215,8 @@ static int addr_generation_dependency_p PARAMS ((rtx, rtx)); static int s390_split_branches PARAMS ((rtx, bool *)); static void find_constant_pool_ref PARAMS ((rtx, rtx *)); static void replace_constant_pool_ref PARAMS ((rtx *, rtx, rtx)); -static int find_base_register_in_addr PARAMS ((struct s390_address *)); -static bool find_base_register_ref PARAMS ((rtx)); -static void replace_base_register_ref PARAMS ((rtx *, rtx)); +static rtx find_ltrel_base PARAMS ((rtx)); +static void replace_ltrel_base PARAMS ((rtx *, rtx)); static void s390_optimize_prolog PARAMS ((int)); static bool s390_fixup_clobbered_return_reg PARAMS ((rtx)); static int find_unused_clobbered_reg PARAMS ((void)); @@ -1134,10 +1133,10 @@ larl_operand (op, mode) /* Now we must have a @GOTENT offset or @PLT stub or an @INDNTPOFF TLS offset. */ if (GET_CODE (op) == UNSPEC - && XINT (op, 1) == 111) + && XINT (op, 1) == UNSPEC_GOTENT) return 1; if (GET_CODE (op) == UNSPEC - && XINT (op, 1) == 113) + && XINT (op, 1) == UNSPEC_PLT) return 1; if (GET_CODE (op) == UNSPEC && XINT (op, 1) == UNSPEC_INDNTPOFF) @@ -1249,7 +1248,7 @@ s390_short_displacement (disp) /* GOT offset is not OK, the GOT can be large. */ if (GET_CODE (disp) == CONST && GET_CODE (XEXP (disp, 0)) == UNSPEC - && XINT (XEXP (disp, 0), 1) == 110) + && XINT (XEXP (disp, 0), 1) == UNSPEC_GOT) return 0; /* All other symbolic constants are literal pool references, @@ -1455,7 +1454,7 @@ bras_sym_operand (op, mode) /* Allow @PLT stubs. */ if (code == CONST && GET_CODE (XEXP (op, 0)) == UNSPEC - && XINT (XEXP (op, 0), 1) == 113) + && XINT (XEXP (op, 0), 1) == UNSPEC_PLT) return 1; return 0; } @@ -1749,10 +1748,10 @@ s390_cannot_force_const_mem (x) switch (XINT (x, 1)) { /* Only lt-relative or GOT-relative UNSPECs are OK. */ - case 100: - case 104: - case 112: - case 114: + case UNSPEC_LTREL_OFFSET: + case UNSPEC_GOT: + case UNSPEC_GOTOFF: + case UNSPEC_PLTOFF: case UNSPEC_TLSGD: case UNSPEC_TLSLDM: case UNSPEC_NTPOFF: @@ -1996,6 +1995,8 @@ s390_decompose_address (addr, out) rtx indx = NULL_RTX; rtx disp = NULL_RTX; int pointer = FALSE; + int base_ptr = FALSE; + int indx_ptr = FALSE; /* Decompose address into base + index + displacement. */ @@ -2041,35 +2042,18 @@ s390_decompose_address (addr, out) disp = addr; /* displacement */ - /* Prefer to use pointer as base, not index. */ - if (base && indx) - { - int base_ptr = GET_CODE (base) == UNSPEC - || (REG_P (base) && REG_POINTER (base)); - int indx_ptr = GET_CODE (indx) == UNSPEC - || (REG_P (indx) && REG_POINTER (indx)); - - if (!base_ptr && indx_ptr) - { - rtx tmp = base; - base = indx; - indx = tmp; - } - } - /* Validate base register. */ if (base) { if (GET_CODE (base) == UNSPEC) { - if (XVECLEN (base, 0) != 1 || XINT (base, 1) != 101) - return FALSE; - base = XVECEXP (base, 0, 0); - pointer = TRUE; + if (XVECLEN (base, 0) != 1 || XINT (base, 1) != UNSPEC_LTREL_BASE) + return FALSE; + base = gen_rtx_REG (Pmode, BASE_REGISTER); } if (GET_CODE (base) != REG || GET_MODE (base) != Pmode) - return FALSE; + return FALSE; if (REGNO (base) == BASE_REGISTER || REGNO (base) == STACK_POINTER_REGNUM @@ -2082,7 +2066,7 @@ s390_decompose_address (addr, out) && REGNO (base) <= LAST_VIRTUAL_REGISTER) || (flag_pic && REGNO (base) == PIC_OFFSET_TABLE_REGNUM)) - pointer = TRUE; + pointer = base_ptr = TRUE; } /* Validate index register. */ @@ -2090,14 +2074,13 @@ s390_decompose_address (addr, out) { if (GET_CODE (indx) == UNSPEC) { - if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != 101) - return FALSE; - indx = XVECEXP (indx, 0, 0); - pointer = TRUE; + if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != UNSPEC_LTREL_BASE) + return FALSE; + indx = gen_rtx_REG (Pmode, BASE_REGISTER); } if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode) - return FALSE; + return FALSE; if (REGNO (indx) == BASE_REGISTER || REGNO (indx) == STACK_POINTER_REGNUM @@ -2110,7 +2093,16 @@ s390_decompose_address (addr, out) && REGNO (indx) <= LAST_VIRTUAL_REGISTER) || (flag_pic && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM)) - pointer = TRUE; + pointer = indx_ptr = TRUE; + } + + /* Prefer to use pointer as base, not index. */ + if (base && indx && !base_ptr + && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx)))) + { + rtx tmp = base; + base = indx; + indx = tmp; } /* Validate displacement. */ @@ -2134,11 +2126,11 @@ s390_decompose_address (addr, out) } } - /* In the small-PIC case, the linker converts @GOT12 + /* In the small-PIC case, the linker converts @GOT and @GOTNTPOFF offsets to possible displacements. */ else if (GET_CODE (disp) == CONST && GET_CODE (XEXP (disp, 0)) == UNSPEC - && (XINT (XEXP (disp, 0), 1) == 110 + && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF)) { if (flag_pic != 1) @@ -2205,7 +2197,8 @@ s390_decompose_address (addr, out) else base = gen_rtx_REG (Pmode, BASE_REGISTER); - disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp), 100); + disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp), + UNSPEC_LTREL_OFFSET); disp = gen_rtx_CONST (Pmode, disp); if (offset) @@ -2356,19 +2349,19 @@ legitimize_pic_address (orig, reg) } else { - /* Access local symbols relative to the literal pool. */ + /* Access local symbols relative to the GOT. */ rtx temp = reg? reg : gen_reg_rtx (Pmode); - addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 100); + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; + + addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTOFF); addr = gen_rtx_CONST (Pmode, addr); addr = force_const_mem (Pmode, addr); emit_move_insn (temp, addr); - base = gen_rtx_REG (Pmode, BASE_REGISTER); - base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101); - new = gen_rtx_PLUS (Pmode, base, temp); - + new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp); if (reg != 0) { emit_move_insn (reg, new); @@ -2384,12 +2377,12 @@ legitimize_pic_address (orig, reg) if (flag_pic == 1) { /* Assume GOT offset < 4k. This is handled the same way - in both 31- and 64-bit code (@GOT12). */ + in both 31- and 64-bit code (@GOT). */ if (reload_in_progress || reload_completed) regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; - new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 110); + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT); new = gen_rtx_CONST (Pmode, new); new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, new); new = gen_rtx_MEM (Pmode, new); @@ -2404,7 +2397,7 @@ legitimize_pic_address (orig, reg) rtx temp = gen_reg_rtx (Pmode); - new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 111); + new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTENT); new = gen_rtx_CONST (Pmode, new); emit_move_insn (temp, new); @@ -2423,7 +2416,7 @@ legitimize_pic_address (orig, reg) if (reload_in_progress || reload_completed) regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; - addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 112); + addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT); addr = gen_rtx_CONST (Pmode, addr); addr = force_const_mem (Pmode, addr); emit_move_insn (temp, addr); @@ -2446,35 +2439,41 @@ legitimize_pic_address (orig, reg) abort (); switch (XINT (addr, 1)) { - /* If someone moved an @GOT or lt-relative UNSPEC + /* If someone moved a GOT-relative UNSPEC out of the literal pool, force them back in. */ - case 100: - case 112: - case 114: + case UNSPEC_GOTOFF: + case UNSPEC_PLTOFF: new = force_const_mem (Pmode, orig); break; + /* @GOT is OK as is if small. */ + case UNSPEC_GOT: + if (flag_pic == 2) + new = force_const_mem (Pmode, orig); + break; + /* @GOTENT is OK as is. */ - case 111: + case UNSPEC_GOTENT: break; /* @PLT is OK as is on 64-bit, must be converted to - lt-relative PLT on 31-bit. */ - case 113: + GOT-relative @PLTOFF on 31-bit. */ + case UNSPEC_PLT: if (!TARGET_64BIT) { rtx temp = reg? reg : gen_reg_rtx (Pmode); + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; + addr = XVECEXP (addr, 0, 0); - addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), 114); + addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), + UNSPEC_PLTOFF); addr = gen_rtx_CONST (Pmode, addr); addr = force_const_mem (Pmode, addr); emit_move_insn (temp, addr); - base = gen_rtx_REG (Pmode, BASE_REGISTER); - base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101); - new = gen_rtx_PLUS (Pmode, base, temp); - + new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp); if (reg != 0) { emit_move_insn (reg, new); @@ -2533,20 +2532,21 @@ legitimize_pic_address (orig, reg) } else { - /* Access local symbols relative to the literal pool. */ + /* Access local symbols relative to the GOT. */ rtx temp = reg? reg : gen_reg_rtx (Pmode); - addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), 100); + if (reload_in_progress || reload_completed) + regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1; + + addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), + UNSPEC_GOTOFF); addr = gen_rtx_PLUS (Pmode, addr, op1); addr = gen_rtx_CONST (Pmode, addr); addr = force_const_mem (Pmode, addr); emit_move_insn (temp, addr); - base = gen_rtx_REG (Pmode, BASE_REGISTER); - base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 101); - new = gen_rtx_PLUS (Pmode, base, temp); - + new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp); if (reg != 0) { emit_move_insn (reg, new); @@ -2555,7 +2555,7 @@ legitimize_pic_address (orig, reg) } } - /* Now, check whether it is an LT-relative symbol plus offset + /* Now, check whether it is a GOT relative symbol plus offset that was pulled out of the literal pool. Force it back in. */ else if (GET_CODE (op0) == UNSPEC @@ -2563,7 +2563,7 @@ legitimize_pic_address (orig, reg) { if (XVECLEN (op0, 0) != 1) abort (); - if (XINT (op0, 1) != 100) + if (XINT (op0, 1) != UNSPEC_GOTOFF) abort (); new = force_const_mem (Pmode, orig); @@ -3279,7 +3279,7 @@ s390_delegitimize_address (orig_x) { y = XEXP (XEXP (x, 1), 0); if (GET_CODE (y) == UNSPEC - && XINT (y, 1) == 110) + && XINT (y, 1) == UNSPEC_GOT) return XVECEXP (y, 0, 0); return orig_x; } @@ -3288,7 +3288,7 @@ s390_delegitimize_address (orig_x) { y = XEXP (x, 0); if (GET_CODE (y) == UNSPEC - && XINT (y, 1) == 111) + && XINT (y, 1) == UNSPEC_GOTENT) return XVECEXP (y, 0, 0); return orig_x; } @@ -3378,37 +3378,30 @@ s390_output_symbolic_const (file, x) output_operand_lossage ("invalid UNSPEC as operand (1)"); switch (XINT (x, 1)) { - case 100: - case 104: + 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 105: - s390_output_symbolic_const (file, cfun->machine->literal_pool_label); - fprintf (file, "-"); - s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - break; - case 110: - s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@GOT12"); - break; - case 111: + case UNSPEC_GOTENT: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@GOTENT"); break; - case 112: + case UNSPEC_GOT: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@GOT"); break; - case 113: + case UNSPEC_GOTOFF: + s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); + fprintf (file, "@GOTOFF"); + break; + case UNSPEC_PLT: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); fprintf (file, "@PLT"); break; - case 114: + case UNSPEC_PLTOFF: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); - fprintf (file, "@PLT-"); - s390_output_symbolic_const (file, cfun->machine->literal_pool_label); + fprintf (file, "@PLTOFF"); break; case UNSPEC_TLSGD: s390_output_symbolic_const (file, XVECEXP (x, 0, 0)); @@ -3968,14 +3961,16 @@ s390_split_branches (temp_reg, temp_used) else { new_literal = 1; - tmp = gen_rtx_UNSPEC (SImode, gen_rtvec (1, *label), 104); - tmp = gen_rtx_CONST (SImode, tmp); - tmp = force_const_mem (SImode, tmp); - tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn); + target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, *label), + UNSPEC_LTREL_OFFSET); + target = gen_rtx_CONST (Pmode, target); + target = force_const_mem (Pmode, target); + tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn); INSN_ADDRESSES_NEW (tmp, -1); - target = gen_rtx_REG (Pmode, BASE_REGISTER); - target = gen_rtx_PLUS (Pmode, target, temp_reg); + target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (target, 0)), + UNSPEC_LTREL_BASE); + target = gen_rtx_PLUS (Pmode, temp_reg, target); } if (!validate_change (insn, label, target, 0)) @@ -4002,6 +3997,11 @@ find_constant_pool_ref (x, ref) int i, j; const char *fmt; + /* Ignore LTREL_BASE references. */ + if (GET_CODE (x) == UNSPEC + && XINT (x, 1) == UNSPEC_LTREL_BASE) + return; + if (GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x)) { @@ -4100,135 +4100,58 @@ replace_constant_pool_ref (x, ref, addr) } } -/* Check whether ADDR is an address that uses the base register, - without actually constituting a literal pool access. (This happens - in 31-bit PIC mode, where the base register is used as anchor for - relative addressing of local symbols.) - - Returns 1 if the base register occupies the base slot, - returns 2 if the base register occupies the index slot, - returns 0 if the address is not of this form. */ - -static int -find_base_register_in_addr (addr) - struct s390_address *addr; -{ - /* If DISP is complex, we might have a literal pool reference. */ - if (addr->disp && GET_CODE (addr->disp) != CONST_INT) - return 0; - - if (addr->base && REG_P (addr->base) && REGNO (addr->base) == BASE_REGISTER) - return 1; - - if (addr->indx && REG_P (addr->indx) && REGNO (addr->indx) == BASE_REGISTER) - return 2; - - return 0; -} - -/* Return true if X contains an address that uses the base register, - without actually constituting a literal pool access. */ +/* Check whether X contains an UNSPEC_LTREL_BASE. + Return its constant pool symbol if found, NULL_RTX otherwise. */ -static bool -find_base_register_ref (x) +static rtx +find_ltrel_base (x) rtx x; { - bool retv = FALSE; - struct s390_address addr; int i, j; const char *fmt; - /* Addresses can only occur inside a MEM ... */ - if (GET_CODE (x) == MEM) - { - if (s390_decompose_address (XEXP (x, 0), &addr) - && find_base_register_in_addr (&addr)) - return TRUE; - } - - /* ... or a load-address type pattern. */ - if (GET_CODE (x) == SET && GET_CODE (SET_DEST (x)) == REG) - { - if (s390_decompose_address (SET_SRC (x), &addr) - && find_base_register_in_addr (&addr)) - return TRUE; - } + if (GET_CODE (x) == UNSPEC + && XINT (x, 1) == UNSPEC_LTREL_BASE) + return XVECEXP (x, 0, 0); fmt = GET_RTX_FORMAT (GET_CODE (x)); for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) { if (fmt[i] == 'e') { - retv |= find_base_register_ref (XEXP (x, i)); + rtx fnd = find_ltrel_base (XEXP (x, i)); + if (fnd) + return fnd; } else if (fmt[i] == 'E') { for (j = 0; j < XVECLEN (x, i); j++) - retv |= find_base_register_ref (XVECEXP (x, i, j)); + { + rtx fnd = find_ltrel_base (XVECEXP (x, i, j)); + if (fnd) + return fnd; + } } } - return retv; + return NULL_RTX; } -/* If X contains an address that uses the base register, - without actually constituting a literal pool access, - replace the base register with REPL in all such cases. - - Handles both MEMs and load address patterns. */ +/* Replace any occurrence of UNSPEC_LTREL_BASE in X with BASE. */ static void -replace_base_register_ref (x, repl) +replace_ltrel_base (x, base) rtx *x; - rtx repl; + rtx base; { - struct s390_address addr; - rtx new_addr; - int i, j, pos; + int i, j; const char *fmt; - /* Addresses can only occur inside a MEM ... */ - if (GET_CODE (*x) == MEM) + if (GET_CODE (*x) == UNSPEC + && XINT (*x, 1) == UNSPEC_LTREL_BASE) { - if (s390_decompose_address (XEXP (*x, 0), &addr) - && (pos = find_base_register_in_addr (&addr))) - { - if (pos == 1) - addr.base = repl; - else - addr.indx = repl; - - new_addr = addr.base; - if (addr.indx) - new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.indx); - if (addr.disp) - new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.disp); - - *x = replace_equiv_address (*x, new_addr); - return; - } - } - - /* ... or a load-address type pattern. */ - if (GET_CODE (*x) == SET && GET_CODE (SET_DEST (*x)) == REG) - { - if (s390_decompose_address (SET_SRC (*x), &addr) - && (pos = find_base_register_in_addr (&addr))) - { - if (pos == 1) - addr.base = repl; - else - addr.indx = repl; - - new_addr = addr.base; - if (addr.indx) - new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.indx); - if (addr.disp) - new_addr = gen_rtx_PLUS (Pmode, new_addr, addr.disp); - - SET_SRC (*x) = new_addr; - return; - } + *x = base; + return; } fmt = GET_RTX_FORMAT (GET_CODE (*x)); @@ -4236,23 +4159,24 @@ replace_base_register_ref (x, repl) { if (fmt[i] == 'e') { - replace_base_register_ref (&XEXP (*x, i), repl); + replace_ltrel_base (&XEXP (*x, i), base); } else if (fmt[i] == 'E') { for (j = 0; j < XVECLEN (*x, i); j++) - replace_base_register_ref (&XVECEXP (*x, i, j), repl); + replace_ltrel_base (&XVECEXP (*x, i, j), base); } } } -/* We keep a list of constants we which we have to add to internal +/* We keep a list of constants which we have to add to internal constant tables in the middle of large functions. */ -#define NR_C_MODES 6 +#define NR_C_MODES 7 enum machine_mode constant_modes[NR_C_MODES] = { + TImode, DFmode, DImode, SFmode, SImode, HImode, @@ -4261,6 +4185,7 @@ enum machine_mode constant_modes[NR_C_MODES] = 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, @@ -4284,11 +4209,10 @@ struct constant_pool struct constant *constants[NR_C_MODES]; rtx label; int size; - bool anchor; }; -static struct constant_pool * s390_chunkify_start PARAMS ((rtx, bool *)); -static void s390_chunkify_finish PARAMS ((struct constant_pool *, rtx)); +static struct constant_pool * s390_chunkify_start PARAMS ((void)); +static void s390_chunkify_finish PARAMS ((struct constant_pool *)); static void s390_chunkify_cancel PARAMS ((struct constant_pool *)); static struct constant_pool *s390_start_pool PARAMS ((struct constant_pool **, rtx)); @@ -4297,7 +4221,6 @@ static void s390_add_pool_insn PARAMS ((struct constant_pool *, rtx)); static struct constant_pool *s390_find_pool PARAMS ((struct constant_pool *, rtx)); static void s390_add_constant PARAMS ((struct constant_pool *, rtx, enum machine_mode)); static rtx s390_find_constant PARAMS ((struct constant_pool *, rtx, enum machine_mode)); -static void s390_add_anchor PARAMS ((struct constant_pool *)); static rtx s390_dump_pool PARAMS ((struct constant_pool *)); static void s390_free_pool PARAMS ((struct constant_pool *)); @@ -4322,7 +4245,6 @@ s390_start_pool (pool_list, insn) pool->pool_insn = NULL_RTX; pool->insns = BITMAP_XMALLOC (); pool->size = 0; - pool->anchor = FALSE; for (prev = pool_list; *prev; prev = &(*prev)->next) ; @@ -4439,19 +4361,6 @@ s390_find_constant (pool, val, mode) return offset; } -/* Set 'anchor' flag in POOL. */ - -static void -s390_add_anchor (pool) - struct constant_pool *pool; -{ - if (!pool->anchor) - { - pool->anchor = TRUE; - pool->size += 4; - } -} - /* Dump out the constants in POOL. */ static rtx @@ -4473,26 +4382,16 @@ s390_dump_pool (pool) insn = emit_label_after (pool->label, insn); INSN_ADDRESSES_NEW (insn, -1); - /* Emit anchor if we need one. */ - if (pool->anchor) - { - rtx anchor = gen_rtx_LABEL_REF (VOIDmode, pool->label); - anchor = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, anchor), 105); - anchor = gen_rtx_CONST (VOIDmode, anchor); - insn = emit_insn_after (gen_consttable_si (anchor), insn); - INSN_ADDRESSES_NEW (insn, -1); - } - /* Dump constants in descending alignment requirement order, ensuring proper alignment for every constant. */ for (i = 0; i < NR_C_MODES; i++) for (c = pool->constants[i]; c; c = c->next) { - /* Convert 104 unspecs to pool-relative references. */ + /* Convert UNSPEC_LTREL_OFFSET unspecs to pool-relative references. */ rtx value = c->value; if (GET_CODE (value) == CONST && GET_CODE (XEXP (value, 0)) == UNSPEC - && XINT (XEXP (value, 0), 1) == 104 + && XINT (XEXP (value, 0), 1) == UNSPEC_LTREL_OFFSET && XVECLEN (XEXP (value, 0), 0) == 1) { value = gen_rtx_MINUS (Pmode, XVECEXP (XEXP (value, 0), 0, 0), @@ -4547,25 +4446,20 @@ s390_free_pool (pool) } -/* Chunkify the literal pool if required. - - Code generated by this routine is allowed to use - TEMP_REG as temporary scratch register. If this is - done, TEMP_USED is set to true. */ +/* Chunkify the literal pool if required. */ #define S390_POOL_CHUNK_MIN 0xc00 #define S390_POOL_CHUNK_MAX 0xe00 static struct constant_pool * -s390_chunkify_start (temp_reg, temp_used) - rtx temp_reg; - bool *temp_used; +s390_chunkify_start (void) { 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; + rtx pending_ltrel = NULL_RTX; rtx insn; rtx (*gen_reload_base) PARAMS ((rtx, rtx)) = @@ -4581,46 +4475,59 @@ s390_chunkify_start (temp_reg, temp_used) shorten_branches (get_insns ()); - /* Scan all insns and move literals to pool chunks. - Also, emit anchor reload insns before every insn that uses - the literal pool base register as anchor pointer. */ + /* Scan all insns and move literals to pool chunks. */ for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { + /* Check for pending LTREL_BASE. */ + if (INSN_P (insn)) + { + rtx ltrel_base = find_ltrel_base (PATTERN (insn)); + if (ltrel_base) + { + if (ltrel_base == pending_ltrel) + pending_ltrel = NULL_RTX; + else + abort (); + } + } + 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); + if (!curr_pool) curr_pool = s390_start_pool (&pool_list, insn); - s390_add_constant (curr_pool, get_pool_constant (pool_ref), - get_pool_mode (pool_ref)); + s390_add_constant (curr_pool, constant, mode); s390_add_pool_insn (curr_pool, insn); - } - else if (!TARGET_64BIT && flag_pic - && find_base_register_ref (PATTERN (insn))) - { - rtx new = gen_reload_anchor (temp_reg, base_reg); - new = emit_insn_before (new, insn); - INSN_ADDRESSES_NEW (new, INSN_ADDRESSES (INSN_UID (insn))); - extra_size += 8; - *temp_used = 1; - - if (!curr_pool) - curr_pool = s390_start_pool (&pool_list, new); - - s390_add_anchor (curr_pool); - s390_add_pool_insn (curr_pool, insn); + /* Don't split the pool chunk between a LTREL_OFFSET load + and the corresponding LTREL_BASE. */ + if (GET_CODE (constant) == CONST + && GET_CODE (XEXP (constant, 0)) == UNSPEC + && XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET) + { + if (pending_ltrel) + abort (); + pending_ltrel = pool_ref; + } } } if (GET_CODE (insn) == JUMP_INSN || GET_CODE (insn) == CODE_LABEL) - if (curr_pool) - s390_add_pool_insn (curr_pool, insn); + { + if (curr_pool) + s390_add_pool_insn (curr_pool, insn); + /* An LTREL_BASE must follow within the same basic block. */ + if (pending_ltrel) + abort (); + } if (!curr_pool || INSN_ADDRESSES_SIZE () <= (size_t) INSN_UID (insn) @@ -4672,10 +4579,9 @@ s390_chunkify_start (temp_reg, temp_used) if (get_attr_length (insn) == 0) continue; - /* Don't separate insns created by s390_split_branches. */ - if (GET_CODE (insn) == INSN - && GET_CODE (PATTERN (insn)) == SET - && rtx_equal_p (SET_DEST (PATTERN (insn)), temp_reg)) + /* Don't separate LTREL_BASE from the corresponding + LTREL_OFFSET load. */ + if (pending_ltrel) continue; label = gen_label_rtx (); @@ -4698,6 +4604,8 @@ s390_chunkify_start (temp_reg, temp_used) if (curr_pool) s390_end_pool (curr_pool, NULL_RTX); + if (pending_ltrel) + abort (); /* Find all labels that are branched into @@ -4811,15 +4719,11 @@ s390_chunkify_start (temp_reg, temp_used) /* 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. - - Code generated by this routine is allowed to use - TEMP_REG as temporary scratch register. */ + all changes to the current function as required. */ static void -s390_chunkify_finish (pool_list, temp_reg) +s390_chunkify_finish (pool_list) struct constant_pool *pool_list; - rtx temp_reg; { rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER); struct constant_pool *curr_pool = NULL; @@ -4830,6 +4734,9 @@ s390_chunkify_finish (pool_list, temp_reg) for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) { + if (INSN_P (insn)) + replace_ltrel_base (&PATTERN (insn), base_reg); + curr_pool = s390_find_pool (pool_list, insn); if (!curr_pool) continue; @@ -4846,12 +4753,6 @@ s390_chunkify_finish (pool_list, temp_reg) replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr); INSN_CODE (insn) = -1; } - - else if (!TARGET_64BIT && flag_pic - && find_base_register_ref (PATTERN (insn))) - { - replace_base_register_ref (&PATTERN (insn), temp_reg); - } } } @@ -4906,7 +4807,7 @@ s390_chunkify_cancel (pool_list) remove_insn (curr_pool->pool_insn); } - /* Remove all base/anchor register reload insns. */ + /* Remove all base register reload insns. */ for (insn = get_insns (); insn; ) { @@ -4915,8 +4816,7 @@ s390_chunkify_cancel (pool_list) if (GET_CODE (insn) == INSN && GET_CODE (PATTERN (insn)) == SET && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC - && (XINT (SET_SRC (PATTERN (insn)), 1) == 210 - || XINT (SET_SRC (PATTERN (insn)), 1) == 211)) + && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPEC_RELOAD_BASE) remove_insn (insn); insn = next_insn; @@ -5231,7 +5131,7 @@ s390_reorg () struct constant_pool *pool_list; /* Try to chunkify the literal pool. */ - pool_list = s390_chunkify_start (temp_reg, &temp_used); + pool_list = s390_chunkify_start (); /* Split out-of-range branches. If this has created new literal pool entries, cancel current chunk list and @@ -5262,7 +5162,7 @@ s390_reorg () /* 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, temp_reg); + s390_chunkify_finish (pool_list); break; } @@ -5555,6 +5455,52 @@ restore_gprs (base, offset, first, last) return insn; } +/* Emit code to load the GOT register. If MAYBE_DEAD is true, + annotate generated insns with REG_MAYBE_DEAD notes. */ + +static GTY(()) rtx got_symbol; +void +s390_load_got (maybe_dead) + int maybe_dead; +{ + if (!got_symbol) + { + got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); + SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL; + } + + if (TARGET_64BIT) + { + rtx insn = emit_move_insn (pic_offset_table_rtx, got_symbol); + if (maybe_dead) + REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, + REG_NOTES (insn)); + } + else + { + rtx offset, insn; + + offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol), + UNSPEC_LTREL_OFFSET); + offset = gen_rtx_CONST (Pmode, offset); + offset = force_const_mem (Pmode, offset); + + insn = emit_move_insn (pic_offset_table_rtx, offset); + if (maybe_dead) + REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, + REG_NOTES (insn)); + + offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)), + UNSPEC_LTREL_BASE); + offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset); + + insn = emit_move_insn (pic_offset_table_rtx, offset); + if (maybe_dead) + REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, + REG_NOTES (insn)); + } +} + /* Expand the prologue into a bunch of separate insns. */ void @@ -5724,38 +5670,7 @@ s390_emit_prologue () /* Set up got pointer, if needed. */ if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM]) - { - rtx got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_"); - SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL; - - if (TARGET_64BIT) - { - insn = emit_insn (gen_movdi (pic_offset_table_rtx, - got_symbol)); - - /* It can happen that the GOT pointer isn't really needed ... */ - REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, - REG_NOTES (insn)); - } - else - { - got_symbol = gen_rtx_UNSPEC (VOIDmode, - gen_rtvec (1, got_symbol), 100); - got_symbol = gen_rtx_CONST (VOIDmode, got_symbol); - got_symbol = force_const_mem (Pmode, got_symbol); - insn = emit_move_insn (pic_offset_table_rtx, - got_symbol); - REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, - REG_NOTES (insn)); - - got_symbol = gen_rtx_REG (Pmode, BASE_REGISTER); - got_symbol = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol), 101); - got_symbol = gen_rtx_PLUS (Pmode, got_symbol, pic_offset_table_rtx); - insn = emit_move_insn (pic_offset_table_rtx, got_symbol); - REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX, - REG_NOTES (insn)); - } - } + s390_load_got (true); } /* Expand the epilogue into a bunch of separate insns. */ @@ -6649,7 +6564,7 @@ s390_function_profiler (file, labelno) op[4] = gen_rtx_SYMBOL_REF (Pmode, "_mcount"); if (flag_pic) { - op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), 113); + op[4] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[4]), UNSPEC_PLT); op[4] = gen_rtx_CONST (Pmode, op[4]); } @@ -6749,7 +6664,7 @@ s390_output_mi_thunk (file, thunk, delta, vcall_offset, function) { nonlocal = 1; op[0] = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op[0]), - TARGET_64BIT ? 113 : flag_pic == 2 ? 112 : 110); + TARGET_64BIT ? UNSPEC_PLT : UNSPEC_GOT); op[0] = gen_rtx_CONST (Pmode, op[0]); } diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index fc1af11c7ef..e5807027652 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -50,7 +50,19 @@ ;; (define_constants - [; TLS relocation specifiers + [; GOT/PLT and lt-relative accesses + (UNSPEC_LTREL_OFFSET 100) + (UNSPEC_LTREL_BASE 101) + (UNSPEC_GOTENT 110) + (UNSPEC_GOT 111) + (UNSPEC_GOTOFF 112) + (UNSPEC_PLT 113) + (UNSPEC_PLTOFF 114) + + ; Literal pool + (UNSPEC_RELOAD_BASE 210) + + ; TLS relocation specifiers (UNSPEC_TLSGD 500) (UNSPEC_TLSLDM 501) (UNSPEC_NTPOFF 502) @@ -69,7 +81,20 @@ ;; (define_constants - [; TLS support + [; Literal pool + (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 (UNSPECV_SET_TP 500) ]) @@ -6382,7 +6407,6 @@ "" " { - int plt_call = 0; rtx insn; /* Direct function calls need special treatment. */ @@ -6394,20 +6418,19 @@ replace the symbol itself with the PLT stub. */ if (flag_pic && !SYMBOL_REF_LOCAL_P (sym)) { - sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113); + sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT); sym = gen_rtx_CONST (Pmode, sym); - - plt_call = 1; } /* Unless we can use the bras(l) insn, force the routine address into a register. */ if (!TARGET_SMALL_EXEC && !TARGET_64BIT) - { - rtx target = gen_reg_rtx (Pmode); - emit_move_insn (target, sym); - sym = target; - } + { + if (flag_pic) + sym = legitimize_pic_address (sym, 0); + else + sym = force_reg (Pmode, sym); + } operands[0] = gen_rtx_MEM (QImode, sym); } @@ -6415,13 +6438,6 @@ /* Emit insn. */ insn = emit_call_insn (gen_call_exp (operands[0], operands[1], gen_rtx_REG (Pmode, RETURN_REGNUM))); - - /* In 31-bit, we must load the GOT register even if the - compiler doesn't know about it, because the PLT glue - code uses it. In 64-bit, this is not necessary. */ - if (plt_call && !TARGET_64BIT) - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); - DONE; }") @@ -6501,7 +6517,6 @@ "" " { - int plt_call = 0; rtx insn; /* Direct function calls need special treatment. */ @@ -6513,19 +6528,18 @@ replace the symbol itself with the PLT stub. */ if (flag_pic && !SYMBOL_REF_LOCAL_P (sym)) { - sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113); + sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT); sym = gen_rtx_CONST (Pmode, sym); - - plt_call = 1; } /* Unless we can use the bras(l) insn, force the routine address into a register. */ if (!TARGET_SMALL_EXEC && !TARGET_64BIT) { - rtx target = gen_reg_rtx (Pmode); - emit_move_insn (target, sym); - sym = target; + if (flag_pic) + sym = legitimize_pic_address (sym, 0); + else + sym = force_reg (Pmode, sym); } operands[1] = gen_rtx_MEM (QImode, sym); @@ -6535,13 +6549,6 @@ insn = emit_call_insn ( gen_call_value_exp (operands[0], operands[1], operands[2], gen_rtx_REG (Pmode, RETURN_REGNUM))); - - /* In 31-bit, we must load the GOT register even if the - compiler doesn't know about it, because the PLT glue - code uses it. In 64-bit, this is not necessary. */ - if (plt_call && !TARGET_64BIT) - use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); - DONE; }") @@ -6694,16 +6701,17 @@ abort (); sym = s390_tls_get_offset (); - sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), 113); + sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT); sym = gen_rtx_CONST (Pmode, sym); /* Unless we can use the bras(l) insn, force the routine address into a register. */ if (!TARGET_SMALL_EXEC && !TARGET_64BIT) { - rtx target = gen_reg_rtx (Pmode); - emit_move_insn (target, sym); - sym = target; + if (flag_pic) + sym = legitimize_pic_address (sym, 0); + else + sym = force_reg (Pmode, sym); } sym = gen_rtx_MEM (QImode, sym); @@ -6840,35 +6848,28 @@ ; (define_expand "builtin_setjmp_setup" - [(unspec [(match_operand 0 "register_operand" "a")] 1)] + [(match_operand 0 "register_operand" "")] "" - " { rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode))); rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER); emit_move_insn (base, basereg); DONE; -}") +}) (define_expand "builtin_setjmp_receiver" - [(unspec_volatile [(label_ref (match_operand 0 "" ""))] 2)] + [(match_operand 0 "" "")] "flag_pic" - " { - rtx gotreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); - rtx got = gen_rtx_SYMBOL_REF (Pmode, \"_GLOBAL_OFFSET_TABLE_\"); - SYMBOL_REF_FLAGS (got) = SYMBOL_FLAG_LOCAL; - - emit_move_insn (gotreg, got); - emit_insn (gen_rtx_USE (VOIDmode, gotreg)); + s390_load_got (false); + emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx)); DONE; -}") +}) (define_expand "builtin_longjmp" - [(unspec_volatile [(match_operand 0 "register_operand" "r")] 3)] + [(match_operand 0 "register_operand" "")] "" - " { /* The elements of the buffer are, in order: */ rtx fp = gen_rtx_MEM (Pmode, operands[0]); @@ -6876,7 +6877,7 @@ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2 * GET_MODE_SIZE (Pmode))); rtx base = gen_rtx_MEM (Pmode, plus_constant (operands[0], 4 * GET_MODE_SIZE (Pmode))); rtx basereg = gen_rtx_REG (Pmode, BASE_REGISTER); - rtx jmp = gen_rtx_REG (Pmode, 14); + rtx jmp = gen_reg_rtx (Pmode); emit_move_insn (jmp, lab); emit_move_insn (basereg, base); @@ -6888,7 +6889,7 @@ emit_insn (gen_rtx_USE (VOIDmode, basereg)); emit_indirect_jump (jmp); DONE; -}") +}) ;; These patterns say how to save and restore the stack pointer. We need not @@ -6979,56 +6980,58 @@ ; (define_insn "consttable_qi" - [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "X")] 200)] + [(unspec_volatile [(match_operand:QI 0 "consttable_operand" "X")] + UNSPECV_POOL_QI)] "" - "* { assemble_integer (operands[0], 1, BITS_PER_UNIT, 1); - return \"\"; -}" + return ""; +} [(set_attr "op_type" "NN") (set_attr "length" "1")]) (define_insn "consttable_hi" - [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "X")] 201)] + [(unspec_volatile [(match_operand:HI 0 "consttable_operand" "X")] + UNSPECV_POOL_HI)] "" - "* { assemble_integer (operands[0], 2, 2*BITS_PER_UNIT, 1); - return \"\"; -}" + return ""; +} [(set_attr "op_type" "NN") (set_attr "length" "2")]) (define_insn "consttable_si" - [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "X")] 202)] + [(unspec_volatile [(match_operand:SI 0 "consttable_operand" "X")] + UNSPECV_POOL_SI)] "" - "* -{ - if (!TARGET_64BIT && flag_pic && SYMBOLIC_CONST (operands[0])) - return \".long\\t%0\"; - - assemble_integer (operands[0], 4, 4*BITS_PER_UNIT, 1); - return \"\"; -}" + ".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")] 203)] + [(unspec_volatile [(match_operand:DI 0 "consttable_operand" "X")] + UNSPECV_POOL_DI)] "" - "* -{ - assemble_integer (operands[0], 8, 8*BITS_PER_UNIT, 1); - return \"\"; -}" + ".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")] 204)] + [(unspec_volatile [(match_operand:SF 0 "consttable_operand" "X")] + UNSPECV_POOL_SF)] "" - "* { REAL_VALUE_TYPE r; @@ -7037,15 +7040,15 @@ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); assemble_real (r, SFmode, 4*BITS_PER_UNIT); - return \"\"; -}" + return ""; +} [(set_attr "op_type" "NN") (set_attr "length" "4")]) (define_insn "consttable_df" - [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "X")] 205)] + [(unspec_volatile [(match_operand:DF 0 "consttable_operand" "X")] + UNSPECV_POOL_DF)] "" - "* { REAL_VALUE_TYPE r; @@ -7054,34 +7057,34 @@ REAL_VALUE_FROM_CONST_DOUBLE (r, operands[0]); assemble_real (r, DFmode, 8*BITS_PER_UNIT); - return \"\"; -}" + return ""; +} [(set_attr "op_type" "NN") (set_attr "length" "8")]) (define_insn "pool_start_31" - [(unspec_volatile [(const_int 0)] 206)] + [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)] "!TARGET_64BIT" ".align\\t4" [(set_attr "op_type" "NN") (set_attr "length" "2")]) (define_insn "pool_end_31" - [(unspec_volatile [(const_int 0)] 207)] + [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)] "!TARGET_64BIT" ".align\\t2" [(set_attr "op_type" "NN") (set_attr "length" "2")]) (define_insn "pool_start_64" - [(unspec_volatile [(const_int 0)] 206)] + [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)] "TARGET_64BIT" ".section\\t.rodata\;.align\\t8" [(set_attr "op_type" "NN") (set_attr "length" "0")]) (define_insn "pool_end_64" - [(unspec_volatile [(const_int 0)] 207)] + [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)] "TARGET_64BIT" ".previous" [(set_attr "op_type" "NN") @@ -7089,7 +7092,7 @@ (define_insn "reload_base_31" [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(label_ref (match_operand 1 "" ""))] 210))] + (unspec:SI [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))] "!TARGET_64BIT" "basr\\t%0,0\;la\\t%0,%1-.(%0)" [(set_attr "op_type" "NN") @@ -7098,24 +7101,14 @@ (define_insn "reload_base_64" [(set (match_operand:DI 0 "register_operand" "=a") - (unspec:DI [(label_ref (match_operand 1 "" ""))] 210))] + (unspec:DI [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))] "TARGET_64BIT" "larl\\t%0,%1" [(set_attr "op_type" "RIL") (set_attr "type" "larl")]) -(define_insn "reload_anchor" - [(set (match_operand:SI 0 "register_operand" "=a") - (unspec:SI [(match_operand:SI 1 "register_operand" "a")] 211))] - "!TARGET_64BIT" - "l\\t%0,0(%1)\;la\\t%0,0(%0,%1)" - [(set_attr "op_type" "NN") - (set_attr "type" "la") - (set_attr "atype" "agen") - (set_attr "length" "8")]) - (define_insn "pool" - [(unspec_volatile [(match_operand 0 "const_int_operand" "n")] 220)] + [(unspec_volatile [(match_operand 0 "const_int_operand" "n")] UNSPECV_POOL)] "" "* abort ();" [(set_attr "op_type" "NN") @@ -7164,7 +7157,7 @@ (set_attr "atype" "agen")]) (define_insn "literal_pool_31" - [(unspec_volatile [(const_int 0)] 300) + [(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 "" "")))] @@ -7188,7 +7181,7 @@ (set_attr "type" "larl")]) (define_insn "literal_pool_64" - [(unspec_volatile [(const_int 0)] 300) + [(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 "" "")))]