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")