+2005-05-25 Eric Botcazou <ebotcazou@libertysurf.fr>
+
+ PR target/21412
+ * config/sparc/sparc.h (SPARC_SYMBOL_REF_TLS_P): New macro
+ * config/sparc/sparc-protos.h (tls_symbolic_operand): Delete.
+ (sparc_tls_referenced_p): New prototype.
+ * config/sparc/sparc.c (tls_symbolic_operand): Delete.
+ (sparc_expand_move): Look for TLS addresses with constant offsets.
+ (legitimate_constant_p): Use SPARC_SYMBOL_REF_TLS_P instead of
+ tls_symbolic_operand.
+ (legitimate_pic_operand_p): Likewise.
+ (legitimate_address_p): Likewise.
+ (legitimize_address): Likewise.
+ (sparc_tls_symbol_ref_1): New function.
+ (sparc_tls_referenced_p): New function.
+ * config/sparc/predicates.md (tgd_symbolic_operand): Use
+ SYMBOL_REF_TLS_MODEL instead of tls_symbolic_operand.
+ (tld_symbolic_operand): Likewise.
+ (tie_symbolic_operand): Likewise.
+ (tle_symbolic_operand): Likewise.
+
2005-05-24 DJ Delorie <dj@redhat.com>
* common.opt (-Wattributes): New. Default true.
;; Return true if OP is a symbolic operand for the TLS Global Dynamic model.
(define_predicate "tgd_symbolic_operand"
(and (match_code "symbol_ref")
- (match_test "tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
;; Return true if OP is a symbolic operand for the TLS Local Dynamic model.
(define_predicate "tld_symbolic_operand"
(and (match_code "symbol_ref")
- (match_test "tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
;; Return true if OP is a symbolic operand for the TLS Initial Exec model.
(define_predicate "tie_symbolic_operand"
(and (match_code "symbol_ref")
- (match_test "tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC")))
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC")))
;; Return true if OP is a symbolic operand for the TLS Local Exec model.
(define_predicate "tle_symbolic_operand"
(and (match_code "symbol_ref")
- (match_test "tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC")))
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC")))
;; Return true if the operand is an argument used in generating PIC references
;; in either the medium/low or embedded medium/anywhere code models on V9.
extern int zero_operand (rtx, enum machine_mode);
extern int fp_zero_operand (rtx, enum machine_mode);
extern int reg_or_0_operand (rtx, enum machine_mode);
-extern int tls_symbolic_operand (rtx);
extern int empty_delay_slot (rtx);
extern int eligible_for_return_delay (rtx);
extern int eligible_for_sibcall_delay (rtx);
extern int fp_sethi_p (rtx);
extern int fp_mov_p (rtx);
extern int fp_high_losum_p (rtx);
+extern bool sparc_tls_referenced_p (rtx);
extern int mem_min_alignment (rtx, int);
extern int pic_address_needs_scratch (rtx);
extern int reg_unused_after (rtx, rtx);
return 0;
}
-/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
- otherwise return 0. */
-
-int
-tls_symbolic_operand (rtx op)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
/* Expand a move instruction. Return true if all work is done. */
bool
}
/* Fixup TLS cases. */
- if (tls_symbolic_operand (operands [1]))
- operands[1] = legitimize_tls_address (operands[1]);
+ if (TARGET_HAVE_TLS
+ && CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && sparc_tls_referenced_p (operands [1]))
+ {
+ rtx sym = operands[1];
+ rtx addend = NULL;
+ if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (sym, 0), 1);
+ sym = XEXP (XEXP (sym, 0), 0);
+ }
+
+ gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
+
+ sym = legitimize_tls_address (sym);
+ if (addend)
+ {
+ sym = gen_rtx_PLUS (mode, sym, addend);
+ sym = force_operand (sym, operands[0]);
+ }
+ operands[1] = sym;
+ }
+
/* Fixup PIC cases. */
if (flag_pic && CONSTANT_P (operands[1]))
{
/* Offsets of TLS symbols are never valid.
Discourage CSE from creating them. */
if (GET_CODE (inner) == PLUS
- && tls_symbolic_operand (XEXP (inner, 0)))
+ && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
return false;
break;
{
if (pic_address_needs_scratch (x))
return false;
- if (tls_symbolic_operand (x)
+ if (SPARC_SYMBOL_REF_TLS_P (x)
|| (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
- && tls_symbolic_operand (XEXP (XEXP (x, 0), 0))))
+ && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
return false;
return true;
}
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
&& GET_CODE (rs2) != MEM
- && !tls_symbolic_operand (rs2)
+ && ! SPARC_SYMBOL_REF_TLS_P (rs2)
&& (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
&& (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
|| ((REG_P (rs1)
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
- if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
return 0;
}
}
rs1 = XEXP (addr, 0);
imm1 = XEXP (addr, 1);
- if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
return 0;
/* We can't allow TFmode in 32-bit mode, because an offset greater
/* Construct the SYMBOL_REF for the tls_get_offset function. */
static GTY(()) rtx sparc_tls_symbol;
+
static rtx
sparc_tls_get_addr (void)
{
return temp;
}
+/* Return 1 if *X is a thread-local symbol. */
+
+static int
+sparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ return SPARC_SYMBOL_REF_TLS_P (*x);
+}
+
+/* Return 1 if X contains a thread-local symbol. */
+
+bool
+sparc_tls_referenced_p (rtx x)
+{
+ if (!TARGET_HAVE_TLS)
+ return false;
+
+ return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
+}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
if (x != orig_x && legitimate_address_p (mode, x, FALSE))
return x;
- if (tls_symbolic_operand (x))
+ if (SPARC_SYMBOL_REF_TLS_P (x))
x = legitimize_tls_address (x);
else if (flag_pic)
x = legitimize_pic_address (x, mode, 0);