From 8efa18d693207598020f6d7aabb680397ff3815c Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Wed, 31 Oct 2018 12:27:19 +0100 Subject: [PATCH] [ARC] Cleanup TLS implementation and add a number of tests. gcc/ xxxx-xx-xx Claudiu Zissulescu * config/arc/arc.c (arc_get_tp): Remove function. (arc_emit_call_tls_get_addr): Likewise. (arc_call_tls_get_addr): New function. (arc_legitimize_tls_address): Make use of arc_call_tls_get_addr. * config/arc/arc.md (tls_load_tp_soft): Remove. (tls_gd_get_addr): Likewise. testsuite/ xxxx-xx-xx Claudiu Zissulescu * gcc.target/arc/tls-gd.c: New file. * gcc.target/arc/tls-ie.c: Likewise. * gcc.target/arc/tls-ld.c: Likewise. * gcc.target/arc/tls-le.c: Likewise. * gcc.target/arc/tls-1.c: Update test. From-SVN: r265674 --- gcc/ChangeLog | 9 +++ gcc/config/arc/arc.c | 97 +++++++++++---------------- gcc/config/arc/arc.md | 21 ------ gcc/testsuite/ChangeLog | 8 +++ gcc/testsuite/gcc.target/arc/tls-1.c | 19 ++++-- gcc/testsuite/gcc.target/arc/tls-gd.c | 17 +++++ gcc/testsuite/gcc.target/arc/tls-ie.c | 17 +++++ gcc/testsuite/gcc.target/arc/tls-ld.c | 18 +++++ gcc/testsuite/gcc.target/arc/tls-le.c | 16 +++++ 9 files changed, 136 insertions(+), 86 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arc/tls-gd.c create mode 100644 gcc/testsuite/gcc.target/arc/tls-ie.c create mode 100644 gcc/testsuite/gcc.target/arc/tls-ld.c create mode 100644 gcc/testsuite/gcc.target/arc/tls-le.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 820b958b585..ca31cd59da4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2018-10-31 Claudiu Zissulescu + + * config/arc/arc.c (arc_get_tp): Remove function. + (arc_emit_call_tls_get_addr): Likewise. + (arc_call_tls_get_addr): New function. + (arc_legitimize_tls_address): Make use of arc_call_tls_get_addr. + * config/arc/arc.md (tls_load_tp_soft): Remove. + (tls_gd_get_addr): Likewise. + 2018-10-31 Claudiu Zissulescu * config/arc/arc.md (mulsi3): Remove call to mulsi_600_lib. diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index 5443cdd8b3d..7cd0a70536c 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -5561,51 +5561,32 @@ arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local) return false; } -/* Get the thread pointer. */ +/* The __tls_get_attr symbol. */ +static GTY(()) rtx arc_tls_symbol; + +/* Emit a call to __tls_get_addr. TI is the argument to this function. + RET is an RTX for the return value location. The entire insn sequence + is returned. */ static rtx -arc_get_tp (void) +arc_call_tls_get_addr (rtx ti) { - /* If arc_tp_regno has been set, we can use that hard register - directly as a base register. */ - if (arc_tp_regno != -1) - return gen_rtx_REG (Pmode, arc_tp_regno); + rtx arg = gen_rtx_REG (Pmode, R0_REG); + rtx ret = gen_rtx_REG (Pmode, R0_REG); + rtx fn; + rtx_insn *insn; - /* Otherwise, call __read_tp. Copy the result to a pseudo to avoid - conflicts with function arguments / results. */ - rtx reg = gen_reg_rtx (Pmode); - emit_insn (gen_tls_load_tp_soft ()); - emit_move_insn (reg, gen_rtx_REG (Pmode, R0_REG)); - return reg; -} + if (!arc_tls_symbol) + arc_tls_symbol = init_one_libfunc ("__tls_get_addr"); -/* Helper to be used by TLS Global dynamic model. */ + emit_move_insn (arg, ti); + fn = gen_rtx_MEM (SImode, arc_tls_symbol); + insn = emit_call_insn (gen_call_value (ret, fn, const0_rtx)); + RTL_CONST_CALL_P (insn) = 1; + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), ret); + use_reg (&CALL_INSN_FUNCTION_USAGE (insn), arg); -static rtx -arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv) -{ - rtx r0 = gen_rtx_REG (Pmode, R0_REG); - rtx call_fusage = NULL_RTX; - - start_sequence (); - - rtx x = arc_unspec_offset (sym, reloc); - emit_move_insn (r0, x); - use_reg (&call_fusage, r0); - - gcc_assert (reloc == UNSPEC_TLS_GD); - rtx call_insn = emit_call_insn (gen_tls_gd_get_addr (sym)); - /* Should we set RTL_CONST_CALL_P? We read memory, but not in a - way that the application should care. */ - RTL_PURE_CALL_P (call_insn) = 1; - add_function_usage_to (call_insn, call_fusage); - - rtx_insn *insns = get_insns (); - end_sequence (); - - rtx dest = gen_reg_rtx (Pmode); - emit_libcall_block (insns, dest, r0, eqv); - return dest; + return ret; } #define DTPOFF_ZERO_SYM ".tdata" @@ -5616,16 +5597,26 @@ arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv) static rtx arc_legitimize_tls_address (rtx addr, enum tls_model model) { + rtx tmp; + if (!flag_pic && model == TLS_MODEL_LOCAL_DYNAMIC) model = TLS_MODEL_LOCAL_EXEC; + + /* The TP pointer needs to be set. */ + gcc_assert (arc_tp_regno != -1); + switch (model) { + case TLS_MODEL_GLOBAL_DYNAMIC: + tmp = gen_reg_rtx (Pmode); + emit_move_insn (tmp, arc_unspec_offset (addr, UNSPEC_TLS_GD)); + return arc_call_tls_get_addr (tmp); + case TLS_MODEL_LOCAL_DYNAMIC: rtx base; tree decl; const char *base_name; - rtvec v; decl = SYMBOL_REF_DECL (addr); base_name = DTPOFF_ZERO_SYM; @@ -5633,31 +5624,21 @@ arc_legitimize_tls_address (rtx addr, enum tls_model model) base_name = ".tbss"; base = gen_rtx_SYMBOL_REF (Pmode, base_name); - if (strcmp (base_name, DTPOFF_ZERO_SYM) == 0) - { - if (!flag_pic) - goto local_exec; - v = gen_rtvec (1, addr); - } - else - v = gen_rtvec (2, addr, base); - addr = gen_rtx_UNSPEC (Pmode, v, UNSPEC_TLS_OFF); - addr = gen_rtx_CONST (Pmode, addr); - base = arc_legitimize_tls_address (base, TLS_MODEL_GLOBAL_DYNAMIC); - return gen_rtx_PLUS (Pmode, force_reg (Pmode, base), addr); - - case TLS_MODEL_GLOBAL_DYNAMIC: - return arc_emit_call_tls_get_addr (addr, UNSPEC_TLS_GD, addr); + tmp = gen_reg_rtx (Pmode); + emit_move_insn (tmp, arc_unspec_offset (base, UNSPEC_TLS_GD)); + base = arc_call_tls_get_addr (tmp); + return gen_rtx_PLUS (Pmode, force_reg (Pmode, base), + arc_unspec_offset (addr, UNSPEC_TLS_OFF)); case TLS_MODEL_INITIAL_EXEC: addr = arc_unspec_offset (addr, UNSPEC_TLS_IE); addr = copy_to_mode_reg (Pmode, gen_const_mem (Pmode, addr)); - return gen_rtx_PLUS (Pmode, arc_get_tp (), addr); + return gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, arc_tp_regno), addr); case TLS_MODEL_LOCAL_EXEC: - local_exec: addr = arc_unspec_offset (addr, UNSPEC_TLS_OFF); - return gen_rtx_PLUS (Pmode, arc_get_tp (), addr); + return gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode, arc_tp_regno), addr); + default: gcc_unreachable (); } diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 230f4de9883..f77b04f5460 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -5310,27 +5310,6 @@ archs4x, archs4xd, archs4xd_slow" [(set_attr "type" "call") (set_attr "is_SIBCALL" "yes")]) -(define_insn "tls_load_tp_soft" - [(set (reg:SI R0_REG) (unspec:SI [(const_int 0)] UNSPEC_TLS_OFF)) - (clobber (reg:SI RETURN_ADDR_REGNUM))] - "" - "*return arc_output_libcall (\"__read_tp\");" - [(set_attr "is_sfunc" "yes") - (set_attr "predicable" "yes")]) - -(define_insn "tls_gd_get_addr" - [(set (reg:SI R0_REG) - (call:SI (mem:SI (unspec:SI [(match_operand:SI 0 - "symbolic_operand" "X,X")] - UNSPEC_TLS_GD)) - (const_int 0))) - (clobber (reg:SI RETURN_ADDR_REGNUM))] - "" - ".tls_gd_ld %0`bl%* __tls_get_addr@plt" - [(set_attr "type" "call") - ; With TARGET_MEDIUM_CALLS, plt calls are not predicable. - (set_attr "predicable" "no")]) - ;; For thread pointer builtins (define_expand "get_thread_pointersi" [(set (match_operand:SI 0 "register_operand") (match_dup 1))] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9c23f1df1ed..fe9cc5b6ff8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2018-10-31 Claudiu Zissulescu + + * gcc.target/arc/tls-gd.c: New file. + * gcc.target/arc/tls-ie.c: Likewise. + * gcc.target/arc/tls-ld.c: Likewise. + * gcc.target/arc/tls-le.c: Likewise. + * gcc.target/arc/tls-1.c: Update test. + 2018-10-31 Claudiu Zissulescu * gcc.target/arc/mulsi3_highpart-2.c: Update test. diff --git a/gcc/testsuite/gcc.target/arc/tls-1.c b/gcc/testsuite/gcc.target/arc/tls-1.c index 3f7a6d49f59..09f69fa53d8 100644 --- a/gcc/testsuite/gcc.target/arc/tls-1.c +++ b/gcc/testsuite/gcc.target/arc/tls-1.c @@ -1,26 +1,31 @@ /* { dg-do compile } */ /* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ /* { dg-options "-O3 -std=gnu99" } */ /* Check if addressing the `pos` member of struct is done via tls mechanism. */ -struct callchain_cursor { +struct callchain_cursor +{ int last; long long pos; } __thread a; -void fn1(struct callchain_cursor *p1) + +void fn1 (struct callchain_cursor *p1) { p1->pos++; } extern void fn3 (void); -void fn2(void) { +void fn2 (void) +{ struct callchain_cursor *b = &a; - while (1) { - fn3(); - fn1(b); - } + while (1) + { + fn3 (); + fn1 (b); + } } /* { dg-final { scan-assembler "r25,@a@tpoff" } } */ diff --git a/gcc/testsuite/gcc.target/arc/tls-gd.c b/gcc/testsuite/gcc.target/arc/tls-gd.c new file mode 100644 index 00000000000..aa1b5429b08 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-gd.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fpic -ftls-model=global-dynamic" } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ + +/* Check if tls global dynamic is correctly generated. */ + +extern __thread int e2; + +int *ae2 (void) +{ + return &e2; +} + +/* { dg-final { scan-assembler "add r0,pcl,@e2@tlsgd" } } */ +/* { dg-final { scan-assembler "bl @__tls_get_addr@plt" } } */ diff --git a/gcc/testsuite/gcc.target/arc/tls-ie.c b/gcc/testsuite/gcc.target/arc/tls-ie.c new file mode 100644 index 00000000000..0c981cfbf67 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-ie.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fpic -ftls-model=initial-exec" } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ + +/* Check if tls initial execution is correctly generated. */ + +extern __thread int e2; + +int *ae2 (void) +{ + return &e2; +} + +/* { dg-final { scan-assembler "ld r0,\\\[pcl,@e2@tlsie\\\]" } } */ +/* { dg-final { scan-assembler "add_s r0,r0,r25" } } */ diff --git a/gcc/testsuite/gcc.target/arc/tls-ld.c b/gcc/testsuite/gcc.target/arc/tls-ld.c new file mode 100644 index 00000000000..351c3f02abd --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-ld.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fpic -ftls-model=local-dynamic" } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ + +/* Check if tls local dynamic is correctly generated. */ + +extern __thread int e2; + +int *ae2 (void) +{ + return &e2; +} + +/* { dg-final { scan-assembler "add r0,pcl,@.tbss@tlsgd" } } */ +/* { dg-final { scan-assembler "bl @__tls_get_addr@plt" } } */ +/* { dg-final { scan-assembler "add_s r0,r0,@e2@dtpoff" } } */ diff --git a/gcc/testsuite/gcc.target/arc/tls-le.c b/gcc/testsuite/gcc.target/arc/tls-le.c new file mode 100644 index 00000000000..ae3089b5070 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/tls-le.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target fpic } */ +/* { dg-options "-O2 -fpic -ftls-model=local-exec" } */ +/* { dg-require-effective-target tls } */ +/* { dg-skip-if "" { arc*-*-elf* } } */ + +/* Check if tls local execution is correctly generated. */ + +extern __thread int e2; + +int *ae2 (void) +{ + return &e2; +} + +/* { dg-final { scan-assembler "add r0,r25,@e2@tpoff" } } */