diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 34 | ||||
-rw-r--r-- | gcc/config/ia64/ia64-protos.h | 2 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.c | 326 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.h | 10 | ||||
-rw-r--r-- | gcc/config/ia64/ia64.md | 252 | ||||
-rw-r--r-- | gcc/config/ia64/sysv4.h | 7 | ||||
-rwxr-xr-x | gcc/configure | 43 | ||||
-rw-r--r-- | gcc/configure.in | 17 |
8 files changed, 580 insertions, 111 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 001ff8a..b1c1dd3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2002-05-25 Richard Henderson <rth@redhat.com> + + * configure.in (HAVE_AS_TLS): Add ia64 test. + * configure: Rebuild. + * config/ia64/ia64.c (ia64_tls_size_string, ia64_tls_size): New. + (override_options): Set it. + (TARGET_HAVE_TLS): New. + (sdata_symbolic_operand): Look for 's'. + (tls_symbolic_operand): New. + (ia64_expand_load_address): Abort for tls symbols. + (gen_tls_get_addr): New. + (gen_thread_pointer): New. + (ia64_expand_move): Split out from movdi. Handle tls symbols. + (rtx_needs_barrier): Add new unspecs. + (ia64_encode_section_info): Handle tls symbols. + (ia64_strip_name_encoding): Strip two encoding chars. + * config/ia64/ia64.h (ia64_tls_size, ia64_tls_size_string): New. + (TARGET_TLS14, TARGET_TLS22, TARGET_TLS64): New. + (TARGET_OPTIONS): Add tls-size. + (ENCODE_SECTION_INFO_CHAR): Rename from SDATA_NAME_FLAG_CHAR. + * config/ia64/ia64.md (UNSPEC_LTOFF_DTPMOD, UNSPEC_LTOFF_DTPREL, + UNSPEC_DTPREL, UNSPEC_LTOFF_TPREL, UNSPEC_TPREL, UNSPEC_LD_BASE): New. + (movqi, movhi, movsi, movdi, movti): Use ia64_expand_move. + (movsf, movdf): Likewise. + (movdi_symbolic): Use match_scratch. Don't split if we won't + have a scratch availiable. + (load_ltoff_dtpmod, load_dtprel, load_dtprel64, load_dtprel22, + add_dtprel, add_dtprel14, add_dtprel22, load_ltoff_tprel, load_tprel, + load_tprel64, load_tprel22, add_tprel, add_tprel14, add_tprel22): New. + * config/ia64/ia64-protos.h: Update. + * config/ia64/sysv4.h (ASM_OUTPUT_ALIGNED_DECL_LOCAL): Use + sdata_symbolic_operand. + (ASM_OUTPUT_LABELREF): Strip two characters. + 2002-05-25 Kazu Hirata <kazu@cs.umass.edu> * combine.c (simplify_set): Remove an unnecessary subreg. diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h index d28de45..204740a 100644 --- a/gcc/config/ia64/ia64-protos.h +++ b/gcc/config/ia64/ia64-protos.h @@ -31,6 +31,7 @@ extern int call_operand PARAMS((rtx, enum machine_mode)); extern int sdata_symbolic_operand PARAMS((rtx, enum machine_mode)); extern int got_symbolic_operand PARAMS((rtx, enum machine_mode)); extern int symbolic_operand PARAMS((rtx, enum machine_mode)); +extern int tls_symbolic_operand PARAMS((rtx, enum machine_mode)); extern int function_operand PARAMS((rtx, enum machine_mode)); extern int setjmp_operand PARAMS((rtx, enum machine_mode)); extern int move_operand PARAMS((rtx, enum machine_mode)); @@ -68,6 +69,7 @@ extern int destination_tfmode_operand PARAMS((rtx, enum machine_mode)); extern int tfreg_or_fp01_operand PARAMS((rtx, enum machine_mode)); extern int basereg_operand PARAMS((rtx, enum machine_mode)); +extern rtx ia64_expand_move PARAMS ((rtx, rtx)); extern int ia64_move_ok PARAMS((rtx, rtx)); extern int ia64_depz_field_mask PARAMS((rtx, rtx)); extern rtx ia64_gp_save_reg PARAMS((int)); diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 1517a8b..1445ae9 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -94,6 +94,13 @@ static const char * const ia64_output_reg_names[8] = /* String used with the -mfixed-range= option. */ const char *ia64_fixed_range_string; +/* Determines whether we use adds, addl, or movl to generate our + TLS immediate offsets. */ +int ia64_tls_size = 22; + +/* String used with the -mtls-size= option. */ +const char *ia64_tls_size_string; + /* Determines whether we run our final scheduling pass or not. We always avoid the normal second scheduling pass. */ static int ia64_flag_schedule_insns2; @@ -103,6 +110,8 @@ static int ia64_flag_schedule_insns2; unsigned int ia64_section_threshold; +static rtx gen_tls_get_addr PARAMS ((void)); +static rtx gen_thread_pointer PARAMS ((void)); static int find_gr_spill PARAMS ((int)); static int next_scratch_gr_reg PARAMS ((void)); static void mark_reg_gr_used_mask PARAMS ((rtx, void *)); @@ -230,6 +239,11 @@ static const struct attribute_spec ia64_attribute_table[] = #undef TARGET_SCHED_REORDER2 #define TARGET_SCHED_REORDER2 ia64_sched_reorder2 +#ifdef HAVE_AS_TLS +#undef TARGET_HAVE_TLS +#define TARGET_HAVE_TLS true +#endif + struct gcc_target targetm = TARGET_INITIALIZER; /* Return 1 if OP is a valid operand for the MEM of a CALL insn. */ @@ -266,7 +280,10 @@ sdata_symbolic_operand (op, mode) if (CONSTANT_POOL_ADDRESS_P (op)) return GET_MODE_SIZE (get_pool_mode (op)) <= ia64_section_threshold; else - return XSTR (op, 0)[0] == SDATA_NAME_FLAG_CHAR; + { + const char *str = XSTR (op, 0); + return (str[0] == ENCODE_SECTION_INFO_CHAR && str[1] == 's'); + } default: break; @@ -340,6 +357,35 @@ symbolic_operand (op, mode) return 0; } +/* Return tls_model if OP refers to a TLS symbol. */ + +int +tls_symbolic_operand (op, mode) + rtx op; + enum machine_mode mode ATTRIBUTE_UNUSED; +{ + const char *str; + + if (GET_CODE (op) != SYMBOL_REF) + return 0; + str = XSTR (op, 0); + if (str[0] != ENCODE_SECTION_INFO_CHAR) + return 0; + switch (str[1]) + { + case 'G': + return TLS_MODEL_GLOBAL_DYNAMIC; + case 'L': + return TLS_MODEL_LOCAL_DYNAMIC; + case 'i': + return TLS_MODEL_INITIAL_EXEC; + case 'l': + return TLS_MODEL_LOCAL_EXEC; + } + return 0; +} + + /* Return 1 if OP refers to a function. */ int @@ -953,6 +999,9 @@ ia64_expand_load_address (dest, src, scratch) else temp = dest; + if (tls_symbolic_operand (src, Pmode)) + abort (); + if (TARGET_AUTO_PIC) emit_insn (gen_load_gprel64 (temp, src)); else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FLAG (src)) @@ -995,6 +1044,185 @@ ia64_expand_load_address (dest, src, scratch) emit_move_insn (dest, temp); } +static rtx +gen_tls_get_addr () +{ + static rtx tga; + if (!tga) + { + tga = init_one_libfunc ("__tls_get_addr"); + ggc_add_rtx_root (&tga, 1); + } + return tga; +} + +static rtx +gen_thread_pointer () +{ + static rtx tp; + if (!tp) + { + tp = gen_rtx_REG (Pmode, 13); + RTX_UNCHANGING_P (tp); + ggc_add_rtx_root (&tp, 1); + } + return tp; +} + +rtx +ia64_expand_move (op0, op1) + rtx op0, op1; +{ + enum machine_mode mode = GET_MODE (op0); + + if (!reload_in_progress && !reload_completed && !ia64_move_ok (op0, op1)) + op1 = force_reg (mode, op1); + + if (mode == Pmode) + { + enum tls_model tls_kind; + if ((tls_kind = tls_symbolic_operand (op1, Pmode))) + { + rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns; + + switch (tls_kind) + { + case TLS_MODEL_GLOBAL_DYNAMIC: + start_sequence (); + + tga_op1 = gen_reg_rtx (Pmode); + emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1)); + tga_op1 = gen_rtx_MEM (Pmode, tga_op1); + RTX_UNCHANGING_P (tga_op1) = 1; + + tga_op2 = gen_reg_rtx (Pmode); + emit_insn (gen_load_ltoff_dtprel (tga_op2, op1)); + tga_op2 = gen_rtx_MEM (Pmode, tga_op2); + RTX_UNCHANGING_P (tga_op2) = 1; + + tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX, + LCT_CONST, Pmode, 2, tga_op1, + Pmode, tga_op2, Pmode); + + insns = get_insns (); + end_sequence (); + + emit_libcall_block (insns, op0, tga_ret, op1); + return NULL_RTX; + + case TLS_MODEL_LOCAL_DYNAMIC: + /* ??? This isn't the completely proper way to do local-dynamic + If the call to __tls_get_addr is used only by a single symbol, + then we should (somehow) move the dtprel to the second arg + to avoid the extra add. */ + start_sequence (); + + tga_op1 = gen_reg_rtx (Pmode); + emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1)); + tga_op1 = gen_rtx_MEM (Pmode, tga_op1); + RTX_UNCHANGING_P (tga_op1) = 1; + + tga_op2 = const0_rtx; + + tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX, + LCT_CONST, Pmode, 2, tga_op1, + Pmode, tga_op2, Pmode); + + insns = get_insns (); + end_sequence (); + + tga_eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), + UNSPEC_LD_BASE); + tmp = gen_reg_rtx (Pmode); + emit_libcall_block (insns, tmp, tga_ret, tga_eqv); + + if (register_operand (op0, Pmode)) + tga_ret = op0; + else + tga_ret = gen_reg_rtx (Pmode); + if (TARGET_TLS64) + { + emit_insn (gen_load_dtprel (tga_ret, op1)); + emit_insn (gen_adddi3 (tga_ret, tmp, tga_ret)); + } + else + emit_insn (gen_add_dtprel (tga_ret, tmp, op1)); + if (tga_ret == op0) + return NULL_RTX; + op1 = tga_ret; + break; + + case TLS_MODEL_INITIAL_EXEC: + tmp = gen_reg_rtx (Pmode); + emit_insn (gen_load_ltoff_tprel (tmp, op1)); + tmp = gen_rtx_MEM (Pmode, tmp); + RTX_UNCHANGING_P (tmp) = 1; + tmp = force_reg (Pmode, tmp); + + if (register_operand (op0, Pmode)) + op1 = op0; + else + op1 = gen_reg_rtx (Pmode); + emit_insn (gen_adddi3 (op1, tmp, gen_thread_pointer ())); + if (op1 == op0) + return NULL_RTX; + break; + + case TLS_MODEL_LOCAL_EXEC: + if (register_operand (op0, Pmode)) + tmp = op0; + else + tmp = gen_reg_rtx (Pmode); + if (TARGET_TLS64) + { + emit_insn (gen_load_tprel (tmp, op1)); + emit_insn (gen_adddi3 (tmp, gen_thread_pointer (), tmp)); + } + else + emit_insn (gen_add_tprel (tmp, gen_thread_pointer (), op1)); + if (tmp == op0) + return NULL_RTX; + op1 = tmp; + break; + + default: + abort (); + } + } + else if (!TARGET_NO_PIC && symbolic_operand (op1, DImode)) + { + /* Before optimization starts, delay committing to any particular + type of PIC address load. If this function gets deferred, we + may acquire information that changes the value of the + sdata_symbolic_operand predicate. + + But don't delay for function pointers. Loading a function address + actually loads the address of the descriptor not the function. + If we represent these as SYMBOL_REFs, then they get cse'd with + calls, and we end up with calls to the descriptor address instead + of calls to the function address. Functions are not candidates + for sdata anyways. + + Don't delay for LABEL_REF because the splitter loses REG_LABEL + notes. Don't delay for pool addresses on general principals; + they'll never become non-local behind our back. */ + + if (rtx_equal_function_value_matters + && GET_CODE (op1) != LABEL_REF + && ! (GET_CODE (op1) == SYMBOL_REF + && (SYMBOL_REF_FLAG (op1) + || CONSTANT_POOL_ADDRESS_P (op1) + || STRING_POOL_ADDRESS_P (op1)))) + emit_insn (gen_movdi_symbolic (op0, op1)); + else + ia64_expand_load_address (op0, op1, NULL_RTX); + return NULL_RTX; + } + } + + return op1; +} + rtx ia64_gp_save_reg (setjmp_p) int setjmp_p; @@ -3975,6 +4203,16 @@ ia64_override_options () if (ia64_fixed_range_string) fix_range (ia64_fixed_range_string); + if (ia64_tls_size_string) + { + char *end; + unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10); + if (*end || (tmp != 14 && tmp != 22 && tmp != 64)) + error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string); + else + ia64_tls_size = tmp; + } + ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload; flag_schedule_insns_after_reload = 0; @@ -4595,6 +4833,20 @@ rtx_needs_barrier (x, flags, pred) case UNSPEC: switch (XINT (x, 1)) { + case UNSPEC_LTOFF_DTPMOD: + case UNSPEC_LTOFF_DTPREL: + case UNSPEC_DTPREL: + case UNSPEC_LTOFF_TPREL: + case UNSPEC_TPREL: + case UNSPEC_PRED_REL_MUTEX: + case UNSPEC_PIC_CALL: + case UNSPEC_MF: + case UNSPEC_FETCHADD_ACQ: + case UNSPEC_BSP_VALUE: + case UNSPEC_FLUSHRS: + case UNSPEC_BUNDLE_SELECTOR: + break; + case UNSPEC_GR_SPILL: case UNSPEC_GR_RESTORE: { @@ -4614,15 +4866,6 @@ rtx_needs_barrier (x, flags, pred) need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred); break; - case UNSPEC_PRED_REL_MUTEX: - case UNSPEC_PIC_CALL: - case UNSPEC_MF: - case UNSPEC_FETCHADD_ACQ: - case UNSPEC_BSP_VALUE: - case UNSPEC_FLUSHRS: - case UNSPEC_BUNDLE_SELECTOR: - break; - case UNSPEC_ADDP4: need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred); break; @@ -6910,8 +7153,9 @@ ia64_encode_section_info (decl, first) int first ATTRIBUTE_UNUSED; { const char *symbol_str; - bool is_local, is_small; + bool is_local; rtx symbol; + char encoding = 0; if (TREE_CODE (decl) == FUNCTION_DECL) { @@ -6930,40 +7174,66 @@ ia64_encode_section_info (decl, first) is_local = (*targetm.binds_local_p) (decl); + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) + { + enum tls_model kind; + if (!flag_pic) + { + if (is_local) + kind = TLS_MODEL_LOCAL_EXEC; + else + kind = TLS_MODEL_INITIAL_EXEC; + } + else if (is_local) + kind = TLS_MODEL_LOCAL_DYNAMIC; + else + kind = TLS_MODEL_GLOBAL_DYNAMIC; + if (kind < flag_tls_default) + kind = flag_tls_default; + + encoding = " GLil"[kind]; + } /* Determine if DECL will wind up in .sdata/.sbss. */ - is_small = ia64_in_small_data_p (decl); + else if (is_local && ia64_in_small_data_p (decl)) + encoding = 's'; /* Finally, encode this into the symbol string. */ - if (is_local && is_small) + if (encoding) { char *newstr; size_t len; - if (symbol_str[0] == SDATA_NAME_FLAG_CHAR) - return; + if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR) + { + if (encoding == symbol_str[1]) + return; + /* ??? Sdata became thread or thread becaome not thread. Lose. */ + abort (); + } - len = strlen (symbol_str) + 1; - newstr = alloca (len + 1); - newstr[0] = SDATA_NAME_FLAG_CHAR; - memcpy (newstr + 1, symbol_str, len); + len = strlen (symbol_str); + newstr = alloca (len + 3); + newstr[0] = ENCODE_SECTION_INFO_CHAR; + newstr[1] = encoding; + memcpy (newstr + 2, symbol_str, len + 1); - XSTR (symbol, 0) = ggc_alloc_string (newstr, len); + XSTR (symbol, 0) = ggc_alloc_string (newstr, len + 2); } - /* This decl is marked as being in small data/bss but it shouldn't - be; one likely explanation for this is that the decl has been - moved into a different section from the one it was in when - targetm.encode_section_info was first called. Remove the '@'. */ - else if (symbol_str[0] == SDATA_NAME_FLAG_CHAR) - XSTR (symbol, 0) = ggc_strdup (symbol_str + 1); + /* This decl is marked as being in small data/bss but it shouldn't be; + one likely explanation for this is that the decl has been moved into + a different section from the one it was in when encode_section_info + was first called. Remove the encoding. */ + else if (symbol_str[0] == ENCODE_SECTION_INFO_CHAR) + XSTR (symbol, 0) = ggc_strdup (symbol_str + 2); } static const char * ia64_strip_name_encoding (str) const char *str; { - if (str[0] == SDATA_NAME_FLAG_CHAR) - str++; + if (str[0] == ENCODE_SECTION_INFO_CHAR) + str += 2; if (str[0] == '*') str++; return str; diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h index 0d3d362..d1e0556 100644 --- a/gcc/config/ia64/ia64.h +++ b/gcc/config/ia64/ia64.h @@ -109,6 +109,11 @@ extern int target_flags; #define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM) +extern int ia64_tls_size; +#define TARGET_TLS14 (ia64_tls_size == 14) +#define TARGET_TLS22 (ia64_tls_size == 22) +#define TARGET_TLS64 (ia64_tls_size == 64) + /* This macro defines names of command options to set and clear bits in `target_flags'. Its definition is an initializer with a subgrouping for each command option. */ @@ -177,10 +182,13 @@ extern int target_flags; subgrouping for each command option. */ extern const char *ia64_fixed_range_string; +extern const char *ia64_tls_size_string; #define TARGET_OPTIONS \ { \ { "fixed-range=", &ia64_fixed_range_string, \ N_("Specify range of registers to make fixed")}, \ + { "tls-size=", &ia64_tls_size_string, \ + N_("Specify bit size of immediate TLS offsets")}, \ } /* Sometimes certain combinations of command options do not make sense on a @@ -1774,7 +1782,7 @@ do { \ #define BSS_SECTION_ASM_OP "\t.bss" -#define SDATA_NAME_FLAG_CHAR '@' +#define ENCODE_SECTION_INFO_CHAR '@' #define IA64_DEFAULT_GVALUE 8 diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md index d81d6ac..8bfffe3 100644 --- a/gcc/config/ia64/ia64.md +++ b/gcc/config/ia64/ia64.md @@ -49,20 +49,28 @@ ;; ??? Need a better way to describe alternate fp status registers. (define_constants - [(UNSPEC_GR_SPILL 1) - (UNSPEC_GR_RESTORE 2) - (UNSPEC_FR_SPILL 3) - (UNSPEC_FR_RESTORE 4) - (UNSPEC_FR_RECIP_APPROX 5) - (UNSPEC_PRED_REL_MUTEX 7) - (UNSPEC_POPCNT 8) - (UNSPEC_PIC_CALL 9) - (UNSPEC_MF 12) - (UNSPEC_CMPXCHG_ACQ 13) - (UNSPEC_FETCHADD_ACQ 19) - (UNSPEC_BSP_VALUE 20) - (UNSPEC_FLUSHRS 21) - (UNSPEC_BUNDLE_SELECTOR 22) + [; Relocations + (UNSPEC_LTOFF_DTPMOD 0) + (UNSPEC_LTOFF_DTPREL 1) + (UNSPEC_DTPREL 2) + (UNSPEC_LTOFF_TPREL 3) + (UNSPEC_TPREL 4) + + (UNSPEC_LD_BASE 9) + (UNSPEC_GR_SPILL 10) + (UNSPEC_GR_RESTORE 11) + (UNSPEC_FR_SPILL 12) + (UNSPEC_FR_RESTORE 13) + (UNSPEC_FR_RECIP_APPROX 14) + (UNSPEC_PRED_REL_MUTEX 15) + (UNSPEC_POPCNT 16) + (UNSPEC_PIC_CALL 17) + (UNSPEC_MF 18) + (UNSPEC_CMPXCHG_ACQ 19) + (UNSPEC_FETCHADD_ACQ 20) + (UNSPEC_BSP_VALUE 21) + (UNSPEC_FLUSHRS 22) + (UNSPEC_BUNDLE_SELECTOR 23) (UNSPEC_ADDP4 24) (UNSPEC_PROLOGUE_USE 25) ]) @@ -72,9 +80,9 @@ (UNSPECV_BLOCKAGE 1) (UNSPECV_INSN_GROUP_BARRIER 2) (UNSPECV_BREAK 3) - (UNSPECV_SET_BSP 5) - (UNSPECV_PSAC_ALL 8) ; pred.safe_across_calls - (UNSPECV_PSAC_NORMAL 9) + (UNSPECV_SET_BSP 4) + (UNSPECV_PSAC_ALL 5) ; pred.safe_across_calls + (UNSPECV_PSAC_NORMAL 6) ]) ;; :::::::::::::::::::: @@ -276,9 +284,10 @@ (match_operand:QI 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (QImode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn "*movqi_internal" @@ -300,9 +309,10 @@ (match_operand:HI 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (HImode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn "*movhi_internal" @@ -324,9 +334,10 @@ (match_operand:SI 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (SImode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn "*movsi_internal" @@ -352,30 +363,10 @@ (match_operand:DI 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (DImode, operands[1]); - if (! TARGET_NO_PIC && symbolic_operand (operands[1], DImode)) - { - /* Before optimization starts, delay committing to any particular - type of PIC address load. If this function gets deferred, we - may acquire information that changes the value of the - sdata_symbolic_operand predicate. */ - /* But don't delay for function pointers. Loading a function address - actually loads the address of the descriptor not the function. - If we represent these as SYMBOL_REFs, then they get cse'd with - calls, and we end up with calls to the descriptor address instead of - calls to the function address. Functions are not candidates for - sdata anyways. */ - if (rtx_equal_function_value_matters - && ! (GET_CODE (operands[1]) == SYMBOL_REF - && SYMBOL_REF_FLAG (operands[1]))) - emit_insn (gen_movdi_symbolic (operands[0], operands[1], - gen_reg_rtx (DImode))); - else - ia64_expand_load_address (operands[0], operands[1], NULL_RTX); - DONE; - } + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) ;; This is used during early compilation to delay the decision on @@ -384,19 +375,22 @@ ;; deferred functions, since we may acquire additional information ;; on the variables used in the meantime. -;; ??? This causes us to lose REG_LABEL notes, because the insn splitter -;; does not attempt to preserve any REG_NOTES on the input instruction. - (define_insn_and_split "movdi_symbolic" [(set (match_operand:DI 0 "register_operand" "=r") (match_operand:DI 1 "symbolic_operand" "s")) - (clobber (match_operand:DI 2 "register_operand" "+r")) + (clobber (match_scratch:DI 2 "=r")) (use (reg:DI 1))] "" "* abort ();" - "" + "!no_new_pseudos || reload_completed" [(const_int 0)] - { ia64_expand_load_address (operands[0], operands[1], operands[2]); DONE; }) +{ + rtx scratch = operands[2]; + if (!reload_completed) + gen_reg_rtx (Pmode); + ia64_expand_load_address (operands[0], operands[1], scratch); + DONE; +}) (define_insn "*movdi_internal" [(set (match_operand:DI 0 "destination_operand" @@ -505,6 +499,131 @@ "addl %0 = @ltoff(%1), gp" [(set_attr "itanium_class" "ialu")]) +(define_insn "load_ltoff_dtpmod" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (reg:DI 1) + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_LTOFF_DTPMOD)))] + "" + "addl %0 = @ltoff(@dtpmod(%1)), gp" + [(set_attr "itanium_class" "ialu")]) + +(define_insn "load_ltoff_dtprel" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (reg:DI 1) + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_LTOFF_DTPREL)))] + "" + "addl %0 = @ltoff(@dtprel(%1)), gp" + [(set_attr "itanium_class" "ialu")]) + +(define_expand "load_dtprel" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_DTPREL))] + "" + "") + +(define_insn "*load_dtprel64" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_DTPREL))] + "TARGET_TLS64" + "movl %0 = @dtprel(%1)" + [(set_attr "itanium_class" "long_i")]) + +(define_insn "*load_dtprel22" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_DTPREL))] + "" + "addl %0 = @dtprel(%1), r0" + [(set_attr "itanium_class" "ialu")]) + +(define_expand "add_dtprel" + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_DTPREL)))] + "!TARGET_TLS64" + "") + +(define_insn "*add_dtprel14" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "register_operand" "r") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_DTPREL)))] + "TARGET_TLS14" + "adds %0 = @dtprel(%2), %1" + [(set_attr "itanium_class" "ialu")]) + +(define_insn "*add_dtprel22" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "register_operand" "a") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_DTPREL)))] + "TARGET_TLS22" + "addl %0 = @dtprel(%2), %1" + [(set_attr "itanium_class" "ialu")]) + +(define_insn "load_ltoff_tprel" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (reg:DI 1) + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_LTOFF_TPREL)))] + "" + "addl %0 = @ltoff(@tprel(%1)), gp" + [(set_attr "itanium_class" "ialu")]) + +(define_expand "load_tprel" + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_TPREL))] + "" + "") + +(define_insn "*load_tprel64" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_TPREL))] + "TARGET_TLS64" + "movl %0 = @tprel(%1)" + [(set_attr "itanium_class" "long_i")]) + +(define_insn "*load_tprel22" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")] + UNSPEC_TPREL))] + "" + "addl %0 = @tprel(%1), r0" + [(set_attr "itanium_class" "ialu")]) + +(define_expand "add_tprel" + [(set (match_operand:DI 0 "register_operand" "") + (plus:DI (match_operand:DI 1 "register_operand" "") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_TPREL)))] + "!TARGET_TLS64" + "") + +(define_insn "*add_tprel14" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "register_operand" "r") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_TPREL)))] + "TARGET_TLS14" + "adds %0 = @tprel(%2), %1" + [(set_attr "itanium_class" "ialu")]) + +(define_insn "*add_tprel22" + [(set (match_operand:DI 0 "register_operand" "=r") + (plus:DI (match_operand:DI 1 "register_operand" "a") + (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")] + UNSPEC_TPREL)))] + "TARGET_TLS22" + "addl %0 = @tprel(%2), %1" + [(set_attr "itanium_class" "ialu")]) + ;; With no offsettable memory references, we've got to have a scratch ;; around to play with the second word. (define_expand "movti" @@ -513,9 +632,10 @@ (clobber (match_scratch:DI 2 ""))])] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (TImode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn_and_split "*movti_internal" @@ -630,9 +750,10 @@ (match_operand:SF 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (SFmode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn "*movsf_internal" @@ -655,9 +776,10 @@ (match_operand:DF 1 "general_operand" ""))] "" { - if (! reload_in_progress && ! reload_completed - && ! ia64_move_ok (operands[0], operands[1])) - operands[1] = force_reg (DFmode, operands[1]); + rtx op1 = ia64_expand_move (operands[0], operands[1]); + if (!op1) + DONE; + operands[1] = op1; }) (define_insn "*movdf_internal" diff --git a/gcc/config/ia64/sysv4.h b/gcc/config/ia64/sysv4.h index 1684db1..164beba 100644 --- a/gcc/config/ia64/sysv4.h +++ b/gcc/config/ia64/sysv4.h @@ -42,8 +42,7 @@ extern int size_directive_output; #undef ASM_OUTPUT_ALIGNED_LOCAL #define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \ do { \ - if ((DECL) \ - && XSTR (XEXP (DECL_RTL (DECL), 0), 0)[0] == SDATA_NAME_FLAG_CHAR) \ + if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \ sbss_section (); \ else \ bss_section (); \ @@ -62,8 +61,8 @@ do { \ #define ASM_OUTPUT_LABELREF(STREAM, NAME) \ do { \ const char *name_ = NAME; \ - if (*name_ == SDATA_NAME_FLAG_CHAR) \ - name_++; \ + if (*name_ == ENCODE_SECTION_INFO_CHAR) \ + name_ += 2; \ if (*name_ == '*') \ name_++; \ else \ diff --git a/gcc/configure b/gcc/configure index 483178d..9db1b43 100755 --- a/gcc/configure +++ b/gcc/configure @@ -7416,6 +7416,23 @@ foo: .long 25 tls_first_major=2 tls_first_minor=13 ;; + ia64-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: data8 25 + .text + addl r16 = @ltoff(@dtpmod(foo#)), gp + addl r17 = @ltoff(@dtprel(foo#)), gp + addl r18 = @ltoff(@tprel(foo#)), gp + addl r19 = @dtprel(foo#), gp + adds r21 = @dtprel(foo#), r13 + movl r23 = @dtprel(foo#) + addl r20 = @tprel(foo#), gp + adds r22 = @tprel(foo#), r13 + movl r24 = @tprel(foo#)' + tls_first_major=2 + tls_first_minor=13 + ;; esac if test -z "$tls_first_major"; then : @@ -7446,7 +7463,7 @@ case "$target" in # All TARGET_ABI_OSF targets. alpha*-*-osf* | alpha*-*-linux* | alpha*-*-*bsd*) echo $ac_n "checking assembler supports explicit relocations""... $ac_c" 1>&6 -echo "configure:7450: checking assembler supports explicit relocations" >&5 +echo "configure:7467: checking assembler supports explicit relocations" >&5 if eval "test \"`echo '$''{'gcc_cv_as_explicit_relocs'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7496,7 +7513,7 @@ EOF ;; sparc*-*-*) echo $ac_n "checking assembler .register pseudo-op support""... $ac_c" 1>&6 -echo "configure:7500: checking assembler .register pseudo-op support" >&5 +echo "configure:7517: checking assembler .register pseudo-op support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_register_pseudo_op'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7524,7 +7541,7 @@ EOF fi echo $ac_n "checking assembler supports -relax""... $ac_c" 1>&6 -echo "configure:7528: checking assembler supports -relax" >&5 +echo "configure:7545: checking assembler supports -relax" >&5 if eval "test \"`echo '$''{'gcc_cv_as_relax_opt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7552,7 +7569,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs""... $ac_c" 1>&6 -echo "configure:7556: checking assembler and linker support unaligned pc related relocs" >&5 +echo "configure:7573: checking assembler and linker support unaligned pc related relocs" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7579,7 +7596,7 @@ EOF fi echo $ac_n "checking assembler and linker support unaligned pc related relocs against hidden symbols""... $ac_c" 1>&6 -echo "configure:7583: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 +echo "configure:7600: checking assembler and linker support unaligned pc related relocs against hidden symbols" >&5 if eval "test \"`echo '$''{'gcc_cv_as_sparc_ua_pcrel_hidden'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7620,7 +7637,7 @@ EOF if test "x$gcc_cv_as_flags64" != xno; then echo $ac_n "checking for assembler offsetable %lo() support""... $ac_c" 1>&6 -echo "configure:7624: checking for assembler offsetable %lo() support" >&5 +echo "configure:7641: checking for assembler offsetable %lo() support" >&5 if eval "test \"`echo '$''{'gcc_cv_as_offsetable_lo10'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7660,7 +7677,7 @@ EOF i[34567]86-*-* | x86_64-*-*) echo $ac_n "checking assembler instructions""... $ac_c" 1>&6 -echo "configure:7664: checking assembler instructions" >&5 +echo "configure:7681: checking assembler instructions" >&5 gcc_cv_as_instructions= if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then if test "$gcc_cv_gas_major_version" -eq 2 -a "$gcc_cv_gas_minor_version" -ge 9 -o "$gcc_cv_gas_major_version" -gt 2; then @@ -7687,7 +7704,7 @@ EOF echo "$ac_t""$gcc_cv_as_instructions" 1>&6 echo $ac_n "checking assembler GOTOFF in data directives""... $ac_c" 1>&6 -echo "configure:7691: checking assembler GOTOFF in data directives" >&5 +echo "configure:7708: checking assembler GOTOFF in data directives" >&5 gcc_cv_as_gotoff_in_data=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x then @@ -7717,7 +7734,7 @@ EOF esac echo $ac_n "checking assembler dwarf2 debug_line support""... $ac_c" 1>&6 -echo "configure:7721: checking assembler dwarf2 debug_line support" >&5 +echo "configure:7738: checking assembler dwarf2 debug_line support" >&5 gcc_cv_as_dwarf2_debug_line=no # ??? Not all targets support dwarf2 debug_line, even within a version # of gas. Moreover, we need to emit a valid instruction to trigger any @@ -7773,7 +7790,7 @@ fi echo "$ac_t""$gcc_cv_as_dwarf2_debug_line" 1>&6 echo $ac_n "checking assembler --gdwarf2 support""... $ac_c" 1>&6 -echo "configure:7777: checking assembler --gdwarf2 support" >&5 +echo "configure:7794: checking assembler --gdwarf2 support" >&5 gcc_cv_as_gdwarf2_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7802,7 +7819,7 @@ fi echo "$ac_t""$gcc_cv_as_gdwarf2_flag" 1>&6 echo $ac_n "checking assembler --gstabs support""... $ac_c" 1>&6 -echo "configure:7806: checking assembler --gstabs support" >&5 +echo "configure:7823: checking assembler --gstabs support" >&5 gcc_cv_as_gstabs_flag=no if test x$gcc_cv_gas_major_version != x -a x$gcc_cv_gas_minor_version != x; then @@ -7830,7 +7847,7 @@ fi echo "$ac_t""$gcc_cv_as_gstabs_flag" 1>&6 echo $ac_n "checking linker PT_GNU_EH_FRAME support""... $ac_c" 1>&6 -echo "configure:7834: checking linker PT_GNU_EH_FRAME support" >&5 +echo "configure:7851: checking linker PT_GNU_EH_FRAME support" >&5 gcc_cv_ld_eh_frame_hdr=no if test x$gcc_cv_gld_major_version != x -a x$gcc_cv_gld_minor_version != x; then if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 12 -o "$gcc_cv_gld_major_version" -gt 2 && grep 'EMUL = elf' ../ld/Makefile > /dev/null; then @@ -7993,7 +8010,7 @@ fi echo $ac_n "checking whether to enable maintainer-specific portions of Makefiles""... $ac_c" 1>&6 -echo "configure:7997: checking whether to enable maintainer-specific portions of Makefiles" >&5 +echo "configure:8014: checking whether to enable maintainer-specific portions of Makefiles" >&5 # Check whether --enable-maintainer-mode or --disable-maintainer-mode was given. if test "${enable_maintainer_mode+set}" = set; then enableval="$enable_maintainer_mode" diff --git a/gcc/configure.in b/gcc/configure.in index 8dcb671..55ad7c4 100644 --- a/gcc/configure.in +++ b/gcc/configure.in @@ -1743,6 +1743,23 @@ foo: .long 25 tls_first_major=2 tls_first_minor=13 ;; + ia64-*-*) + conftest_s=' + .section ".tdata","awT",@progbits +foo: data8 25 + .text + addl r16 = @ltoff(@dtpmod(foo#)), gp + addl r17 = @ltoff(@dtprel(foo#)), gp + addl r18 = @ltoff(@tprel(foo#)), gp + addl r19 = @dtprel(foo#), gp + adds r21 = @dtprel(foo#), r13 + movl r23 = @dtprel(foo#) + addl r20 = @tprel(foo#), gp + adds r22 = @tprel(foo#), r13 + movl r24 = @tprel(foo#)' + tls_first_major=2 + tls_first_minor=13 + ;; esac if test -z "$tls_first_major"; then : |