Introduce TLS descriptors for i386 and x86_64.

* config/i386/i386.h (TARGET_GNU2_TLS): New macro.
(TARGET_ANY_GNU_TLS): New macro.
(enum tls_dialect): Added TLS_DIALECT_GNU2.
(struct machine_function): Add tls_descriptor_call_expanded_p.
(ix86_tls_descriptor_calls_expande_in_cfun): New macro.
(ix86_current_function_calls_tls_descriptor): Likewise.
* config/i386/i386.c (ix86_tls_dialect): Fix typo in comment.
(override_options): Introduce gnu2 tls dialect.
(ix86_frame_pointer_required): Functions containing TLSCALLs are
not leaves.
(ix86_select_alt_pic_regnum, ix86_compute_frame_layout):
Likewise.
(legitimize_tls_address): Adjust logic for GNU2 TLS.
(ix86_init_machine_status): Initialize new field.
(ix86_tls_get_addr): Use TARGET_ANY_GNU_TLS.
(ix86_tls_module_base): New.
* config/i386/i386-protos.h (ix86_tls_module_base): Declare it.
* config/i386/i386.md (UNSPEC_TLSDESC): New constant.
(tls_global_dynamic_32, tls_global_dynamic_64): Handle GNU2 TLS.
(tls_local_dynamic_base_32, tls_local_dynamic_base_64): Likewise.
(tls_dynamic_gnu2_32, *tls_dynamic_lea_32): New patterns.
(*tls_dynamic_call_32, *tls_dynamic_gnu2_combine_32): Likewise.
(tls_dynamic_gnu2_64, *tls_dynamic_lea_64): Likewise.
(*tls_dynamic_call_64, *tls_dynamic_gnu2_combine_64): Likewise.
* config/i386/predicates.md (tls_modbase_operand): New.
(tp_or_register_operand): New.

From-SVN: r109934
This commit is contained in:
Alexandre Oliva 2006-01-19 00:40:16 +00:00 committed by Alexandre Oliva
parent 7dbca013b2
commit 5bf5a10b1c
6 changed files with 301 additions and 21 deletions

View File

@ -1,3 +1,33 @@
2006-01-18 Alexandre Oliva <aoliva@redhat.com>
Introduce TLS descriptors for i386 and x86_64.
* config/i386/i386.h (TARGET_GNU2_TLS): New macro.
(TARGET_ANY_GNU_TLS): New macro.
(enum tls_dialect): Added TLS_DIALECT_GNU2.
(struct machine_function): Add tls_descriptor_call_expanded_p.
(ix86_tls_descriptor_calls_expande_in_cfun): New macro.
(ix86_current_function_calls_tls_descriptor): Likewise.
* config/i386/i386.c (ix86_tls_dialect): Fix typo in comment.
(override_options): Introduce gnu2 tls dialect.
(ix86_frame_pointer_required): Functions containing TLSCALLs are
not leaves.
(ix86_select_alt_pic_regnum, ix86_compute_frame_layout):
Likewise.
(legitimize_tls_address): Adjust logic for GNU2 TLS.
(ix86_init_machine_status): Initialize new field.
(ix86_tls_get_addr): Use TARGET_ANY_GNU_TLS.
(ix86_tls_module_base): New.
* config/i386/i386-protos.h (ix86_tls_module_base): Declare it.
* config/i386/i386.md (UNSPEC_TLSDESC): New constant.
(tls_global_dynamic_32, tls_global_dynamic_64): Handle GNU2 TLS.
(tls_local_dynamic_base_32, tls_local_dynamic_base_64): Likewise.
(tls_dynamic_gnu2_32, *tls_dynamic_lea_32): New patterns.
(*tls_dynamic_call_32, *tls_dynamic_gnu2_combine_32): Likewise.
(tls_dynamic_gnu2_64, *tls_dynamic_lea_64): Likewise.
(*tls_dynamic_call_64, *tls_dynamic_gnu2_combine_64): Likewise.
* config/i386/predicates.md (tls_modbase_operand): New.
(tp_or_register_operand): New.
2006-01-18 Daniel Berlin <dberlin@dberlin.org>
* ipa-reference.c (check_operand): Allow FUNCTION_DECL.

View File

