Commit 75d38379 by Jakub Jelinek Committed by Jakub Jelinek

i386.c (x86_64_sign_extended_value): Add allow_rip argument.

	* config/i386/i386.c (x86_64_sign_extended_value): Add allow_rip
	argument.  In CM_SMALL_PIC model consider SYMBOL_REFs binding locally or
	from constant pool or LABEL_REFs as sign extended if allow_rip.
	Change all +-1GB limits to +-16MB.
	(x86_64_general_operand, x86_64_szext_general_operand,
	x86_64_nonmemory_operand, x86_64_movabs_operand,
	x86_64_szext_nonmemory_operand, x86_64_immediate_operand,
	legitimate_address_p, ix86_expand_int_movcc): Update callers.
	(local_symbolic_operand): Don't allow offsets bigger than +-16MB
	in CM_SMALL_PIC model.
	(legitimate_pic_address_disp_p): Don't check offsets before
	calling local_symbolic_operand.
	(legitimize_pic_address): Force offsets bigger than +-16MB into
	register.
	* config/i386/i386.h (EXTRA_CONSTRAINT, CONST_COSTS): Likewise.
	* config/i386/i386-protos.h (x86_64_sign_extended_value): Update
	prototype.

	* configure.in: Test for @GOTNTPOFF and @INDNTPOFF on IA-32 too.
	Add x86-64 test.  Set tls_first_minor to 14 on IA-32 and x86-64.
	* configure: Rebuilt.
	* config/i386/i386.c (x86_64_sign_extended_value): Don't allow TLS
	SYMBOL_REFs unless enclosed in UNSPEC.  Handle UNSPEC_DTPOFF,
	UNSPEC_GOTNTPOFF and UNSPEC_NTPOFF.
	(legitimate_address_p): Allow foo@dtpoff(base) even on TARGET_64BIT
	-fpic.
	(ix86_encode_section_info): Don't ever generate TLSGD or TLSLD for
	non-pic code if TARGET_64BIT.
	(legitimize_address): Generate 64-bit TLS sequences.
	(output_pic_addr_const): Support x86-64 TLS operators.
	(i386_output_dwarf_dtprel): Output 64-bit DTPOFF as .long f@DTPOFF, 0.
	(print_operand_address): Use %fs instead of %gs on TARGET_64BIT.
	Don't append (%rip) in 64-bit TLSGD and TLSLD sequences.
	(output_addr_const_extra): Support x86-64 TLS operators.
	(maybe_get_pool_constant): Handle TARGET_64BIT -fpic.
	(ix86_tls_get_addr): Use __tls_get_addr on TARGET_64BIT
	unconditionally.
	* config/i386/i386.md (*tls_global_dynamic_gnu): Renamed to...
	(*tls_global_dynamic_32_gnu): ..., add !TARGET_64BIT.
	(*tls_global_dynamic_sun): Renamed to...
	(*tls_global_dynamic_32_sun): ..., add !TARGET_64BIT.
	(tls_global_dynamic): Renamed to...
	(tls_global_dynamic_32): ... this.
	(tls_global_dynamic_64, *tls_global_dynamic_64): New.
	(*tls_local_dynamic_base_dynamic_gnu): Renamed to...
	(*tls_local_dynamic_base_dynamic_32_gnu): ..., add !TARGET_64BIT.
	(*tls_local_dynamic_base_dynamic_sun): Renamed to...
	(*tls_local_dynamic_base_dynamic_32_sun): ..., add !TARGET_64BIT.
	(tls_local_dynamic_base_dynamic): Renamed to...
	(tls_local_dynamic_base_dynamic_32): ... this.
	(tls_local_dynamic_base_dynamic_64,
	*tls_local_dynamic_base_dynamic_64): New.
	(*tls_local_dynamic_once): Renamed to...
	(*tls_local_dynamic_32_once): ... this.

	* gcc.dg/tls/pic-1.c: New test.
	* gcc.dg/tls/nonpic-1.c: New test.
	* gcc.dg/20021018-1.c: New test.

