aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaudiu Zissulescu <claziss@synopsys.com>2018-10-31 12:27:19 +0100
committerClaudiu Zissulescu <claziss@gcc.gnu.org>2018-10-31 12:27:19 +0100
commit8efa18d693207598020f6d7aabb680397ff3815c (patch)
treed14cf258e4d02ce01bf66209ee32c96aa0256a6a
parent088371bfc578852981949bdd0e1643fcb73c7279 (diff)
downloadgcc-8efa18d693207598020f6d7aabb680397ff3815c.zip
gcc-8efa18d693207598020f6d7aabb680397ff3815c.tar.gz
gcc-8efa18d693207598020f6d7aabb680397ff3815c.tar.bz2
[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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/arc/arc.c95
-rw-r--r--gcc/config/arc/arc.md21
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/gcc.target/arc/tls-1.c19
-rw-r--r--gcc/testsuite/gcc.target/arc/tls-gd.c17
-rw-r--r--gcc/testsuite/gcc.target/arc/tls-ie.c17
-rw-r--r--gcc/testsuite/gcc.target/arc/tls-ld.c18
-rw-r--r--gcc/testsuite/gcc.target/arc/tls-le.c16
9 files changed, 135 insertions, 85 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 820b958..ca31cd5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,14 @@
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.
(mulsi3_600_lib): Remove pattern.
(umulsi3_highpart_600_lib_le): Likewise.
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 5443cdd..7cd0a70 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;
-static rtx
-arc_get_tp (void)
-{
- /* 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. */
+/* 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_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv)
+arc_call_tls_get_addr (rtx ti)
{
- 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"
@@ -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 230f4de..f77b04f 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 9c23f1d..fe9cc5b 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,13 @@
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.
2018-10-31 Martin Liska <mliska@suse.cz>
diff --git a/gcc/testsuite/gcc.target/arc/tls-1.c b/gcc/testsuite/gcc.target/arc/tls-1.c
index 3f7a6d4..09f69fa 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 0000000..aa1b542
--- /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 0000000..0c981cf
--- /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 0000000..351c3f0
--- /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 0000000..ae3089b
--- /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" } } */