* Claudiu Zissulescu <claz...@gmail.com> [2018-10-10 11:00:12 +0300]:
> Cleanup TLS implementation and add a number of tests. > > gcc/ > 2018-07-25 Claudiu Zissulescu <claz...@synopsys.com> > > * 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/ > 2018-07-25 Claudiu Zissulescu <claz...@synopsys.com> > > * 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/config/arc/arc.c | 95 +++++++++++---------------- > gcc/config/arc/arc.md | 21 ------ > gcc/testsuite/gcc.target/arc/tls-1.c | 2 +- > 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 +++++ > 7 files changed, 106 insertions(+), 80 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/config/arc/arc.c b/gcc/config/arc/arc.c > index de4c7433c1b..56f566795ff 100644 > --- a/gcc/config/arc/arc.c > +++ b/gcc/config/arc/arc.c > @@ -5559,51 +5559,30 @@ arc_raw_symbolic_reference_mentioned_p (rtx op, bool > skip_local) > return false; > } > > -/* Get the thread pointer. */ > +/* 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. */ This comment should be moved down to arc_call_tls_get_addr, and a new comment should be added explaining what arc_tls_symbol is used for. Otherwise, this seems fine. Thanks, Andrew > +static GTY(()) rtx arc_tls_symbol; > > 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); > - > - /* 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; > -} > - > -/* Helper to be used by TLS Global dynamic model. */ > - > -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); > + rtx arg = gen_rtx_REG (Pmode, R0_REG); > + rtx ret = gen_rtx_REG (Pmode, R0_REG); > + rtx fn; > + rtx_insn *insn; > > - 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); > + if (!arc_tls_symbol) > + arc_tls_symbol = init_one_libfunc ("__tls_get_addr"); > > - rtx_insn *insns = get_insns (); > - end_sequence (); > + 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); > > - rtx dest = gen_reg_rtx (Pmode); > - emit_libcall_block (insns, dest, r0, eqv); > - return dest; > + return ret; > } > > #define DTPOFF_ZERO_SYM ".tdata" > @@ -5614,16 +5593,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; > @@ -5631,31 +5620,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 d73289a20c4..6ea67791627 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/gcc.target/arc/tls-1.c > b/gcc/testsuite/gcc.target/arc/tls-1.c > index 6521b641549..da21a5ba032 100644 > --- a/gcc/testsuite/gcc.target/arc/tls-1.c > +++ b/gcc/testsuite/gcc.target/arc/tls-1.c > @@ -1,6 +1,6 @@ > /* { dg-do compile } */ > /* { dg-require-effective-target tls } */ > -/* { dg-skip-if "" { arc-*-elf* } } */ > +/* { dg-skip-if "" { arc*-*-elf* } } */ > /* { dg-options "-O3 -std=gnu99" } */ > > /* Check if addressing the `pos` member of struct is done via tls > 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" } } */ > -- > 2.17.1 >