From: Monk Chiang <m...@andestech.com>

Monk Chiang  <sh.chian...@gmail.com>
Kito Cheng  <kito.ch...@gmail.com>
Shiva Chen  <shiva0...@gmail.com>

ChangeLog
gcc/
        * config/nds32/nds32-md-auxiliary.c (nds32_legitimize_pic_address):
        Use new PIC pattern.
        (nds32_legitimize_tls_address): Use new TLS pattern.
        (nds32_output_symrel): New.
        * config/nds32/nds32-protos.h (nds32_output_symrel): Declare.
        (nds32_alloc_relax_group_id): Ditto.
        * config/nds32/nds32-relax-opt.c (nds32_alloc_relax_group_id):
        New.
        (nds32_group_insns): Use nds32_alloc_relax_group_id instead of
        use relax_group_id.
        (nds32_group_tls_insn): Ditto.
        (nds32_group_float_insns): Ditto.
        * config/nds32/nds32.md (tls_le): New.
        (sym_got): Ditto.

gcc/testsuite/

        * gcc.target/nds32/pic.c: New.
        * gcc.target/nds32/tls-le.c: Ditto.
---
 gcc/config/nds32/nds32-md-auxiliary.c   | 43 ++++++++++++++++++++++-----------
 gcc/config/nds32/nds32-protos.h         |  3 +++
 gcc/config/nds32/nds32-relax-opt.c      | 19 ++++++++-------
 gcc/config/nds32/nds32.md               | 27 +++++++++++++++++++++
 gcc/testsuite/gcc.target/nds32/pic.c    | 42 ++++++++++++++++++++++++++++++++
 gcc/testsuite/gcc.target/nds32/tls-le.c | 17 +++++++++++++
 6 files changed, 128 insertions(+), 23 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/nds32/pic.c
 create mode 100644 gcc/testsuite/gcc.target/nds32/tls-le.c

diff --git a/gcc/config/nds32/nds32-md-auxiliary.c 
b/gcc/config/nds32/nds32-md-auxiliary.c
index 3c510cf..35fcc64 100644
--- a/gcc/config/nds32/nds32-md-auxiliary.c
+++ b/gcc/config/nds32/nds32-md-auxiliary.c
@@ -3493,6 +3493,7 @@ nds32_legitimize_pic_address (rtx x)
   rtx addr = x;
   rtx reg = gen_reg_rtx (Pmode);
   rtx pat;
+  int relax_group_id = nds32_alloc_relax_group_id ();
 
   if (GET_CODE (x) == LABEL_REF
       || (GET_CODE (x) == SYMBOL_REF
@@ -3501,16 +3502,14 @@ nds32_legitimize_pic_address (rtx x)
     {
       addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOTOFF);
       addr = gen_rtx_CONST (SImode, addr);
-      emit_insn (gen_sethi (reg, addr));
-      emit_insn (gen_lo_sum (reg, reg, addr));
+      emit_insn (gen_sym_got (reg, addr, GEN_INT (relax_group_id)));
       x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx);
     }
   else if (GET_CODE (x) == SYMBOL_REF)
     {
       addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_GOT);
       addr = gen_rtx_CONST (SImode, addr);
-      emit_insn (gen_sethi (reg, addr));
-      emit_insn (gen_lo_sum (reg, reg, addr));
+      emit_insn (gen_sym_got (reg, addr, GEN_INT (relax_group_id)));
 
       x = gen_const_mem (SImode, gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
                                               reg));
@@ -3534,8 +3533,7 @@ nds32_legitimize_pic_address (rtx x)
          pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), UNSPEC_GOTOFF);
          pat = gen_rtx_PLUS (Pmode, pat, op1);
          pat = gen_rtx_CONST (Pmode, pat);
-         emit_insn (gen_sethi (reg, pat));
-         emit_insn (gen_lo_sum (reg, reg, pat));
+         emit_insn (gen_sym_got (reg, pat, GEN_INT (relax_group_id)));
          x = gen_rtx_PLUS (Pmode, reg, pic_offset_table_rtx);
        }
       else if (GET_CODE (op0) == SYMBOL_REF
@@ -3544,8 +3542,8 @@ nds32_legitimize_pic_address (rtx x)
          /* This is a constant offset from a @GOT symbol reference.  */
          addr = gen_rtx_UNSPEC (SImode, gen_rtvec (1, op0), UNSPEC_GOT);
          addr = gen_rtx_CONST (SImode, addr);
-         emit_insn (gen_sethi (reg, addr));
-         emit_insn (gen_lo_sum (reg, reg, addr));
+         emit_insn (gen_sym_got (reg, addr, GEN_INT (relax_group_id)));
+
          addr = gen_const_mem (SImode, gen_rtx_PLUS (Pmode,
                                                      pic_offset_table_rtx,
                                                      reg));
@@ -3668,6 +3666,7 @@ nds32_legitimize_tls_address (rtx x)
   rtx tmp_reg;
   rtx tp_reg = gen_rtx_REG (Pmode, TP_REGNUM);
   rtx pat, insns, reg0;
+  int relax_group_id = nds32_alloc_relax_group_id ();
 
   if (GET_CODE (x) == SYMBOL_REF)
     switch (SYMBOL_REF_TLS_MODEL (x))
@@ -3685,7 +3684,7 @@ nds32_legitimize_tls_address (rtx x)
        reg0 = gen_rtx_REG (Pmode, 0);
        /* If we can confirm all clobber reigsters, it doesn't have to use call
           instruction.  */
-       insns = emit_call_insn (gen_tls_desc (pat, GEN_INT (0)));
+       insns = emit_call_insn (gen_tls_desc (pat, GEN_INT (relax_group_id)));
        use_reg (&CALL_INSN_FUNCTION_USAGE (insns), pic_offset_table_rtx);
        RTL_CONST_CALL_P (insns) = 1;
        tmp_reg = gen_reg_rtx (SImode);
@@ -3697,7 +3696,7 @@ nds32_legitimize_tls_address (rtx x)
        pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSIE);
        tmp_reg  = gen_reg_rtx (SImode);
        pat = gen_rtx_CONST (SImode, pat);
-       emit_insn (gen_tls_ie (tmp_reg, pat, GEN_INT (0)));
+       emit_insn (gen_tls_ie (tmp_reg, pat, GEN_INT (relax_group_id)));
        if (flag_pic)
          emit_use (pic_offset_table_rtx);
        x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg);
@@ -3711,8 +3710,7 @@ nds32_legitimize_tls_address (rtx x)
        tmp_reg  = gen_reg_rtx (SImode);
        pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, x), UNSPEC_TLSLE);
        pat = gen_rtx_CONST (SImode, pat);
-       emit_insn (gen_sethi (tmp_reg, pat));
-       emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat));
+       emit_insn (gen_tls_le (tmp_reg, pat, GEN_INT (relax_group_id)));
        x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg);
        break;
 
@@ -3734,8 +3732,7 @@ nds32_legitimize_tls_address (rtx x)
          pat = gen_rtx_UNSPEC (SImode, gen_rtvec (1, base), UNSPEC_TLSLE);
          pat = gen_rtx_PLUS (SImode, pat, addend);
          pat = gen_rtx_CONST (SImode, pat);
-         emit_insn (gen_sethi (tmp_reg, pat));
-         emit_insn (gen_lo_sum (tmp_reg, tmp_reg, pat));
+         emit_insn (gen_tls_le (tmp_reg, pat, GEN_INT (relax_group_id)));
          x = gen_rtx_PLUS (Pmode, tmp_reg, tp_reg);
        }
     }
@@ -3914,3 +3911,21 @@ nds32_output_tls_ie (rtx *operands)
   output_asm_insn (pattern, operands);
   return "";
 }
+
+const char *
+nds32_output_symrel (rtx *operands)
+{
+  char pattern[1000];
+
+  if (TARGET_RELAX_HINT)
+    snprintf (pattern, sizeof (pattern),
+             ".relax_hint %%2\n\tsethi %%0, hi20(%%1)\n\t"
+             ".relax_hint %%2\n\tori %%0, %%0, lo12(%%1)");
+  else
+    snprintf (pattern, sizeof (pattern),
+             "sethi %%0, hi20(%%1)\n\t"
+             "ori %%0, %%0, lo12(%%1)");
+
+  output_asm_insn (pattern, operands);
+  return "";
+}
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index 38aaca9..aaa65d6 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -256,6 +256,7 @@ extern const char *nds32_output_call (rtx, rtx *, rtx,
                                      const char *, const char *, bool);
 extern const char *nds32_output_tls_desc (rtx *);
 extern const char *nds32_output_tls_ie (rtx *);
+extern const char *nds32_output_symrel (rtx *);
 
 /* Auxiliary functions to output stack push/pop instruction.  */
 
@@ -369,4 +370,6 @@ extern bool nds32_use_load_post_increment(machine_mode);
 extern rtl_opt_pass *make_pass_nds32_relax_opt (gcc::context *);
 extern rtl_opt_pass *make_pass_nds32_fp_as_gp (gcc::context *);
 
+extern int nds32_alloc_relax_group_id ();
+
 /* ------------------------------------------------------------------------ */
diff --git a/gcc/config/nds32/nds32-relax-opt.c 
b/gcc/config/nds32/nds32-relax-opt.c
index 25be202..5da2753 100644
--- a/gcc/config/nds32/nds32-relax-opt.c
+++ b/gcc/config/nds32/nds32-relax-opt.c
@@ -78,6 +78,12 @@ static int relax_group_id = 0;
       lwi37    $rb, [(sym)]
       swi37    $rc, [(sym)] */
 
+int
+nds32_alloc_relax_group_id ()
+{
+  return relax_group_id++;
+}
+
 /* Return true if is load/store with REG addressing mode
    and memory mode is SImode.  */
 static bool
@@ -345,7 +351,7 @@ nds32_group_insns (rtx_insn *sethi)
        return;
     }
 
-  group_id = GEN_INT (relax_group_id);
+  group_id = GEN_INT (nds32_alloc_relax_group_id ());
   /* Insert .relax_* directive for sethi.  */
   emit_insn_before (gen_relax_group (group_id), sethi);
 
@@ -378,8 +384,6 @@ nds32_group_insns (rtx_insn *sethi)
            }
        }
     }
-
-  relax_group_id++;
 }
 
 /* Convert relax group id in rtl.  */
@@ -389,6 +393,7 @@ nds32_group_tls_insn (rtx insn)
 {
   rtx pat = PATTERN (insn);
   rtx unspec_relax_group = XEXP (XVECEXP (pat, 0, 1), 0);
+  int group_id = nds32_alloc_relax_group_id ();
 
   while (GET_CODE (pat) != SET && GET_CODE (pat) == PARALLEL)
     {
@@ -398,10 +403,8 @@ nds32_group_tls_insn (rtx insn)
   if (GET_CODE (unspec_relax_group) == UNSPEC
       && XINT (unspec_relax_group, 1) == UNSPEC_VOLATILE_RELAX_GROUP)
     {
-      XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (relax_group_id);
+      XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (group_id);
     }
-
-  relax_group_id++;
 }
 
 static bool
@@ -472,7 +475,7 @@ nds32_group_float_insns (rtx_insn *insn)
        return;
     }
 
-  group_id = GEN_INT (relax_group_id);
+  group_id = GEN_INT (nds32_alloc_relax_group_id ());
   /* Insert .relax_* directive for insn.  */
   emit_insn_before (gen_relax_group (group_id), insn);
 
@@ -487,8 +490,6 @@ nds32_group_float_insns (rtx_insn *insn)
       /* Insert .relax_* directive.  */
        emit_insn_before (gen_relax_group (group_id), use_insn);
     }
