2002-08-08 Jakub Jelinek * config/i386/i386.c (legitimate_constant_p): UNSPEC_TP is not legitimate constant. (legitimate_pic_operand_p): Neither pic operand. (legitimate_address_p): But legitimate address. (get_thread_pointer): Generate MEM/u instead of CONST around UNSPEC_TP. (print_operand): Remove printing of UNSPEC_TP. (print_operand_address): And print it here. * gcc.dg/tls/opt-2.c: New test. --- gcc/config/i386/i386.c.jj 2002-08-07 22:18:39.000000000 +0200 +++ gcc/config/i386/i386.c 2002-08-08 18:18:18.000000000 +0200 @@ -4861,8 +4861,6 @@ { case UNSPEC_TPOFF: return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode); - case UNSPEC_TP: - return true; default: return false; } @@ -4921,8 +4919,6 @@ { case UNSPEC_TPOFF: return local_exec_symbolic_operand (XVECEXP (inner, 0, 0), Pmode); - case UNSPEC_TP: - return true; default: return false; } @@ -5048,6 +5044,13 @@ debug_rtx (addr); } + if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP) + { + if (TARGET_DEBUG_ADDR) + fprintf (stderr, "Success.\n"); + return TRUE; + } + if (ix86_decompose_address (addr, &parts) <= 0) { reason = "decomposition failed"; @@ -5499,7 +5502,9 @@ rtx tp; tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP); - tp = gen_rtx_CONST (Pmode, tp); + tp = gen_rtx_MEM (Pmode, tp); + RTX_UNCHANGING_P (tp) = 1; + set_mem_alias_set (tp, ix86_GOT_alias_set ()); tp = force_reg (Pmode, tp); return tp; @@ -6613,17 +6618,6 @@ fprintf (file, "%s", dstr); } - else if (GET_CODE (x) == CONST - && GET_CODE (XEXP (x, 0)) == UNSPEC - && XINT (XEXP (x, 0), 1) == UNSPEC_TP) - { - if (ASSEMBLER_DIALECT == ASM_INTEL) - fputs ("DWORD PTR ", file); - if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0) - putc ('%', file); - fputs ("gs:0", file); - } - else { if (code != 'P') @@ -6662,6 +6656,16 @@ rtx base, index, disp; int scale; + if (GET_CODE (addr) == UNSPEC && XINT (addr, 1) == UNSPEC_TP) + { + if (ASSEMBLER_DIALECT == ASM_INTEL) + fputs ("DWORD PTR ", file); + if (ASSEMBLER_DIALECT == ASM_ATT || USER_LABEL_PREFIX[0] == 0) + putc ('%', file); + fputs ("gs:0", file); + return; + } + if (! ix86_decompose_address (addr, &parts)) { output_operand_lossage ("Wrong address expression or operand constraint"); --- gcc/testsuite/gcc.dg/tls/opt-2.c.jj 2002-08-08 18:36:32.000000000 +0200 +++ gcc/testsuite/gcc.dg/tls/opt-2.c 2002-08-08 18:34:44.000000000 +0200 @@ -0,0 +1,53 @@ +/* This testcase generated invalid assembly on IA-32, + since %gs:0 memory load was not exposed to the compiler + as memory load and mem to mem moves are not possible + on IA-32. */ +/* { dg-do link } */ +/* { dg-options "-O2 -ftls-model=initial-exec" } */ +/* { dg-options "-O2 -ftls-model=initial-exec -march=i686" { target i?86-*-* } } */ + +__thread int thr; + +struct A +{ + unsigned int a, b, c, d, e; +}; + +int bar (int x, unsigned long y, void *z) +{ + return 0; +} + +int +foo (int x, int y, const struct A *z) +{ + struct A b; + int d; + + b = *z; + d = bar (x, y, &b); + if (d == 0 && y == 0x5402) + { + int e = thr; + d = bar (x, 0x5401, &b); + if (d) + { + thr = e; + d = 0; + } + else if ((z->c & 0600) != (b.c & 0600) + || ((z->c & 060) && ((z->c & 060) != (b.c & 060)))) + { + thr = 22; + d = -1; + } + } + + return d; +} + +int main (void) +{ + foo (1, 2, 0); + return 0; +}