@ -1,6 +1,7 @@
/* Definitions of target machine for GCC for IA-32.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1996, 1997, 1998, 1999,
2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GCC.
@ -179,6 +180,7 @@ extern int x86_field_alignment (tree, int);
#endif
extern rtx ix86_tls_get_addr (void);
extern rtx ix86_tls_module_base (void);
extern void ix86_expand_vector_init (bool, rtx, rtx);
extern void ix86_expand_vector_set (bool, rtx, rtx, int);

View File

@ -1,6 +1,6 @@
/* Subroutines used for code generation on IA-32.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@ -876,7 +876,7 @@ struct ix86_frame
enum cmodel ix86_cmodel;
/* Asm dialect. */
enum asm_dialect ix86_asm_dialect = ASM_ATT;
/* TLS dialext. */
/* TLS dialects. */
enum tls_dialect ix86_tls_dialect = TLS_DIALECT_GNU;
/* Which unit we are generating floating point math for. */
@ -1626,6 +1626,8 @@ override_options (void)
{
if (strcmp (ix86_tls_dialect_string, "gnu") == 0)
ix86_tls_dialect = TLS_DIALECT_GNU;
else if (strcmp (ix86_tls_dialect_string, "gnu2") == 0)
ix86_tls_dialect = TLS_DIALECT_GNU2;
else if (strcmp (ix86_tls_dialect_string, "sun") == 0)
ix86_tls_dialect = TLS_DIALECT_SUN;
else
@ -4415,7 +4417,8 @@ ix86_frame_pointer_required (void)
the frame pointer by default. Turn it back on now if we've not
got a leaf function. */
if (TARGET_OMIT_LEAF_FRAME_POINTER
&& (!current_function_is_leaf))
&& (!current_function_is_leaf
|| ix86_current_function_calls_tls_descriptor))
return 1;
if (current_function_profile)
@ -4597,7 +4600,8 @@ gen_push (rtx arg)
static unsigned int
ix86_select_alt_pic_regnum (void)
{
if (current_function_is_leaf && !current_function_profile)
if (current_function_is_leaf && !current_function_profile
&& !ix86_current_function_calls_tls_descriptor)
{
int i;
for (i = 2; i >= 0; --i)
@ -4788,7 +4792,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
expander assumes that last current_function_outgoing_args_size
of stack frame are unused. */
if (ACCUMULATE_OUTGOING_ARGS
&& (!current_function_is_leaf || current_function_calls_alloca))
&& (!current_function_is_leaf || current_function_calls_alloca
|| ix86_current_function_calls_tls_descriptor))
{
offset += current_function_outgoing_args_size;
frame->outgoing_arguments_size = current_function_outgoing_args_size;
@ -4798,7 +4803,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
/* Align stack boundary. Only needed if we're calling another function
or using alloca. */
if (!current_function_is_leaf || current_function_calls_alloca)
if (!current_function_is_leaf || current_function_calls_alloca
|| ix86_current_function_calls_tls_descriptor)
frame->padding2 = ((offset + preferred_alignment - 1)
& -preferred_alignment) - offset;
else
@ -4819,7 +4825,8 @@ ix86_compute_frame_layout (struct ix86_frame *frame)
frame->save_regs_using_mov = false;
if (TARGET_RED_ZONE && current_function_sp_is_unchanging
&& current_function_is_leaf)
&& current_function_is_leaf
&& !ix86_current_function_calls_tls_descriptor)
{
frame->red_zone_size = frame->to_allocate;
if (frame->save_regs_using_mov)
@ -6351,14 +6358,16 @@ get_thread_pointer (int to_reg)
static rtx
legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
{
rtx dest, base, off, pic;
rtx dest, base, off, pic, tp;
int type;
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
dest = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
if (TARGET_64BIT && ! TARGET_GNU2_TLS)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns;
@ -6369,13 +6378,24 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
emit_libcall_block (insns, dest, rax, x);
}
else if (TARGET_64BIT && TARGET_GNU2_TLS)
emit_insn (gen_tls_global_dynamic_64 (dest, x));
else
emit_insn (gen_tls_global_dynamic_32 (dest, x));
if (TARGET_GNU2_TLS)
{
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
}
break;
case TLS_MODEL_LOCAL_DYNAMIC:
base = gen_reg_rtx (Pmode);
if (TARGET_64BIT)
tp = TARGET_GNU2_TLS ? get_thread_pointer (1) : 0;
if (TARGET_64BIT && ! TARGET_GNU2_TLS)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
@ -6388,13 +6408,25 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
emit_libcall_block (insns, base, rax, note);
}
else if (TARGET_64BIT && TARGET_GNU2_TLS)
emit_insn (gen_tls_local_dynamic_base_64 (base));
else
emit_insn (gen_tls_local_dynamic_base_32 (base));
if (TARGET_GNU2_TLS)
{
rtx x = ix86_tls_module_base ();
base = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, base));
set_unique_reg_note (get_last_insn (), REG_EQUIV, x);
}
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
off = gen_rtx_CONST (Pmode, off);
return gen_rtx_PLUS (Pmode, base, off);
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, base, off));
break;
case TLS_MODEL_INITIAL_EXEC:
if (TARGET_64BIT)
@ -6407,9 +6439,9 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
if (reload_in_progress)
regs_ever_live[PIC_OFFSET_TABLE_REGNUM] = 1;
pic = pic_offset_table_rtx;
type = TARGET_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
type = TARGET_ANY_GNU_TLS ? UNSPEC_GOTNTPOFF : UNSPEC_GOTTPOFF;
}
else if (!TARGET_GNU_TLS)
else if (!TARGET_ANY_GNU_TLS)
{
pic = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (pic));
@ -6428,7 +6460,7 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
off = gen_const_mem (Pmode, off);
set_mem_alias_set (off, ix86_GOT_alias_set ());
if (TARGET_64BIT || TARGET_GNU_TLS)
if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
{
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
off = force_reg (Pmode, off);
@ -6444,11 +6476,11 @@ legitimize_tls_address (rtx x, enum tls_model model, int for_mov)
case TLS_MODEL_LOCAL_EXEC:
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
(TARGET_64BIT || TARGET_GNU_TLS)
(TARGET_64BIT || TARGET_ANY_GNU_TLS)
? UNSPEC_NTPOFF : UNSPEC_TPOFF);
off = gen_rtx_CONST (Pmode, off);
if (TARGET_64BIT || TARGET_GNU_TLS)
if (TARGET_64BIT || TARGET_ANY_GNU_TLS)
{
base = get_thread_pointer (for_mov || !TARGET_TLS_DIRECT_SEG_REFS);
return gen_rtx_PLUS (Pmode, base, off);
@ -12900,6 +12932,7 @@ ix86_init_machine_status (void)
f = ggc_alloc_cleared (sizeof (struct machine_function));
f->use_fast_prologue_epilogue_nregs = -1;
f->tls_descriptor_call_expanded_p = 0;
return f;
}
@ -12942,13 +12975,32 @@ ix86_tls_get_addr (void)
if (!ix86_tls_symbol)
{
ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
(TARGET_GNU_TLS && !TARGET_64BIT)
(TARGET_ANY_GNU_TLS
&& !TARGET_64BIT)
? "___tls_get_addr"
: "__tls_get_addr");
}
return ix86_tls_symbol;
}
/* Construct the SYMBOL_REF for the _TLS_MODULE_BASE_ symbol. */
static GTY(()) rtx ix86_tls_module_base_symbol;
rtx
ix86_tls_module_base (void)
{
if (!ix86_tls_module_base_symbol)
{
ix86_tls_module_base_symbol = gen_rtx_SYMBOL_REF (Pmode,
"_TLS_MODULE_BASE_");
SYMBOL_REF_FLAGS (ix86_tls_module_base_symbol)
|= TLS_MODEL_GLOBAL_DYNAMIC << SYMBOL_FLAG_TLS_SHIFT;
}
return ix86_tls_module_base_symbol;
}
/* Calculate the length of the memory address in the instruction
encoding. Does not include the one-byte modrm, opcode, or prefix. */