From-SVN: r58383
parent 59798a0c
2002-10-21 Jakub Jelinek <jakub@redhat.com>
* config/i386/i386.c (x86_64_sign_extended_value): Add allow_rip
argument. In CM_SMALL_PIC model consider SYMBOL_REFs binding locally or
from constant pool or LABEL_REFs as sign extended if allow_rip.
Change all +-1GB limits to +-16MB.
(x86_64_general_operand, x86_64_szext_general_operand,
x86_64_nonmemory_operand, x86_64_movabs_operand,
x86_64_szext_nonmemory_operand, x86_64_immediate_operand,
legitimate_address_p, ix86_expand_int_movcc): Update callers.
(local_symbolic_operand): Don't allow offsets bigger than +-16MB
in CM_SMALL_PIC model.
(legitimate_pic_address_disp_p): Don't check offsets before
calling local_symbolic_operand.
(legitimize_pic_address): Force offsets bigger than +-16MB into
register.
* config/i386/i386.h (EXTRA_CONSTRAINT, CONST_COSTS): Likewise.
* config/i386/i386-protos.h (x86_64_sign_extended_value): Update
prototype.
* configure.in: Test for @GOTNTPOFF and @INDNTPOFF on IA-32 too.
Add x86-64 test. Set tls_first_minor to 14 on IA-32 and x86-64.
* configure: Rebuilt.
* config/i386/i386.c (x86_64_sign_extended_value): Don't allow TLS
SYMBOL_REFs unless enclosed in UNSPEC. Handle UNSPEC_DTPOFF,
UNSPEC_GOTNTPOFF and UNSPEC_NTPOFF.
(legitimate_address_p): Allow foo@dtpoff(base) even on TARGET_64BIT
-fpic.
(ix86_encode_section_info): Don't ever generate TLSGD or TLSLD for
non-pic code if TARGET_64BIT.
(legitimize_address): Generate 64-bit TLS sequences.
(output_pic_addr_const): Support x86-64 TLS operators.
(i386_output_dwarf_dtprel): Output 64-bit DTPOFF as .long f@DTPOFF, 0.
(print_operand_address): Use %fs instead of %gs on TARGET_64BIT.
Don't append (%rip) in 64-bit TLSGD and TLSLD sequences.
(output_addr_const_extra): Support x86-64 TLS operators.
(maybe_get_pool_constant): Handle TARGET_64BIT -fpic.
(ix86_tls_get_addr): Use __tls_get_addr on TARGET_64BIT
unconditionally.
* config/i386/i386.md (*tls_global_dynamic_gnu): Renamed to...
(*tls_global_dynamic_32_gnu): ..., add !TARGET_64BIT.
(*tls_global_dynamic_sun): Renamed to...
(*tls_global_dynamic_32_sun): ..., add !TARGET_64BIT.
(tls_global_dynamic): Renamed to...
(tls_global_dynamic_32): ... this.
(tls_global_dynamic_64, *tls_global_dynamic_64): New.
(*tls_local_dynamic_base_dynamic_gnu): Renamed to...
(*tls_local_dynamic_base_dynamic_32_gnu): ..., add !TARGET_64BIT.
(*tls_local_dynamic_base_dynamic_sun): Renamed to...
(*tls_local_dynamic_base_dynamic_32_sun): ..., add !TARGET_64BIT.
(tls_local_dynamic_base_dynamic): Renamed to...
(tls_local_dynamic_base_dynamic_32): ... this.
(tls_local_dynamic_base_dynamic_64,
*tls_local_dynamic_base_dynamic_64): New.
(*tls_local_dynamic_once): Renamed to...
(*tls_local_dynamic_32_once): ... this.
2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
* libgcc2.c: Inline __udiv_w_sdiv when compiling __udivdi3,
......
......@@ -153,7 +153,7 @@ extern int ix86_attr_length_address_default PARAMS ((rtx));
extern enum machine_mode ix86_fp_compare_mode PARAMS ((enum rtx_code));
extern int x86_64_sign_extended_value PARAMS ((rtx));
extern int x86_64_sign_extended_value PARAMS ((rtx, int));
extern int x86_64_zero_extended_value PARAMS ((rtx));
extern rtx ix86_libcall_value PARAMS ((enum machine_mode));
extern bool ix86_function_value_regno_p PARAMS ((int));
......
......@@ -2877,7 +2877,7 @@ x86_64_general_operand (op, mode)
return general_operand (op, mode);
if (nonimmediate_operand (op, mode))
return 1;
return x86_64_sign_extended_value (op);
return x86_64_sign_extended_value (op, 1);
}
/* Return nonzero if OP is general operand representable on x86_64
......@@ -2892,7 +2892,7 @@ x86_64_szext_general_operand (op, mode)
return general_operand (op, mode);
if (nonimmediate_operand (op, mode))
return 1;
return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
return x86_64_sign_extended_value (op, 1) || x86_64_zero_extended_value (op);
}
/* Return nonzero if OP is nonmemory operand representable on x86_64. */
......@@ -2906,7 +2906,7 @@ x86_64_nonmemory_operand (op, mode)
return nonmemory_operand (op, mode);
if (register_operand (op, mode))
return 1;
return x86_64_sign_extended_value (op);
return x86_64_sign_extended_value (op, 1);
}
/* Return nonzero if OP is nonmemory operand acceptable by movabs patterns. */
......@@ -2918,7 +2918,7 @@ x86_64_movabs_operand (op, mode)
{
if (!TARGET_64BIT || !flag_pic)
return nonmemory_operand (op, mode);
if (register_operand (op, mode) || x86_64_sign_extended_value (op))
if (register_operand (op, mode) || x86_64_sign_extended_value (op, 0))
return 1;
if (CONSTANT_P (op) && !symbolic_reference_mentioned_p (op))
return 1;
......@@ -2936,7 +2936,7 @@ x86_64_szext_nonmemory_operand (op, mode)
return nonmemory_operand (op, mode);
if (register_operand (op, mode))
return 1;
return x86_64_sign_extended_value (op) || x86_64_zero_extended_value (op);
return x86_64_sign_extended_value (op, 0) || x86_64_zero_extended_value (op);
}
/* Return nonzero if OP is immediate operand representable on x86_64. */
......@@ -2948,7 +2948,7 @@ x86_64_immediate_operand (op, mode)
{
if (!TARGET_64BIT)
return immediate_operand (op, mode);
return x86_64_sign_extended_value (op);
return x86_64_sign_extended_value (op, 0);
}
/* Return nonzero if OP is immediate operand representable on x86_64. */
......@@ -3071,7 +3071,10 @@ local_symbolic_operand (op, mode)
if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
&& GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
&& (ix86_cmodel != CM_SMALL_PIC
|| (INTVAL (XEXP (XEXP (op, 0), 1)) >= -16*1024*1024
&& INTVAL (XEXP (XEXP (op, 0), 1)) < 16*1024*1024)))
op = XEXP (XEXP (op, 0), 0);
if (GET_CODE (op) != SYMBOL_REF)
......@@ -3819,8 +3822,9 @@ ix86_can_use_return_insn_p ()
/* Return 1 if VALUE can be stored in the sign extended immediate field. */
int
x86_64_sign_extended_value (value)
x86_64_sign_extended_value (value, allow_rip)
rtx value;
int allow_rip;
{
switch (GET_CODE (value))
{
......@@ -3837,21 +3841,38 @@ x86_64_sign_extended_value (value)
}
break;
/* For certain code models, the symbolic references are known to fit. */
/* For certain code models, the symbolic references are known to fit.
in CM_SMALL_PIC model we know it fits if it is local to the shared
library. Don't count TLS SYMBOL_REFs here, since they should fit
only if inside of UNSPEC handled below. */
case SYMBOL_REF:
return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL;
return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
|| (allow_rip
&& ix86_cmodel == CM_SMALL_PIC
&& (CONSTANT_POOL_ADDRESS_P (value)
|| SYMBOL_REF_FLAG (value))
&& ! tls_symbolic_operand (value, GET_MODE (value))));
/* For certain code models, the code is near as well. */
case LABEL_REF:
return ix86_cmodel != CM_LARGE && ix86_cmodel != CM_SMALL_PIC;
return ix86_cmodel != CM_LARGE
&& (allow_rip || ix86_cmodel != CM_SMALL_PIC);
/* We also may accept the offsetted memory references in certain special
cases. */
case CONST:
if (GET_CODE (XEXP (value, 0)) == UNSPEC
&& XINT (XEXP (value, 0), 1) == UNSPEC_GOTPCREL)
return 1;
else if (GET_CODE (XEXP (value, 0)) == PLUS)
if (GET_CODE (XEXP (value, 0)) == UNSPEC)
switch (XINT (XEXP (value, 0), 1))
{
case UNSPEC_GOTPCREL:
case UNSPEC_DTPOFF:
case UNSPEC_GOTNTPOFF:
case UNSPEC_NTPOFF:
return 1;
default:
break;
}
if (GET_CODE (XEXP (value, 0)) == PLUS)
{
rtx op1 = XEXP (XEXP (value, 0), 0);
rtx op2 = XEXP (XEXP (value, 0), 1);
......@@ -3865,12 +3886,12 @@ x86_64_sign_extended_value (value)
switch (GET_CODE (op1))
{
case SYMBOL_REF:
/* For CM_SMALL assume that latest object is 1MB before
/* For CM_SMALL assume that latest object is 16MB before
end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are
in the positive half of address space. */
if (ix86_cmodel == CM_SMALL
&& offset < 1024*1024*1024
&& offset < 16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
/* For CM_KERNEL we know that all object resist in the
......@@ -3881,12 +3902,27 @@ x86_64_sign_extended_value (value)
&& offset > 0
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
/* For CM_SMALL_PIC, we can make similar assumptions
as for CM_SMALL model, if we know the symbol is local
to the shared library. Disallow any TLS symbols,
since they should always be enclosed in an UNSPEC. */
if (ix86_cmodel == CM_SMALL_PIC
&& allow_rip
&& (CONSTANT_POOL_ADDRESS_P (op1)
|| SYMBOL_REF_FLAG (op1))
&& ! tls_symbolic_operand (op1, GET_MODE (op1))
&& offset < 16*1024*1024
&& offset >= -16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
break;
case LABEL_REF:
/* These conditions are similar to SYMBOL_REF ones, just the
constraints for code models differ. */
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
&& offset < 1024*1024*1024
if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
|| (ix86_cmodel == CM_SMALL_PIC && allow_rip
&& offset >= -16*1024*1024))
&& offset < 16*1024*1024
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
if (ix86_cmodel == CM_KERNEL
......@@ -3894,6 +3930,16 @@ x86_64_sign_extended_value (value)
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
break;
case UNSPEC:
switch (XINT (op1, 1))
{
case UNSPEC_DTPOFF:
case UNSPEC_NTPOFF:
if (offset > 0
&& trunc_int_for_mode (offset, SImode) == offset)
return 1;
}
break;
default:
return 0;
}
......@@ -5082,21 +5128,8 @@ legitimate_pic_address_disp_p (disp)
/* In 64bit mode we can allow direct addresses of symbols and labels
when they are not dynamic symbols. */
if (TARGET_64BIT)
{
rtx x = disp;
if (GET_CODE (disp) == CONST)
x = XEXP (disp, 0);
/* ??? Handle PIC code models */
if (GET_CODE (x) == PLUS
&& (GET_CODE (XEXP (x, 1)) == CONST_INT
&& ix86_cmodel == CM_SMALL_PIC
&& INTVAL (XEXP (x, 1)) < 1024*1024*1024
&& INTVAL (XEXP (x, 1)) > -1024*1024*1024))
x = XEXP (x, 0);
if (local_symbolic_operand (x, Pmode))
return 1;
}
if (TARGET_64BIT && local_symbolic_operand (disp, Pmode))
return 1;
if (GET_CODE (disp) != CONST)
return 0;
disp = XEXP (disp, 0);
......@@ -5305,7 +5338,7 @@ legitimate_address_p (mode, addr, strict)
if (TARGET_64BIT)
{
if (!x86_64_sign_extended_value (disp))
if (!x86_64_sign_extended_value (disp, !(index || base)))
{
reason = "displacement is out of range";
goto report_error;
......@@ -5352,10 +5385,19 @@ legitimate_address_p (mode, addr, strict)
is_legitimate_pic:
if (TARGET_64BIT && (index || base))
{
reason = "non-constant pic memory reference";
goto report_error;
/* foo@dtpoff(%rX) is ok. */
if (GET_CODE (disp) != CONST
|| GET_CODE (XEXP (disp, 0)) != PLUS
|| GET_CODE (XEXP (XEXP (disp, 0), 0)) != UNSPEC
|| GET_CODE (XEXP (XEXP (disp, 0), 1)) != CONST_INT
|| (XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_DTPOFF
&& XINT (XEXP (XEXP (disp, 0), 0), 1) != UNSPEC_NTPOFF))
{
reason = "non-constant pic memory reference";
goto report_error;
}
}
if (! legitimate_pic_address_disp_p (disp))
else if (! legitimate_pic_address_disp_p (disp))
{
reason = "displacement is an invalid pic construct";
goto report_error;
......@@ -5553,7 +5595,9 @@ legitimize_pic_address (orig, reg)
}
else
{
/* ??? We need to limit offsets here. */
if (INTVAL (op1) < -16*1024*1024
|| INTVAL (op1) >= 16*1024*1024)
new = gen_rtx_PLUS (Pmode, op0, force_reg (Pmode, op1));
}
}
else
......@@ -5611,6 +5655,21 @@ ix86_encode_section_info (decl, first)
size_t len;
enum tls_model kind = decl_tls_model (decl);
if (TARGET_64BIT && ! flag_pic)
{
/* x86-64 doesn't allow non-pic code for shared libraries,
so don't generate GD/LD TLS models for non-pic code. */
switch (kind)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
kind = TLS_MODEL_INITIAL_EXEC; break;
case TLS_MODEL_LOCAL_DYNAMIC:
kind = TLS_MODEL_LOCAL_EXEC; break;
default:
break;
}
}
symbol_str = XSTR (symbol, 0);
if (symbol_str[0] == '%')
......@@ -5700,17 +5759,44 @@ legitimize_address (x, oldx, mode)
if (log)
{
rtx dest, base, off, pic;
int type;
switch (log)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
dest = gen_reg_rtx (Pmode);
emit_insn (gen_tls_global_dynamic (dest, x));
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns;
start_sequence ();
emit_call_insn (gen_tls_global_dynamic_64 (rax, x));
insns = get_insns ();
end_sequence ();
emit_libcall_block (insns, dest, rax, x);
}
else
emit_insn (gen_tls_global_dynamic_32 (dest, x));
break;
case TLS_MODEL_LOCAL_DYNAMIC:
base = gen_reg_rtx (Pmode);
emit_insn (gen_tls_local_dynamic_base (base));
if (TARGET_64BIT)
{
rtx rax = gen_rtx_REG (Pmode, 0), insns, note;
start_sequence ();
emit_call_insn (gen_tls_local_dynamic_base_64 (rax));
insns = get_insns ();
end_sequence ();
note = gen_rtx_EXPR_LIST (VOIDmode, const0_rtx, NULL);
note = gen_rtx_EXPR_LIST (VOIDmode, ix86_tls_get_addr (), note);
emit_libcall_block (insns, base, rax, note);
}
else
emit_insn (gen_tls_local_dynamic_base_32 (base));
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPOFF);
off = gen_rtx_CONST (Pmode, off);
......@@ -5718,36 +5804,42 @@ legitimize_address (x, oldx, mode)
return gen_rtx_PLUS (Pmode, base, off);
case TLS_MODEL_INITIAL_EXEC:
if (flag_pic)
if (TARGET_64BIT)
{
pic = NULL;
type = UNSPEC_GOTNTPOFF;
}
else if (flag_pic)
{
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;
}
else if (!TARGET_GNU_TLS)
{
pic = gen_reg_rtx (Pmode);
emit_insn (gen_set_got (pic));
type = UNSPEC_GOTTPOFF;
}
else
pic = NULL;
{
pic = NULL;
type = UNSPEC_INDNTPOFF;
}
base = get_thread_pointer ();
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
!TARGET_GNU_TLS
? UNSPEC_GOTTPOFF
: flag_pic ? UNSPEC_GOTNTPOFF
: UNSPEC_INDNTPOFF);
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), type);
off = gen_rtx_CONST (Pmode, off);
if (flag_pic || !TARGET_GNU_TLS)
if (pic)
off = gen_rtx_PLUS (Pmode, pic, off);
off = gen_rtx_MEM (Pmode, off);
RTX_UNCHANGING_P (off) = 1;
set_mem_alias_set (off, ix86_GOT_alias_set ());
dest = gen_reg_rtx (Pmode);
if (TARGET_GNU_TLS)
if (TARGET_64BIT || TARGET_GNU_TLS)
{
emit_move_insn (dest, off);
return gen_rtx_PLUS (Pmode, base, dest);
......@@ -5760,10 +5852,11 @@ legitimize_address (x, oldx, mode)
base = get_thread_pointer ();
off = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x),
TARGET_GNU_TLS ? UNSPEC_NTPOFF : UNSPEC_TPOFF);
(TARGET_64BIT || TARGET_GNU_TLS)
? UNSPEC_NTPOFF : UNSPEC_TPOFF);
off = gen_rtx_CONST (Pmode, off);
if (TARGET_GNU_TLS)
if (TARGET_64BIT || TARGET_GNU_TLS)
return gen_rtx_PLUS (Pmode, base, off);
else
{
......@@ -6041,13 +6134,19 @@ output_pic_addr_const (file, x, code)
fputs ("@TPOFF", file);
break;
case UNSPEC_NTPOFF:
fputs ("@NTPOFF", file);
if (TARGET_64BIT)
fputs ("@TPOFF", file);
else
fputs ("@NTPOFF", file);
break;
case UNSPEC_DTPOFF:
fputs ("@DTPOFF", file);
break;
case UNSPEC_GOTNTPOFF:
fputs ("@GOTNTPOFF", file);
if (TARGET_64BIT)
fputs ("@GOTTPOFF(%rip)", file);
else
fputs ("@GOTNTPOFF", file);
break;
case UNSPEC_INDNTPOFF:
fputs ("@INDNTPOFF", file);
......@@ -6094,22 +6193,19 @@ i386_output_dwarf_dtprel (file, size, x)
int size;
rtx x;
{
fputs (ASM_LONG, file);
output_addr_const (file, x);
fputs ("@DTPOFF", file);
switch (size)
{
case 4:
fputs (ASM_LONG, file);
break;
case 8:
#ifdef ASM_QUAD
fputs (ASM_QUAD, file);
fputs (", 0", file);
break;
#endif
default:
abort ();
}
output_addr_const (file, x);
fputs ("@DTPOFF", file);
}
/* In the name of slightly smaller debug output, and to cater to
......@@ -6821,7 +6917,10 @@ print_operand_address (file, addr)
fputs ("DWORD PTR ", file);
if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0)
putc ('%', file);
fputs ("gs:0", file);
if (TARGET_64BIT)
fputs ("fs:0", file);
else
fputs ("gs:0", file);
return;
}
......@@ -6854,7 +6953,8 @@ print_operand_address (file, addr)
/* Use one byte shorter RIP relative addressing for 64bit mode. */
if (TARGET_64BIT
&& (GET_CODE (addr) == SYMBOL_REF
&& ((GET_CODE (addr) == SYMBOL_REF
&& ! tls_symbolic_operand (addr, GET_MODE (addr)))
|| GET_CODE (addr) == LABEL_REF
|| (GET_CODE (addr) == CONST
&& GET_CODE (XEXP (addr, 0)) == PLUS
......@@ -6967,7 +7067,10 @@ output_addr_const_extra (file, x)
break;
case UNSPEC_NTPOFF:
output_addr_const (file, op);
fputs ("@NTPOFF", file);
if (TARGET_64BIT)
fputs ("@TPOFF", file);
else
fputs ("@NTPOFF", file);
break;
case UNSPEC_DTPOFF:
output_addr_const (file, op);
......@@ -6975,7 +7078,10 @@ output_addr_const_extra (file, x)
break;
case UNSPEC_GOTNTPOFF:
output_addr_const (file, op);
fputs ("@GOTNTPOFF", file);
if (TARGET_64BIT)
fputs ("@GOTTPOFF(%rip)", file);
else
fputs ("@GOTNTPOFF", file);
break;
case UNSPEC_INDNTPOFF:
output_addr_const (file, op);
......@@ -7539,7 +7645,7 @@ maybe_get_pool_constant (x)
{
x = XEXP (x, 0);
if (flag_pic)
if (flag_pic && ! TARGET_64BIT)
{
if (GET_CODE (x) != PLUS)
return NULL_RTX;
......@@ -9096,7 +9202,7 @@ ix86_expand_int_movcc (operands)
if ((diff == 1 || diff == 2 || diff == 4 || diff == 8
|| diff == 3 || diff == 5 || diff == 9)
&& (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf))))
&& (mode != DImode || x86_64_sign_extended_value (GEN_INT (cf), 0)))
{
/*
* xorl dest,dest
......@@ -10827,9 +10933,10 @@ ix86_tls_get_addr ()
if (!ix86_tls_symbol)
{
ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, (TARGET_GNU_TLS
? "___tls_get_addr"
: "__tls_get_addr"));
ix86_tls_symbol = gen_rtx_SYMBOL_REF (Pmode,
(TARGET_GNU_TLS && !TARGET_64BIT)
? "___tls_get_addr"
: "__tls_get_addr");
}
return ix86_tls_symbol;
......
......@@ -1426,7 +1426,7 @@ enum reg_class
constraint, the value returned should be 0 regardless of VALUE. */
#define EXTRA_CONSTRAINT(VALUE, C) \
((C) == 'e' ? x86_64_sign_extended_value (VALUE) \
((C) == 'e' ? x86_64_sign_extended_value (VALUE, 0) \
: (C) == 'Z' ? x86_64_zero_extended_value (VALUE) \
: 0)
......@@ -2553,7 +2553,7 @@ do { \
case CONST: \
case LABEL_REF: \
case SYMBOL_REF: \
if (TARGET_64BIT && !x86_64_sign_extended_value (RTX)) \
if (TARGET_64BIT && !x86_64_sign_extended_value (RTX, 0)) \
return 3; \
if (TARGET_64BIT && !x86_64_zero_extended_value (RTX)) \
return 2; \
......
......@@ -13783,7 +13783,7 @@
;; Note that these code sequences must appear exactly as shown
;; in order to allow linker relaxation.
(define_insn "*tls_global_dynamic_gnu"
(define_insn "*tls_global_dynamic_32_gnu"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(match_operand:SI 1 "register_operand" "b")
(match_operand:SI 2 "tls_symbolic_operand" "")
......@@ -13792,12 +13792,12 @@
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
(clobber (reg:CC 17))]
"TARGET_GNU_TLS"
"!TARGET_64BIT && TARGET_GNU_TLS"
"lea{l}\t{%a2@TLSGD(,%1,1), %0|%0, %a2@TLSGD[%1*1]}\;call\t%P3"
[(set_attr "type" "multi")
(set_attr "length" "12")])
(define_insn "*tls_global_dynamic_sun"
(define_insn "*tls_global_dynamic_32_sun"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(match_operand:SI 1 "register_operand" "b")
(match_operand:SI 2 "tls_symbolic_operand" "")
......@@ -13806,13 +13806,13 @@
(clobber (match_scratch:SI 4 "=d"))
(clobber (match_scratch:SI 5 "=c"))
(clobber (reg:CC 17))]
"TARGET_SUN_TLS"
"!TARGET_64BIT && TARGET_SUN_TLS"
"lea{l}\t{%a2@DTLNDX(%1), %4|%4, %a2@DTLNDX[%1]}
push{l}\t%4\;call\t%a2@TLSPLT\;pop{l}\t%4\;nop"
[(set_attr "type" "multi")
(set_attr "length" "14")])
(define_expand "tls_global_dynamic"
(define_expand "tls_global_dynamic_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI
[(match_dup 2)
......@@ -13834,7 +13834,28 @@
operands[3] = ix86_tls_get_addr ();
})
(define_insn "*tls_local_dynamic_base_gnu"
(define_insn "*tls_global_dynamic_64"
[(set (match_operand:DI 0 "register_operand" "=a")
(call (mem:QI (match_operand:DI 2 "call_insn_operand" ""))
(match_operand:DI 3 "" "")))
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLS_GD)]
"TARGET_64BIT"
".byte\t0x66\;lea{q}\t{%a1@TLSGD(%%rip), %%rdi|%%rdi, %a1@TLSGD[%%rip]}\;.word\t0x6666\;rex64\;call\t%P2"
[(set_attr "type" "multi")
(set_attr "length" "16")])
(define_expand "tls_global_dynamic_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(call (mem:QI (match_dup 2)) (const_int 0)))
(unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")]
UNSPEC_TLS_GD)])]
""
{
operands[2] = ix86_tls_get_addr ();
})
(define_insn "*tls_local_dynamic_base_32_gnu"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(match_operand:SI 1 "register_operand" "b")
(match_operand:SI 2 "call_insn_operand" "")]
......@@ -13842,12 +13863,12 @@
(clobber (match_scratch:SI 3 "=d"))
(clobber (match_scratch:SI 4 "=c"))
(clobber (reg:CC 17))]
"TARGET_GNU_TLS"
"!TARGET_64BIT && TARGET_GNU_TLS"
"lea{l}\t{%&@TLSLDM(%1), %0|%0, %&@TLSLDM[%1]}\;call\t%P2"
[(set_attr "type" "multi")
(set_attr "length" "11")])
(define_insn "*tls_local_dynamic_base_sun"
(define_insn "*tls_local_dynamic_base_32_sun"
[(set (match_operand:SI 0 "register_operand" "=a")
(unspec:SI [(match_operand:SI 1 "register_operand" "b")
(match_operand:SI 2 "call_insn_operand" "")]
......@@ -13855,13 +13876,13 @@
(clobber (match_scratch:SI 3 "=d"))
(clobber (match_scratch:SI 4 "=c"))
(clobber (reg:CC 17))]
"TARGET_SUN_TLS"
"!TARGET_64BIT && TARGET_SUN_TLS"
"lea{l}\t{%&@TMDNX(%1), %3|%3, %&@TMDNX[%1]}
push{l}\t%3\;call\t%&@TLSPLT\;pop{l}\t%3"
[(set_attr "type" "multi")
(set_attr "length" "13")])
(define_expand "tls_local_dynamic_base"
(define_expand "tls_local_dynamic_base_32"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(unspec:SI [(match_dup 1) (match_dup 2)]
UNSPEC_TLS_LD_BASE))
......@@ -13880,10 +13901,29 @@
operands[2] = ix86_tls_get_addr ();
})
(define_insn "*tls_local_dynamic_base_64"
[(set (match_operand:DI 0 "register_operand" "=a")
(call (mem:QI (match_operand:DI 1 "call_insn_operand" ""))
(match_operand:DI 2 "" "")))
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)]
"TARGET_64BIT"
"lea{q}\t{%&@TLSLD(%%rip), %%rdi|%%rdi, %&@TLSLD[%%rip]}\;call\t%P1"
[(set_attr "type" "multi")
(set_attr "length" "12")])
(define_expand "tls_local_dynamic_base_64"
[(parallel [(set (match_operand:DI 0 "register_operand" "")
(call (mem:QI (match_dup 1)) (const_int 0)))
(unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])]
""
{
operands[1] = ix86_tls_get_addr ();
})
;; Local dynamic of a single variable is a lose. Show combine how
;; to convert that back to global dynamic.
(define_insn_and_split "*tls_local_dynamic_once"
(define_insn_and_split "*tls_local_dynamic_32_once"
[(set (match_operand:SI 0 "register_operand" "=a")
(plus:SI (unspec:SI [(match_operand:SI 1 "register_operand" "b")
(match_operand:SI 2 "call_insn_operand" "")]
......
......@@ -7482,11 +7482,27 @@ foo: .long 25
leal foo@DTPOFF(%eax), %edx
movl foo@GOTTPOFF(%ebx), %eax
subl foo@GOTTPOFF(%ebx), %eax
addl foo@GOTNTPOFF(%ebx), %eax
movl foo@INDNTPOFF, %eax
movl $foo@TPOFF, %eax
subl $foo@TPOFF, %eax
leal foo@NTPOFF(%ecx), %eax'
tls_first_major=2
tls_first_minor=13
tls_first_minor=14
;;
x86_64-*-*)
conftest_s='
.section ".tdata","awT",@progbits
foo: .long 25
.text
movq %fs:0, %rax
leaq foo@TLSGD(%rip), %rdi
leaq foo@TLSLD(%rip), %rdi
leaq foo@DTPOFF(%rax), %rdx
movq foo@GOTTPOFF(%rip), %rax
movq $foo@TPOFF, %rax'
tls_first_major=2
tls_first_minor=14
;;
ia64-*-*)
conftest_s='
......
......@@ -1802,11 +1802,27 @@ foo: .long 25
leal foo@DTPOFF(%eax), %edx
movl foo@GOTTPOFF(%ebx), %eax
subl foo@GOTTPOFF(%ebx), %eax
addl foo@GOTNTPOFF(%ebx), %eax
movl foo@INDNTPOFF, %eax
movl $foo@TPOFF, %eax
subl $foo@TPOFF, %eax
leal foo@NTPOFF(%ecx), %eax'
tls_first_major=2
tls_first_minor=13
tls_first_minor=14
;;
x86_64-*-*)
conftest_s='
.section ".tdata","awT",@progbits
foo: .long 25
.text
movq %fs:0, %rax
leaq foo@TLSGD(%rip), %rdi
leaq foo@TLSLD(%rip), %rdi
leaq foo@DTPOFF(%rax), %rdx
movq foo@GOTTPOFF(%rip), %rax
movq $foo@TPOFF, %rax'
tls_first_major=2
tls_first_minor=14
;;
ia64-*-*)
conftest_s='
......
2002-10-21 Jakub Jelinek <jakub@redhat.com>
* gcc.dg/tls/pic-1.c: New test.
* gcc.dg/tls/nonpic-1.c: New test.
* gcc.dg/20021018-1.c: New test.
2002-10-21 Ulrich Weigand <uweigand@de.ibm.com>
* lib/profopt.exp (profopt-cleanup): New argument TESTCASE.
......
/* { dg-do run } */
/* { dg-options "-O2 -fpic" } */
extern void abort (void);
extern void exit (int);
static const long foo [10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
long __attribute__((noinline))
bar (int x)
{
return foo [x - 0x6ffffffa];
}
int
main (void)
{
if (bar (0x6ffffffc) != 2)
abort ();
exit (0);
}
/* { dg-do compile } */
/* { dg-options "-O2 -ftls-model=initial-exec" } */
extern __thread long e1;
extern __thread int e2;
static __thread long s1;
static __thread int s2;
long *ae1 (void)
{
return &e1;
}
int *ae2 (void)
{
return &e2;
}
long *as1 (void)
{
return &s1;
}
int *as2 (void)
{
return &s2;
}
long ge1 (void)
{
return e1;
}
int ge2 (void)
{
return e2;
}
long gs1 (void)
{
return s1;
}
int gs2 (void)
{
return s2;
}
long ge3 (void)
{
return e1 + e2;
}
long gs3 (void)
{
return s1 + s2;
}
long ge4 (void)
{
if (0)
return e1;
return e2;
}
long gs4 (void)
{
if (0)
return s1;
return s2;
}
/* { dg-do compile } */
/* { dg-options "-O2 -fpic -ftls-model=global-dynamic" } */
extern __thread long e1;
extern __thread int e2;
static __thread long s1;
static __thread int s2;
long *ae1 (void)
{
return &e1;
}
int *ae2 (void)
{
return &e2;
}
long *as1 (void)
{
return &s1;
}
int *as2 (void)
{
return &s2;
}
long ge1 (void)
{
return e1;
}
int ge2 (void)
{
return e2;
}
long gs1 (void)
{
return s1;
}
int gs2 (void)
{
return s2;
}
long ge3 (void)
{
return e1 + e2;
}
long gs3 (void)
{
return s1 + s2;
}
long ge4 (void)
{
if (0)
return e1;
return e2;
}
long gs4 (void)
{
if (0)
return s1;
return s2;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment