Greetings,

This patch fixes a bug with TLS in which the frame pointer is not
established until after the tlsdesc call, thus not conforming to
the aarch64 procedure call standard.

Changed the tlsdesc instruction patterns to set a dependency on the
x29 frame pointer. This helps the instruction scheduler to arrange
the tlsdesc call after the frame pointer is set.

Example of frame pointer (x29) set incorrectly after tlsdesc call:

stp     x29, x30, [sp, -16]!
adrp    x0, :tlsdesc:.LANCHOR0
ldr     x2, [x0, #:tlsdesc_lo12:.LANCHOR0]
add     x0, x0, :tlsdesc_lo12:.LANCHOR0
.tlsdesccall    .LANCHOR0
blr     x2
...
mov     x29, sp
...

After introducing dependency on x29, the scheduler does the frame
pointer setup before tlsdesc:

stp     x29, x30, [sp, -16]!
mov     x29, sp
adrp    x0, :tlsdesc:.LANCHOR0
ldr     x2, [x0, #:tlsdesc_lo12:.LANCHOR0]
add     x0, x0, :tlsdesc_lo12:.LANCHOR0
.tlsdesccall    .LANCHOR0
blr     x2
...

Testcase used with -O2 -fpic:

void foo()
{
  static __thread int x = 0;
  bar (&x);
}

I am not sure what would classify as an effective check for this
testcase. The only idea I received so far would be to write a regexp
inside a scan-assembler-not that would potentially look for this pattern:

<optional instructions>
.tlsdesccall <label>
blr <reg>
<optional instructions>
[mov x29, sp] OR [add x29, sp, 0]
<optional instructions>

(similar to what was attempted in gcc/testsuite/gcc.target/arm/pr85434.c)

I would like maintainers' input on whether such a testcase should be added
and if there are better ways of checking for the instruction order.

Bootstrapped and tested on aarch64-none-linux-gnu.

Ok for trunk? If yes, I don't have any commit rights, so can someone please
commit it on my behalf.

Cheers,
Syl

gcc/ChangeLog:

2019-06-25  Sylvia Taylor  <sylvia.tay...@arm.com>

        * config/aarch64/aarch64.md
        (tlsdesc_small_advsimd_<mode>): Update.
        (tlsdesc_small_sve_<mode>): Likewise.
        (FP_REGNUM): New.
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 
ff83974aeb0b1bf46415c29ba47ada74a79d7586..099cad54336ccaf2b658fbe9fd7a4a84b3abc6e0
 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -120,6 +120,7 @@
     ;; Scratch registers used in frame layout.
     (IP0_REGNUM         16)
     (IP1_REGNUM         17)
+    (FP_REGNUM         29)
     (LR_REGNUM          30)
   ]
 )
@@ -6617,7 +6618,8 @@
                    UNSPEC_TLSDESC))
    (clobber (reg:DI LR_REGNUM))
    (clobber (reg:CC CC_REGNUM))
-   (clobber (match_scratch:DI 1 "=r"))]
+   (clobber (match_scratch:DI 1 "=r"))
+   (use (reg:DI FP_REGNUM))]
   "TARGET_TLS_DESC && !TARGET_SVE"
   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, 
%L0\;.tlsdesccall\\t%0\;blr\\t%1"
   [(set_attr "type" "call")
@@ -6680,7 +6682,8 @@
    (clobber (reg:VNx2BI P13_REGNUM))
    (clobber (reg:VNx2BI P14_REGNUM))
    (clobber (reg:VNx2BI P15_REGNUM))
-   (clobber (match_scratch:DI 1 "=r"))]
+   (clobber (match_scratch:DI 1 "=r"))
+   (use (reg:DI FP_REGNUM))]
   "TARGET_TLS_DESC && TARGET_SVE"
   "adrp\\tx0, %A0\;ldr\\t%<w>1, [x0, #%L0]\;add\\t<w>0, <w>0, 
%L0\;.tlsdesccall\\t%0\;blr\\t%1"
   [(set_attr "type" "call")

Reply via email to