This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: RFC: TLS improvements for IA32 and AMD64/EM64T
- From: Alexandre Oliva <aoliva at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: Mark Mitchell <mark at codesourcery dot com>, gcc-patches at gcc dot gnu dot org
- Date: Sat, 14 Jan 2006 08:59:10 -0500
- Subject: Re: RFC: TLS improvements for IA32 and AMD64/EM64T
- References: <ord5n91tx5.fsf@livre.oliva.athome.lsd.ic.unicamp.br> <or4q8l1sv8.fsf@livre.oliva.athome.lsd.ic.unicamp.br> <20050916215356.GA26641@redhat.com> <or7jdfy5b6.fsf@livre.oliva.athome.lsd.ic.unicamp.br> <20050917180134.GA16067@redhat.com> <or8xxt5gal.fsf@livre.oliva.athome.lsd.ic.unicamp.br> <43301CD4.1070301@codesourcery.com> <or3bnx8u71.fsf@livre.oliva.athome.lsd.ic.unicamp.br> <20050922154515.GC12513@redhat.com> <orek7ejtoa.fsf@livre.oliva.athome.lsd.ic.unicamp.br>
On Sep 24, 2005, Alexandre Oliva <aoliva@redhat.com> wrote:
> How's the patch below for 4.2?
Ping? Here's a rediffed and retested patch... Ok for trunk?
Index: gcc/ChangeLog
from 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.
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c.orig 2006-01-13 18:17:37.000000000 -0500
+++ gcc/config/i386/i386.c 2006-01-13 18:17:43.000000000 -0500
@@ -873,7 +873,7 @@
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. */
@@ -1623,6 +1623,8 @@
{
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
@@ -4412,7 +4414,8 @@
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)
@@ -4594,7 +4597,8 @@
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)
@@ -4785,7 +4789,8 @@
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;
@@ -4795,7 +4800,8 @@
/* 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
@@ -4816,7 +4822,8 @@
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)
@@ -6348,14 +6355,16 @@
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;
@@ -6366,13 +6375,24 @@
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;
@@ -6385,13 +6405,25 @@
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)
@@ -6404,9 +6436,9 @@
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));
@@ -6425,7 +6457,7 @@
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);
@@ -6441,11 +6473,11 @@
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);
@@ -12897,6 +12929,7 @@
f = ggc_alloc_cleared (sizeof (struct machine_function));
f->use_fast_prologue_epilogue_nregs = -1;
+ f->tls_descriptor_call_expanded_p = 0;
return f;
}
@@ -12939,13 +12972,32 @@
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. */
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h.orig 2006-01-13 18:17:37.000000000 -0500
+++ gcc/config/i386/i386.h 2006-01-13 18:17:43.000000000 -0500
@@ -225,6 +225,8 @@
&& (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 @@
enum tls_dialect
{
TLS_DIALECT_GNU,
+ TLS_DIALECT_GNU2,
TLS_DIALECT_SUN
};
@@ -2275,11 +2278,30 @@
/* 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
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md.orig 2006-01-13 18:17:37.000000000 -0500
+++ gcc/config/i386/i386.md 2006-01-13 18:17:43.000000000 -0500
@@ -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
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h.orig 2006-01-13 18:17:37.000000000 -0500
+++ gcc/config/i386/i386-protos.h 2006-01-13 18:17:43.000000000 -0500
@@ -179,6 +179,7 @@
#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);
Index: gcc/config/i386/predicates.md
===================================================================
--- gcc/config/i386/predicates.md.orig 2006-01-13 18:17:37.000000000 -0500
+++ gcc/config/i386/predicates.md 2006-01-13 18:17:43.000000000 -0500
@@ -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")
--
Alexandre Oliva http://www.lsd.ic.unicamp.br/~oliva/
Red Hat Compiler Engineer aoliva@{redhat.com, gcc.gnu.org}
Free Software Evangelist oliva@{lsd.ic.unicamp.br, gnu.org}