Commit fd4aca96 by Richard Henderson Committed by Richard Henderson

re PR target/24428 (TLS miscompilation on x86_64)

        PR target/24428
        * config/i386/i386.c (legitimate_constant_p): Check
        SYMBOL_REF_TLS_MODEL directly.  Don't fallthru to SYMBOL_REF
        if LABEL_REF.
        (legitimate_pic_operand_p): Test SYMBOL_REF_TLS_MODEL directly.
        (legitimate_pic_address_disp_p): Reorg CONST checking to make
        sure SYMBOL_REF_TLS_MODEL is tested.  Test SYMBOL_REF_TLS_MODEL
        directly.
        (print_operand_address): Likewise.
        * config/i386/predicates.md (x86_64_immediate_operand): Test
        SYMBOL_REF_TLS_MODEL properly inside CONST.
        (x86_64_zext_immediate_operand): Likewise.
        (global_dynamic_symbolic_operand, local_dynamic_symbolic_operand,
        initial_exec_symbolic_operand, local_exec_symbolic_operand): Remove.
        * config/i386/i386-protos.h: Remove predicates.md entries.

From-SVN: r105592
parent 14a814a4
2006-10-18 Richard Henderson <rth@redhat.com>
PR target/24428
* config/i386/i386.c (legitimate_constant_p): Check
SYMBOL_REF_TLS_MODEL directly. Don't fallthru to SYMBOL_REF
if LABEL_REF.
(legitimate_pic_operand_p): Test SYMBOL_REF_TLS_MODEL directly.
(legitimate_pic_address_disp_p): Reorg CONST checking to make
sure SYMBOL_REF_TLS_MODEL is tested. Test SYMBOL_REF_TLS_MODEL
directly.
(print_operand_address): Likewise.
* config/i386/predicates.md (x86_64_immediate_operand): Test
SYMBOL_REF_TLS_MODEL properly inside CONST.
(x86_64_zext_immediate_operand): Likewise.
(global_dynamic_symbolic_operand, local_dynamic_symbolic_operand,
initial_exec_symbolic_operand, local_exec_symbolic_operand): Remove.
* config/i386/i386-protos.h: Remove predicates.md entries.
2005-10-18 Danny Smith <dannysmith@users.sourceforge.net>
* config/i386/winnt-cxx.c (i386_pe_adjust_class_at_definition):
......
......@@ -46,53 +46,6 @@ extern int symbolic_reference_mentioned_p (rtx);
extern bool extended_reg_mentioned_p (rtx);
extern bool x86_extended_QIreg_mentioned_p (rtx);
extern bool x86_extended_reg_mentioned_p (rtx);
extern int any_fp_register_operand (rtx, enum machine_mode);
extern int register_and_not_any_fp_reg_operand (rtx, enum machine_mode);
extern int fp_register_operand (rtx, enum machine_mode);
extern int register_and_not_fp_reg_operand (rtx, enum machine_mode);
extern int x86_64_general_operand (rtx, enum machine_mode);
extern int x86_64_szext_general_operand (rtx, enum machine_mode);
extern int x86_64_nonmemory_operand (rtx, enum machine_mode);
extern int x86_64_szext_nonmemory_operand (rtx, enum machine_mode);
extern int x86_64_immediate_operand (rtx, enum machine_mode);
extern int x86_64_zext_immediate_operand (rtx, enum machine_mode);
extern int symbolic_operand (rtx, enum machine_mode);
extern int tls_symbolic_operand (rtx, enum machine_mode);
extern int global_dynamic_symbolic_operand (rtx, enum machine_mode);
extern int local_dynamic_symbolic_operand (rtx, enum machine_mode);
extern int initial_exec_symbolic_operand (rtx, enum machine_mode);
extern int local_exec_symbolic_operand (rtx, enum machine_mode);
extern int pic_symbolic_operand (rtx, enum machine_mode);
extern int call_insn_operand (rtx, enum machine_mode);
extern int sibcall_insn_operand (rtx, enum machine_mode);
extern int constant_call_address_operand (rtx, enum machine_mode);
extern int const0_operand (rtx, enum machine_mode);
extern int const1_operand (rtx, enum machine_mode);
extern int const248_operand (rtx, enum machine_mode);
extern int incdec_operand (rtx, enum machine_mode);
extern int reg_no_sp_operand (rtx, enum machine_mode);
extern int mmx_reg_operand (rtx, enum machine_mode);
extern int general_no_elim_operand (rtx, enum machine_mode);
extern int nonmemory_no_elim_operand (rtx, enum machine_mode);
extern int q_regs_operand (rtx, enum machine_mode);
extern int non_q_regs_operand (rtx, enum machine_mode);
extern int sse_comparison_operator (rtx, enum machine_mode);
extern int fcmov_comparison_operator (rtx, enum machine_mode);
extern int cmp_fp_expander_operand (rtx, enum machine_mode);
extern int ix86_comparison_operator (rtx, enum machine_mode);
extern int ext_register_operand (rtx, enum machine_mode);
extern int binary_fp_operator (rtx, enum machine_mode);
extern int mult_operator (rtx, enum machine_mode);
extern int div_operator (rtx, enum machine_mode);
extern int arith_or_logical_operator (rtx, enum machine_mode);
extern int promotable_binary_operator (rtx, enum machine_mode);
extern int memory_displacement_operand (rtx, enum machine_mode);
extern int cmpsi_operand (rtx, enum machine_mode);
extern int long_memory_operand (rtx, enum machine_mode);
extern int aligned_operand (rtx, enum machine_mode);
extern enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
extern int ix86_expand_movmem (rtx, rtx, rtx, rtx);
......
......@@ -5423,21 +5423,27 @@ legitimate_constant_p (rtx x)
return TARGET_64BIT;
case UNSPEC_TPOFF:
case UNSPEC_NTPOFF:
return local_exec_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
x = XVECEXP (x, 0, 0);
return (GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_EXEC);
case UNSPEC_DTPOFF:
return local_dynamic_symbolic_operand (XVECEXP (x, 0, 0), Pmode);
x = XVECEXP (x, 0, 0);
return (GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC);
default:
return false;
}
/* We must have drilled down to a symbol. */
if (!symbolic_operand (x, Pmode))
if (GET_CODE (x) == LABEL_REF)
return true;
if (GET_CODE (x) != SYMBOL_REF)
return false;
/* FALLTHRU */
case SYMBOL_REF:
/* TLS symbols are never valid. */
if (tls_symbolic_operand (x, Pmode))
if (SYMBOL_REF_TLS_MODEL (x))
return false;
break;
......@@ -5491,7 +5497,9 @@ legitimate_pic_operand_p (rtx x)
case UNSPEC_GOTOFF:
return TARGET_64BIT;
case UNSPEC_TPOFF:
return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode);
x = XVECEXP (inner, 0, 0);
return (GET_CODE (x) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_EXEC);
default:
return false;
}
......@@ -5518,32 +5526,38 @@ legitimate_pic_address_disp_p (rtx disp)
when they are not dynamic symbols. */
if (TARGET_64BIT)
{
/* TLS references should always be enclosed in UNSPEC. */
if (tls_symbolic_operand (disp, GET_MODE (disp)))
return 0;
if (GET_CODE (disp) == SYMBOL_REF
&& !SYMBOL_REF_FAR_ADDR_P (disp)
&& SYMBOL_REF_LOCAL_P (disp))
return 1;
if (GET_CODE (disp) == LABEL_REF)
return 1;
if (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == PLUS)
rtx op0 = disp, op1;
switch (GET_CODE (disp))
{
rtx op0 = XEXP (XEXP (disp, 0), 0);
rtx op1 = XEXP (XEXP (disp, 0), 1);
case LABEL_REF:
return true;
case CONST:
if (GET_CODE (XEXP (disp, 0)) != PLUS)
break;
op0 = XEXP (XEXP (disp, 0), 0);
op1 = XEXP (XEXP (disp, 0), 1);
if (GET_CODE (op1) != CONST_INT
|| INTVAL (op1) >= 16*1024*1024
|| INTVAL (op1) < -16*1024*1024)
break;
if (GET_CODE (op0) == LABEL_REF)
return true;
if (GET_CODE (op0) != SYMBOL_REF)
break;
/* FALLTHRU */
case SYMBOL_REF:
/* TLS references should always be enclosed in UNSPEC. */
if (tls_symbolic_operand (op0, GET_MODE (op0)))
return 0;
if (((GET_CODE (op0) == SYMBOL_REF
&& !SYMBOL_REF_FAR_ADDR_P (op0)
&& SYMBOL_REF_LOCAL_P (op0))
|| GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT
&& INTVAL (op1) < 16*1024*1024
&& INTVAL (op1) >= -16*1024*1024)
return 1;
if (SYMBOL_REF_TLS_MODEL (op0))
return false;
if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0))
return true;
break;
default:
break;
}
}
if (GET_CODE (disp) != CONST)
......@@ -5600,11 +5614,17 @@ legitimate_pic_address_disp_p (rtx disp)
case UNSPEC_INDNTPOFF:
if (saw_plus)
return false;
return initial_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
disp = XVECEXP (disp, 0, 0);
return (GET_CODE (disp) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_INITIAL_EXEC);
case UNSPEC_NTPOFF:
return local_exec_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
disp = XVECEXP (disp, 0, 0);
return (GET_CODE (disp) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_LOCAL_EXEC);
case UNSPEC_DTPOFF:
return local_dynamic_symbolic_operand (XVECEXP (disp, 0, 0), Pmode);
disp = XVECEXP (disp, 0, 0);
return (GET_CODE (disp) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (disp) == TLS_MODEL_LOCAL_DYNAMIC);
}
return 0;
......@@ -6856,7 +6876,7 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
rtx x = *px;
if (GET_CODE (x) == SYMBOL_REF
&& local_dynamic_symbolic_operand (x, Pmode))
&& SYMBOL_REF_TLS_MODEL (x) == TLS_MODEL_LOCAL_DYNAMIC)
{
cfun->machine->some_ld_name = XSTR (x, 0);
return 1;
......@@ -7329,16 +7349,17 @@ print_operand_address (FILE *file, rtx addr)
output_addr_const (file, disp);
/* Use one byte shorter RIP relative addressing for 64bit mode. */
if (TARGET_64BIT
&& ((GET_CODE (disp) == SYMBOL_REF
&& ! tls_symbolic_operand (disp, GET_MODE (disp)))
|| GET_CODE (disp) == LABEL_REF
|| (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF
|| GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF)
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)))
fputs ("(%rip)", file);
if (TARGET_64BIT)
{
if (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
disp = XEXP (XEXP (disp, 0), 0);
if (GET_CODE (disp) == LABEL_REF
|| (GET_CODE (disp) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (disp) == 0))
fputs ("(%rip)", file);
}
}
else
{
......
......@@ -108,7 +108,7 @@
library. Don't count TLS SYMBOL_REFs here, since they should fit
only if inside of UNSPEC handled below. */
/* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode))
if (SYMBOL_REF_TLS_MODEL (op))
return false;
return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
|| (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
......@@ -147,6 +147,9 @@
switch (GET_CODE (op1))
{
case SYMBOL_REF:
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op1))
return 0;
/* 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
......@@ -225,7 +228,7 @@
case SYMBOL_REF:
/* For certain code models, the symbolic references are known to fit. */
/* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode))
if (SYMBOL_REF_TLS_MODEL (op))
return false;
return (ix86_cmodel == CM_SMALL
|| (ix86_cmodel == CM_MEDIUM
......@@ -248,6 +251,9 @@
switch (GET_CODE (op1))
{
case SYMBOL_REF:
/* TLS symbols are not constant. */
if (SYMBOL_REF_TLS_MODEL (op1))
return 0;
/* For small code model we may accept pretty large positive
offsets, since one bit is available for free. Negative
offsets are limited by the size of NULL pointer area
......@@ -456,22 +462,6 @@
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
(define_predicate "global_dynamic_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
(define_predicate "local_dynamic_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
(define_predicate "initial_exec_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC")))
(define_predicate "local_exec_symbolic_operand"
(and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC")))
;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand"
(ior (match_code "symbol_ref")
......
/* { dg-do run } */
/* { dg-options "-O2" } */
__thread double thrtest[81];
int main ()
{
int i;
for (i = 0; i < 81; i++)
thrtest[i] = 1.0;
return 0;
}
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