https://gcc.gnu.org/g:fa37f57173e247d274139a69a2ceb37a26041f9c
commit r17-4608-gfa37f57173e247d274139a69a2ceb37a26041f9c Author: Vijay Shankar <[email protected]> Date: Wed Aug 26 15:49:01 2026 -0500 rs6000: Optimize TLS access with combine patterns [PR27479] Reduce TLS variable access from 3 to 2 instructions by adding combine patterns that merge address calculation with load. Before addis 9,13,x@tprel@ha addi 9,9,x@tprel@l lwz 3,0(9) After addis 9,13,x@tprel@ha lwz 3,x@tprel@l(9) Bootstrapped and tested on powerpc64le-linux-gnu with no regressions. Bootstrapped and tested on powerpc64-linux-gnu with no regressions. 2026-04-15 Vijay Shankar <[email protected]> gcc/ChangeLog: PR target/27479 * config/rs6000/rs6000.md (tprel_ld_<az>_<HSI:mode>): New pattern. (tprel_ld_QI_signed): likewise. (tprel_ld_QI): likewise. (tprel_ld_DI): likewise. (tprel_ld_<SFDF:mode>): likewise. gcc/testsuite/ChangeLog: PR target/27479 * gcc.target/powerpc/pr27479.c: New Test. Diff: --- gcc/config/rs6000/rs6000.md | 73 +++++++++++++++++++++++ gcc/testsuite/gcc.target/powerpc/pr27479.c | 95 ++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index ddfed3b63bc0..8f694ac4d1c6 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -10650,6 +10650,79 @@ "la %0,%1@got@tlsgd@pcrel" [(set_attr "prefixed" "yes")]) +;;combine patterns for tls access +(define_insn "*tprel_ld_<az>_<HSI:mode>" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (any_extend:DI + (mem:HSI + (unspec:P + [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSTPRELLO))))] + "HAVE_AS_TLS" + "l<HSI:wd><az> %0,%2@tprel@l(%1)" + [(set_attr "type" "load")]) + +;; Two instructions needed: lbz (zero-extend load byte) + extsb (sign-extend) +;; because there is no sign-extended load byte instruction, only zero-extended. +(define_insn_and_split "*tprel_ld_QI_signed" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (sign_extend:DI + (mem:QI + (unspec:P + [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSTPRELLO))))] + "HAVE_AS_TLS" + "#" + "&& reload_completed" + [(set (match_dup 0) + (zero_extend:DI + (mem:QI + (unspec:P + [(match_dup 1) + (match_dup 2)] + UNSPEC_TLSTPRELLO)))) + (set (match_dup 0) + (sign_extend:DI (match_dup 3)))] + { + operands[3] = gen_lowpart (QImode, operands[0]); + }) + +(define_insn "*tprel_ld_QI" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (zero_extend:DI + (mem:QI + (unspec:P + [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSTPRELLO))))] + "HAVE_AS_TLS" + "lbz %0,%2@tprel@l(%1)" + [(set_attr "type" "load")]) + +(define_insn "*tprel_ld_DI" + [(set (match_operand:DI 0 "gpc_reg_operand" "=r") + (mem:DI + (unspec:P + [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSTPRELLO)))] + "HAVE_AS_TLS" + "ld %0,%2@tprel@l(%1)" + [(set_attr "type" "load")]) + +(define_insn "*tprel_ld_<SFDF:mode>" + [(set (match_operand:SFDF 0 "gpc_reg_operand" "=f") + (mem:SFDF + (unspec:P + [(match_operand:P 1 "gpc_reg_operand" "b") + (match_operand:P 2 "rs6000_tls_symbol_ref" "")] + UNSPEC_TLSTPRELLO)))] + "HAVE_AS_TLS" + "lf<SFDF:sd> %0,%2@tprel@l(%1)" + [(set_attr "type" "fpload")]) + (define_insn_and_split "*tls_gd<bits>" [(set (match_operand:P 0 "gpc_reg_operand" "=b") (unspec:P [(match_operand:P 1 "rs6000_tls_symbol_ref" "") diff --git a/gcc/testsuite/gcc.target/powerpc/pr27479.c b/gcc/testsuite/gcc.target/powerpc/pr27479.c new file mode 100644 index 000000000000..de05237ba5a3 --- /dev/null +++ b/gcc/testsuite/gcc.target/powerpc/pr27479.c @@ -0,0 +1,95 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mdejagnu-cpu=power9" } */ + +/* verify TLS access for PR27479 */ + +/* TLS variables of many types. */ +__thread unsigned char t_uc; +__thread signed char t_sc; +__thread unsigned short t_us; +__thread short t_ss; +__thread unsigned int t_ui; +__thread int t_si; +__thread unsigned long t_ul; +__thread long t_sl; +__thread _Bool t_bool; +__thread int *t_ptr; + +/* Floating-point. */ +__thread float t_f; +__thread double t_d; + +unsigned long +foo_uc (void) +{ + return t_uc; +} + +long +foo_sc (void) +{ + return t_sc; +} + +unsigned long +foo_us (void) +{ + return t_us; +} + +long +foo_ss (void) +{ + return t_ss; +} + +unsigned long +foo_ui (void) +{ + return t_ui; +} + +long +foo_si (void) +{ + return t_si; +} + +unsigned long +foo_ul (void) +{ + return t_ul; +} + +long +foo_sl (void) +{ + return t_sl; +} + +unsigned long +foo_bool (void) +{ + return t_bool; +} + +int * +foo_ptr (void) +{ + return t_ptr; +} + +/* Floating-point accessors. */ +float +foo_f (void) +{ + return t_f; +} + +double +foo_d (void) +{ + return t_d; +} + +/* { dg-final { scan-assembler-not {\maddi\M} } } */
