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> 2005-10-18 Danny Smith <dannysmith@users.sourceforge.net>
* config/i386/winnt-cxx.c (i386_pe_adjust_class_at_definition): * config/i386/winnt-cxx.c (i386_pe_adjust_class_at_definition):
......
...@@ -46,53 +46,6 @@ extern int symbolic_reference_mentioned_p (rtx); ...@@ -46,53 +46,6 @@ extern int symbolic_reference_mentioned_p (rtx);
extern bool extended_reg_mentioned_p (rtx); extern bool extended_reg_mentioned_p (rtx);
extern bool x86_extended_QIreg_mentioned_p (rtx); extern bool x86_extended_QIreg_mentioned_p (rtx);
extern bool x86_extended_reg_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 enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
extern int ix86_expand_movmem (rtx, rtx, rtx, rtx); extern int ix86_expand_movmem (rtx, rtx, rtx, rtx);
......
...@@ -5423,21 +5423,27 @@ legitimate_constant_p (rtx x) ...@@ -5423,21 +5423,27 @@ legitimate_constant_p (rtx x)
return TARGET_64BIT; return TARGET_64BIT;
case UNSPEC_TPOFF: case UNSPEC_TPOFF:
case UNSPEC_NTPOFF: 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: 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: default:
return false; return false;
} }
/* We must have drilled down to a symbol. */ /* 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; return false;
/* FALLTHRU */ /* FALLTHRU */
case SYMBOL_REF: case SYMBOL_REF:
/* TLS symbols are never valid. */ /* TLS symbols are never valid. */
if (tls_symbolic_operand (x, Pmode)) if (SYMBOL_REF_TLS_MODEL (x))
return false; return false;
break; break;
...@@ -5491,7 +5497,9 @@ legitimate_pic_operand_p (rtx x) ...@@ -5491,7 +5497,9 @@ legitimate_pic_operand_p (rtx x)
case UNSPEC_GOTOFF: case UNSPEC_GOTOFF:
return TARGET_64BIT; return TARGET_64BIT;
case UNSPEC_TPOFF: 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: default:
return false; return false;
} }
...@@ -5518,32 +5526,38 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -5518,32 +5526,38 @@ legitimate_pic_address_disp_p (rtx disp)
when they are not dynamic symbols. */ when they are not dynamic symbols. */
if (TARGET_64BIT) if (TARGET_64BIT)
{ {
/* TLS references should always be enclosed in UNSPEC. */ rtx op0 = disp, op1;
if (tls_symbolic_operand (disp, GET_MODE (disp)))
return 0; switch (GET_CODE (disp))
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 = XEXP (XEXP (disp, 0), 0); case LABEL_REF:
rtx op1 = XEXP (XEXP (disp, 0), 1); 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. */ /* TLS references should always be enclosed in UNSPEC. */
if (tls_symbolic_operand (op0, GET_MODE (op0))) if (SYMBOL_REF_TLS_MODEL (op0))
return 0; return false;
if (((GET_CODE (op0) == SYMBOL_REF if (!SYMBOL_REF_FAR_ADDR_P (op0) && SYMBOL_REF_LOCAL_P (op0))
&& !SYMBOL_REF_FAR_ADDR_P (op0) return true;
&& SYMBOL_REF_LOCAL_P (op0)) break;
|| GET_CODE (op0) == LABEL_REF)
&& GET_CODE (op1) == CONST_INT default:
&& INTVAL (op1) < 16*1024*1024 break;
&& INTVAL (op1) >= -16*1024*1024)
return 1;
} }
} }
if (GET_CODE (disp) != CONST) if (GET_CODE (disp) != CONST)
...@@ -5600,11 +5614,17 @@ legitimate_pic_address_disp_p (rtx disp) ...@@ -5600,11 +5614,17 @@ legitimate_pic_address_disp_p (rtx disp)
case UNSPEC_INDNTPOFF: case UNSPEC_INDNTPOFF:
if (saw_plus) if (saw_plus)
return false; 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: 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: 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; return 0;
...@@ -6856,7 +6876,7 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED) ...@@ -6856,7 +6876,7 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
rtx x = *px; rtx x = *px;
if (GET_CODE (x) == SYMBOL_REF 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); cfun->machine->some_ld_name = XSTR (x, 0);
return 1; return 1;
...@@ -7329,17 +7349,18 @@ print_operand_address (FILE *file, rtx addr) ...@@ -7329,17 +7349,18 @@ print_operand_address (FILE *file, rtx addr)
output_addr_const (file, disp); output_addr_const (file, disp);
/* Use one byte shorter RIP relative addressing for 64bit mode. */ /* Use one byte shorter RIP relative addressing for 64bit mode. */
if (TARGET_64BIT if (TARGET_64BIT)
&& ((GET_CODE (disp) == SYMBOL_REF {
&& ! tls_symbolic_operand (disp, GET_MODE (disp))) if (GET_CODE (disp) == CONST
|| GET_CODE (disp) == LABEL_REF
|| (GET_CODE (disp) == CONST
&& GET_CODE (XEXP (disp, 0)) == PLUS && GET_CODE (XEXP (disp, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (disp, 0), 0)) == SYMBOL_REF && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT)
|| GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF) disp = XEXP (XEXP (disp, 0), 0);
&& GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT))) if (GET_CODE (disp) == LABEL_REF
|| (GET_CODE (disp) == SYMBOL_REF
&& SYMBOL_REF_TLS_MODEL (disp) == 0))
fputs ("(%rip)", file); fputs ("(%rip)", file);
} }
}
else else
{ {
if (ASSEMBLER_DIALECT == ASM_ATT) if (ASSEMBLER_DIALECT == ASM_ATT)
......
...@@ -108,7 +108,7 @@ ...@@ -108,7 +108,7 @@
library. Don't count TLS SYMBOL_REFs here, since they should fit library. Don't count TLS SYMBOL_REFs here, since they should fit
only if inside of UNSPEC handled below. */ only if inside of UNSPEC handled below. */
/* TLS symbols are not constant. */ /* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode)) if (SYMBOL_REF_TLS_MODEL (op))
return false; return false;
return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
|| (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op))); || (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
...@@ -147,6 +147,9 @@ ...@@ -147,6 +147,9 @@
switch (GET_CODE (op1)) switch (GET_CODE (op1))
{ {
case SYMBOL_REF: 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 /* For CM_SMALL assume that latest object is 16MB before
end of 31bits boundary. We may also accept pretty end of 31bits boundary. We may also accept pretty
large negative constants knowing that all objects are large negative constants knowing that all objects are
...@@ -225,7 +228,7 @@ ...@@ -225,7 +228,7 @@
case SYMBOL_REF: case SYMBOL_REF:
/* For certain code models, the symbolic references are known to fit. */ /* For certain code models, the symbolic references are known to fit. */
/* TLS symbols are not constant. */ /* TLS symbols are not constant. */
if (tls_symbolic_operand (op, Pmode)) if (SYMBOL_REF_TLS_MODEL (op))
return false; return false;
return (ix86_cmodel == CM_SMALL return (ix86_cmodel == CM_SMALL
|| (ix86_cmodel == CM_MEDIUM || (ix86_cmodel == CM_MEDIUM
...@@ -248,6 +251,9 @@ ...@@ -248,6 +251,9 @@
switch (GET_CODE (op1)) switch (GET_CODE (op1))
{ {
case SYMBOL_REF: 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 /* For small code model we may accept pretty large positive
offsets, since one bit is available for free. Negative offsets, since one bit is available for free. Negative
offsets are limited by the size of NULL pointer area offsets are limited by the size of NULL pointer area
...@@ -456,22 +462,6 @@ ...@@ -456,22 +462,6 @@
(and (match_code "symbol_ref") (and (match_code "symbol_ref")
(match_test "SYMBOL_REF_TLS_MODEL (op) != 0"))) (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 ;; Test for a pc-relative call operand
(define_predicate "constant_call_address_operand" (define_predicate "constant_call_address_operand"
(ior (match_code "symbol_ref") (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