-
-  relax_group_id++;
 }
 
 /* Group the relax candidate instructions for linker.  */
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index f9eba0a..1e5f8de 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -2365,6 +2365,20 @@
    (set_attr "type" "misc")]
 )
 
+;; There is a unspec operand to record RELAX_GROUP number because each
+;; emitted instruction need a relax_hint above it.
+(define_insn "tls_le"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] 
UNSPEC_TLS_IE))
+   (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] 
UNSPEC_VOLATILE_RELAX_GROUP))]
+  ""
+  {
+    return nds32_output_symrel (operands);
+  }
+  [(set_attr "length" "8")
+   (set_attr "type"   "misc")]
+)
+
 ;; The pattern is for some relaxation groups that have to keep addsi3 in 
32-bit mode.
 (define_insn "addsi3_32bit"
   [(set (match_operand:SI 0 "register_operand"             "=r")
@@ -2376,4 +2390,17 @@
    (set_attr "length"  "4")
    (set_attr "feature" "v1")])
 
+;; Patterns for PIC.
+(define_insn "sym_got"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (unspec:SI [(match_operand:SI 1 "nds32_symbolic_operand" "i")] 
UNSPEC_GOT))
+   (use (unspec [(match_operand:SI 2 "immediate_operand" "i")] 
UNSPEC_VOLATILE_RELAX_GROUP))]
+  ""
+  {
+    return nds32_output_symrel (operands);
+  }
+  [(set_attr "length" "8")
+   (set_attr "type"   "misc")]
+)
+
 ;; ----------------------------------------------------------------------------
diff --git a/gcc/testsuite/gcc.target/nds32/pic.c 
b/gcc/testsuite/gcc.target/nds32/pic.c
new file mode 100644
index 0000000..ef62f50
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nds32/pic.c
@@ -0,0 +1,42 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -fdump-rtl-final" } */
+
+struct __locale_struct
+{
+  struct __locale_data *__locales[13];
+};
+
+struct __locale_data
+{
+  const char *name;
+};
+
+extern struct __locale_struct _nl_global_locale __attribute__ ((visibility 
("hidden")));
+
+static void
+setdata (int category, struct __locale_data *data)
+{
+  _nl_global_locale.__locales[category] = data;
+}
+
+char *
+setlocale (int category, const char *locale)
+{
+  char *composite;
+
+  struct __locale_data *newdata[13];
+
+  for (category = 0; category < 13; ++category)
+    if (category != 6)
+      {
+        setdata (category, newdata[category]);
+      }
+  return composite;
+}
+
+/* Check that PIC pattern only generate one RTL pattern for sethi and ori
+   to pass verify_rtx_sharing when build GCC with --enable-checking=yes.  */
+/* { dg-final { scan-rtl-dump "sym_got" "final" } } */
+
+/* Check that PIC patterns have been grouped by correct group ID. */
+/* { dg-final { scan-assembler ".relax_hint \[1-9\]" } } */
diff --git a/gcc/testsuite/gcc.target/nds32/tls-le.c 
b/gcc/testsuite/gcc.target/nds32/tls-le.c
new file mode 100644
index 0000000..69a8058
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nds32/tls-le.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target *-*-linux* } } */
+/* { dg-options "-O2 -ftls-model=initial-exec -fdump-rtl-final" } */
+
+__thread int lala;
+__thread int baba;
+void foo ()
+{
+  lala++;
+  baba++;
+}
+
+/* Check that TLS LE pattern only generate one RTL pattern for sethi and ori
+   to pass verify_rtx_sharing when build GCC with --enable-checking=yes.  */
+/* { dg-final { scan-rtl-dump "tls_le" "final" } } */
+
+/* Check that TLS LE patterns have been grouped by correct group ID. */
+/* { dg-final { scan-assembler ".relax_hint \[1-9\]" } } */
-- 
1.8.3.1

Reply via email to