This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[csl-arm] TLS base corrupted before use


The TLS base register can get corrupted before use when a thread local 
variable is used in a function argument.

arm_load_tp uses r0 directly for the TLS base register. This value can then 
get corrupted (eg. by setting up annother function argument) before it is 
used. We need to use the r0 in the load_tp_soft insn otherwise sched1 can 
move the insn somewhere inconvenient, and reload is unable to spill r0. This 
is gcc.dg/tls/opt-5.c

The attached patch fixes this by copying the tls base into a pseudo. In most 
cases this copy will be optimized away, giving the same code as before.

For example:
int __thread i;
void foo()
{
  bar(0, i);
}
Before the patch wwe get:
        ldr     r3, .L2
        mov     r0, #0
        ldr     r1, [r0, r3]
        bl      bar
With the patch we get:
        bl      __aeabi_read_tp @ load_tp_soft
        mov     r2, r0
        ldr     r3, .L2
        mov     r0, #0
        ldr     r1, [r2, r3]
        bl      bar

Tested with cross to arm-none-eabi.
Applied to csl-arm-branch.

Paul

2005-08-30  Paul Brook  <paul@codesourcery.com>

	* config/arm/arm.c (arm_load_tp): Copy result to pseudo.
Index: gcc/config/arm/arm.c
===================================================================
RCS file: /var/cvsroot/gcc-cvs/gcc/gcc/config/arm/arm.c,v
retrieving revision 1.303.2.88
diff -u -p -r1.303.2.88 arm.c
--- gcc/config/arm/arm.c	12 Aug 2005 15:31:02 -0000	1.303.2.88
+++ gcc/config/arm/arm.c	30 Aug 2005 16:57:24 -0000
@@ -3925,20 +3925,25 @@ get_tls_get_addr (void)
 static rtx
 arm_load_tp (rtx target)
 {
+  if (!target)
+    target = gen_reg_rtx (SImode);
+
   if (TARGET_HARD_TP)
     {
       /* Can return in any reg.  */
-      if (!target)
-	target = gen_reg_rtx (SImode);
-      
       emit_insn (gen_load_tp_hard (target));
     }
   else
     {
       /* Always returned in R0 */
-      target = gen_rtx_REG (SImode, 0);
-      
-      emit_insn (gen_load_tp_soft (target));
+      rtx tmp;
+
+      /* Use a hard reg to avoid aborts in reload.  See gcc.dg/opt-5.c  */
+      tmp = gen_rtx_REG (SImode, 0);
+      emit_insn (gen_load_tp_soft (tmp));
+      /* Copy the result into a pseudo, otherwise other uses of r0
+	 (eg.  setting up function arguments) may clobber the value.  */
+      emit_move_insn (target, tmp);
     }
   return target;
 }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]