[ARC] Cleanup TLS implementation and add a number of tests.
gcc/ xxxx-xx-xx Claudiu Zissulescu <claziss@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/ xxxx-xx-xx Claudiu Zissulescu <claziss@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.target/arc/tls-1.c: Update test. From-SVN: r265674
This commit is contained in:
parent
088371bfc5
commit
8efa18d693
@ -1,3 +1,12 @@
|
||||
2018-10-31 Claudiu Zissulescu <claziss@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.
|
||||
|
||||
2018-10-31 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* config/arc/arc.md (mulsi3): Remove call to mulsi_600_lib.
|
||||
|
@ -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 ();
|
||||
}
|
||||
|
@ -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))]
|
||||
|
@ -1,3 +1,11 @@
|
||||
2018-10-31 Claudiu Zissulescu <claziss@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.target/arc/tls-1.c: Update test.
|
||||
|
||||
2018-10-31 Claudiu Zissulescu <claziss@synopsys.com>
|
||||
|
||||
* gcc.target/arc/mulsi3_highpart-2.c: Update test.
|
||||
|
@ -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" } } */
|
||||
|
17
gcc/testsuite/gcc.target/arc/tls-gd.c
Normal file
17
gcc/testsuite/gcc.target/arc/tls-gd.c
Normal file
@ -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" } } */
|
17
gcc/testsuite/gcc.target/arc/tls-ie.c
Normal file
17
gcc/testsuite/gcc.target/arc/tls-ie.c
Normal file
@ -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" } } */
|
18
gcc/testsuite/gcc.target/arc/tls-ld.c
Normal file
18
gcc/testsuite/gcc.target/arc/tls-ld.c
Normal file
@ -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" } } */
|
16
gcc/testsuite/gcc.target/arc/tls-le.c
Normal file
16
gcc/testsuite/gcc.target/arc/tls-le.c
Normal file
@ -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" } } */
|
Loading…
Reference in New Issue
Block a user