===================================================================
@@ -12785,6 +12785,9 @@ legitimize_tls_address (rtx x, enum tls_model mode
tp = get_thread_pointer (Pmode, true);
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, tp, dest));
+ if (GET_MODE (x) != Pmode)
+ x = gen_rtx_ZERO_EXTEND (Pmode, x);
+
set_unique_reg_note (get_last_insn (), REG_EQUAL, x);
}
else
@@ -12793,15 +12796,20 @@ legitimize_tls_address (rtx x, enum tls_model mode
if (TARGET_64BIT)
{
- rtx rax = gen_rtx_REG (Pmode, AX_REG), insns;
+ rtx rax = gen_rtx_REG (Pmode, AX_REG);
+ rtx insns;
start_sequence ();
- emit_call_insn (ix86_gen_tls_global_dynamic_64 (rax, x,
- caddr));
+ emit_call_insn
+ (ix86_gen_tls_global_dynamic_64 (rax, x, caddr));
insns = get_insns ();
end_sequence ();
RTL_CONST_CALL_P (insns) = 1;
+
+ if (GET_MODE (x) != Pmode)
+ x = gen_rtx_ZERO_EXTEND (Pmode, x);
+
emit_libcall_block (insns, dest, rax, x);
}
else
@@ -12842,11 +12850,12 @@ legitimize_tls_address (rtx x, enum tls_model mode
if (TARGET_64BIT)
{
- rtx rax = gen_rtx_REG (Pmode, AX_REG), insns, eqv;
+ rtx rax = gen_rtx_REG (Pmode, AX_REG);
+ rtx insns, eqv;
start_sequence ();
- emit_call_insn (ix86_gen_tls_local_dynamic_base_64 (rax,
- caddr));
+ emit_call_insn
+ (ix86_gen_tls_local_dynamic_base_64 (rax, caddr));
insns = get_insns ();
end_sequence ();
@@ -12871,6 +12880,9 @@ legitimize_tls_address (rtx x, enum tls_model mode
{
dest = force_reg (Pmode, gen_rtx_PLUS (Pmode, dest, tp));
+ if (GET_MODE (x) != Pmode)
+ x = gen_rtx_ZERO_EXTEND (Pmode, x);
+
set_unique_reg_note (get_last_insn (), REG_EQUAL, x);
}
break;
===================================================================
@@ -0,0 +1,18 @@
+/* { dg-do compile { target { ! { ia32 } } } } */
+/* { dg-require-effective-target fpic } */
+/* { dg-options "-O2 -fPIC -mx32 -maddress-mode=long" } */
+
+struct initial_sp
+{
+ void *sp;
+ int mask;
+};
+
+__thread struct initial_sp __morestack_initial_sp;
+
+void foo (int *);
+
+void __morestack_release_segments (void)
+{
+ foo (&__morestack_initial_sp.mask);
+}
Hello! On x32, SImode and DImode symbols are accepted as valid. When SImode symbol is legitimized through legitimize_tls_address, we use Pmode operations and temporaries (in case of -maddress-mode=long, Pmode equals to DImode). In case of Pmode == DImode, we forgot to extend the mode of a sybmol from SImode to DImode, and we set REG_EQUAL to a symbol in wrong mode. The patch extends SImode symbols to DImode using ZERO_EXTEND RTX. 2012-12-06 Uros Bizjak <ubizjak@gmail.com> H.J. Lu <hongjiu.lu@intel.com> PR target/55597 * config/i386/i386.c (legitimize_tls_address): Zero-extend x to Pmode, before using it as insn or call equivalent. testsuite/ChangeLog: 2012-12-06 Uros Bizjak <ubizjak@gmail.com> PR target/55597 * gcc.target/i386/pr55597.c: New test. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32} and by H.J. on x32. Patch was committed to mainline SVN, and will be committed to 4.7. Uros.