View File

@ -1,6 +1,6 @@
/* Definitions of target machine for GCC for IA-32.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@ -225,6 +225,8 @@ extern int x86_prefetch_sse;
&& (ix86_fpmath & FPMATH_387))
#define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU)
#define TARGET_GNU2_TLS (ix86_tls_dialect == TLS_DIALECT_GNU2)
#define TARGET_ANY_GNU_TLS (TARGET_GNU_TLS || TARGET_GNU2_TLS)
#define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN)
#define TARGET_CMPXCHG (x86_cmpxchg & (1 << ix86_arch))
@ -2134,6 +2136,7 @@ extern enum fpmath_unit ix86_fpmath;
enum tls_dialect
{
TLS_DIALECT_GNU,
TLS_DIALECT_GNU2,
TLS_DIALECT_SUN
};
@ -2275,11 +2278,30 @@ struct machine_function GTY(())
/* Number of saved registers USE_FAST_PROLOGUE_EPILOGUE has been computed
for. */
int use_fast_prologue_epilogue_nregs;
/* If true, the current function needs the default PIC register, not
an alternate register (on x86) and must not use the red zone (on
x86_64), even if it's a leaf function. We don't want the
function to be regarded as non-leaf because TLS calls need not
affect register allocation. This flag is set when a TLS call
instruction is expanded within a function, and never reset, even
if all such instructions are optimized away. Use the
ix86_current_function_calls_tls_descriptor macro for a better
approximation. */
int tls_descriptor_call_expanded_p;
};
#define ix86_stack_locals (cfun->machine->stack_locals)
#define ix86_save_varrargs_registers (cfun->machine->save_varrargs_registers)
#define ix86_optimize_mode_switching (cfun->machine->optimize_mode_switching)
#define ix86_tls_descriptor_calls_expanded_in_cfun \
(cfun->machine->tls_descriptor_call_expanded_p)
/* Since tls_descriptor_call_expanded is not cleared, even if all TLS
calls are optimized away, we try to detect cases in which it was
optimized away. Since such instructions (use (reg REG_SP)), we can
verify whether there's any such instruction live by testing that
REG_SP is live. */
#define ix86_current_function_calls_tls_descriptor \
(ix86_tls_descriptor_calls_expanded_in_cfun && regs_ever_live[SP_REG])
/* Control behavior of x86_file_start. */
#define X86_FILE_START_VERSION_DIRECTIVE false

View File

@ -1,6 +1,6 @@
;; GCC machine description for IA-32 and x86-64.
;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
;; 2001, 2002, 2003, 2004, 2005
;; 2001, 2002, 2003, 2004, 2005, 2006
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;; x86_64 support added by Jan Hubicka
@ -73,6 +73,7 @@
(UNSPEC_TP 16)
(UNSPEC_TLS_GD 17)
(UNSPEC_TLS_LD_BASE 18)
(UNSPEC_TLSDESC 19)
; Other random patterns
(UNSPEC_SCAS 20)
@ -14161,6 +14162,12 @@
operands[2] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[2]));
}
if (TARGET_GNU2_TLS)
{
emit_insn (gen_tls_dynamic_gnu2_32
(operands[0], operands[1], operands[2]));
DONE;
}
operands[3] = ix86_tls_get_addr ();
})
@ -14182,6 +14189,12 @@
UNSPEC_TLS_GD)])]
""
{
if (TARGET_GNU2_TLS)
{
emit_insn (gen_tls_dynamic_gnu2_64
(operands[0], operands[1]));
DONE;
}
operands[2] = ix86_tls_get_addr ();
})
@ -14228,6 +14241,12 @@
operands[1] = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (operands[1]));
}
if (TARGET_GNU2_TLS)
{
emit_insn (gen_tls_dynamic_gnu2_32
(operands[0], ix86_tls_module_base (), operands[1]));
DONE;
}
operands[2] = ix86_tls_get_addr ();
})
@ -14247,6 +14266,12 @@
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
""
{
if (TARGET_GNU2_TLS)
{
emit_insn (gen_tls_dynamic_gnu2_64
(operands[0], ix86_tls_module_base ()));
DONE;
}
operands[1] = ix86_tls_get_addr ();
})
@ -14324,6 +14349,146 @@
(set_attr "length" "7")
(set_attr "memory" "load")
(set_attr "imm_disp" "false")])
;; GNU2 TLS patterns can be split.
(define_expand "tls_dynamic_gnu2_32"
[(set (match_dup 3)
(plus:SI (match_operand:SI 2 "register_operand" "")
(const:SI
(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")]
UNSPEC_TLSDESC))))
(parallel
[(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(match_dup 1) (match_dup 3)
(match_dup 2) (reg:SI SP_REG)]
UNSPEC_TLSDESC))
(clobber (reg:CC FLAGS_REG))])]
"!TARGET_64BIT && TARGET_GNU2_TLS"
{
operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
ix86_tls_descriptor_calls_expanded_in_cfun = true;
})
(define_insn "*tls_dynamic_lea_32"
[(set (match_operand:SI 0 "register_operand" "=r")
(plus:SI (match_operand:SI 1 "register_operand" "b")
(const:SI
(unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")]
UNSPEC_TLSDESC))))]
"!TARGET_64BIT && TARGET_GNU2_TLS"
"lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}"
[(set_attr "type" "lea")
(set_attr "mode" "SI")
(set_attr "length" "6")
(set_attr "length_address" "4")])
(define_insn "*tls_dynamic_call_32"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")
(match_operand:SI 2 "register_operand" "0")
;; we have to make sure %ebx still points to the GOT
(match_operand:SI 3 "register_operand" "b")
(reg:SI SP_REG)]
UNSPEC_TLSDESC))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU2_TLS"
"call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}"
[(set_attr "type" "call")
(set_attr "length" "2")
(set_attr "length_address" "0")])
(define_insn_and_split "*tls_dynamic_gnu2_combine_32"
[(set (match_operand:SI 0 "register_operand" "=&a")
(plus:SI
(plus:SI (match_operand:SI 3 "tp_or_register_operand" "ir")
(unspec:SI [(match_operand:SI 4 "tls_modbase_operand" "")
(match_operand:SI 5 "" "")
(match_operand:SI 2 "register_operand" "b")
(reg:SI SP_REG)]
UNSPEC_TLSDESC))
(const:SI (unspec:SI
[(match_operand:SI 1 "tls_symbolic_operand" "")]
UNSPEC_DTPOFF))))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT && TARGET_GNU2_TLS"
"#"
""
[(parallel
[(set (match_dup 0)
(plus:SI (match_dup 3)
(match_dup 5)))
(clobber (reg:CC FLAGS_REG))])]
{
operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2]));
})
(define_expand "tls_dynamic_gnu2_64"
[(set (match_dup 2)
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLSDESC))
(parallel
[(set (match_operand:DI 0 "register_operand" "")
(unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)]
UNSPEC_TLSDESC))
(clobber (reg:CC FLAGS_REG))])]
"TARGET_64BIT && TARGET_GNU2_TLS"
{
operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
ix86_tls_descriptor_calls_expanded_in_cfun = true;
})
(define_insn "*tls_dynamic_lea_64"
[(set (match_operand:DI 0 "register_operand" "=r")
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLSDESC))]
"TARGET_64BIT && TARGET_GNU2_TLS"
"lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}"
[(set_attr "type" "lea")
(set_attr "mode" "DI")
(set_attr "length" "7")
(set_attr "length_address" "4")])
(define_insn "*tls_dynamic_call_64"
[(set (match_operand:DI 0 "register_operand" "=a")
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")
(match_operand:DI 2 "register_operand" "0")
(reg:DI SP_REG)]
UNSPEC_TLSDESC))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_GNU2_TLS"
"call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}"
[(set_attr "type" "call")
(set_attr "length" "2")
(set_attr "length_address" "0")])
(define_insn_and_split "*tls_dynamic_gnu2_combine_64"
[(set (match_operand:DI 0 "register_operand" "=&a")
(plus:DI
(plus:DI (match_operand:DI 2 "tp_or_register_operand" "ir")
(unspec:DI [(match_operand:DI 3 "tls_modbase_operand" "")
(match_operand:DI 4 "" "")
(reg:DI SP_REG)]
UNSPEC_TLSDESC))
(const:DI (unspec:DI
[(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_DTPOFF))))
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_GNU2_TLS"
"#"
""
[(parallel
[(set (match_dup 0)
(plus:DI (match_dup 2)
(match_dup 4)))
(clobber (reg:CC FLAGS_REG))])]
{
operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode);
emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1]));
})
;;
;; These patterns match the binary 387 instructions for addM3, subM3,
;; mulM3 and divM3. There are three patterns for each of DFmode and

View File

@ -1,5 +1,5 @@
;; Predicate definitions for IA-32 and x86-64.
;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@ -467,6 +467,15 @@
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
(define_predicate "tls_modbase_operand"
(and (match_code "symbol_ref")
(match_test "op == ix86_tls_module_base ()")))
(define_predicate "tp_or_register_operand"
(ior (match_operand 0 "register_operand")
(and (match_code "unspec")
(match_test "XINT (op, 1) == UNSPEC_TP"))))
;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand"
(ior (match_code "symbol_ref")