[ARC] Add JLI support.
authorClaudiu Zissulescu <claziss@synopsys.com>
Fri, 26 Jan 2018 11:33:22 +0000 (12:33 +0100)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Fri, 26 Jan 2018 11:33:22 +0000 (12:33 +0100)
The ARCv2 ISA provides the JLI instruction, which is two-byte instructions
that can be used to reduce code size in an application. To make use of it,
we provide two new function attributes 'jli_always' and 'jli_fixed' which
will force the compiler to call the indicated function using a jli_s
instruction. The compiler also generates the entries in the JLI table for
the case when we use 'jli_always' attribute. In the case of 'jli_fixed'
the compiler assumes a fixed position of the function into JLI
table. Thus, the user needs to provide an assembly file with the JLI table
for the final link. This is usefully when we want to have a table in ROM
and a second table in the RAM memory.

The jli instruction usage can be also forced without the need to annotate
the source code via '-mjli-always' command.

gcc/
2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>
            John Eric Martin <John.Martin@emmicro-us.com>

        * config/arc/arc-protos.h: Add arc_is_jli_call_p proto.
        * config/arc/arc.c (_arc_jli_section): New struct.
        (arc_jli_section): New type.
        (rc_jli_sections): New static variable.
        (arc_handle_jli_attribute): New function.
        (arc_attribute_table): Add jli_always and jli_fixed attribute.
        (arc_file_end): New function.
        (TARGET_ASM_FILE_END): Define.
        (arc_print_operand): Reuse 'S' letter for JLI output instruction.
        (arc_add_jli_section): New function.
        (jli_call_scan): Likewise.
        (arc_reorg): Call jli_call_scan.
        (arc_output_addsi): Remove 'S' from printing asm operand.
        (arc_is_jli_call_p): New function.
        * config/arc/arc.md (movqi_insn): Remove 'S' from printing asm
        operand.
        (movhi_insn): Likewise.
        (movsi_insn): Likewise.
        (movsi_set_cc_insn): Likewise.
        (loadqi_update): Likewise.
        (load_zeroextendqisi_update): Likewise.
        (load_signextendqisi_update): Likewise.
        (loadhi_update): Likewise.
        (load_zeroextendhisi_update): Likewise.
        (load_signextendhisi_update): Likewise.
        (loadsi_update): Likewise.
        (loadsf_update): Likewise.
        (movsicc_insn): Likewise.
        (bset_insn): Likewise.
        (bxor_insn): Likewise.
        (bclr_insn): Likewise.
        (bmsk_insn): Likewise.
        (bicsi3_insn): Likewise.
        (cmpsi_cc_c_insn): Likewise.
        (movsi_ne): Likewise.
        (movsi_cond_exec): Likewise.
        (clrsbsi2): Likewise.
        (norm_f): Likewise.
        (normw): Likewise.
        (swap): Likewise.
        (divaw): Likewise.
        (flag): Likewise.
        (sr): Likewise.
        (kflag): Likewise.
        (ffs): Likewise.
        (ffs_f): Likewise.
        (fls): Likewise.
        (call_i): Remove 'S' asm letter, add jli instruction.
        (call_value_i): Likewise.
        * config/arc/arc.op (mjli-always): New option.
        * config/arc/constraints.md (Cji): New constraint.
        * config/arc/fpx.md (addsf3_fpx): Remove 'S' from printing asm
        operand.
        (subsf3_fpx): Likewise.
        (mulsf3_fpx): Likewise.
        * config/arc/simdext.md (vendrec_insn): Remove 'S' from printing
        asm operand.
        * doc/extend.texi (ARC): Document 'jli-always' and 'jli-fixed'
        function attrbutes.
        * doc/invoke.texi (ARC): Document mjli-always option.

gcc/testsuite
2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>

        * gcc.target/arc/jli-1.c: New file.
        * gcc.target/arc/jli-2.c: Likewise.

Co-Authored-By: John Eric Martin <John.Martin@emmicro-us.com>
From-SVN: r257081

15 files changed:
gcc/ChangeLog
gcc/config/arc/arc-protos.h
gcc/config/arc/arc.c
gcc/config/arc/arc.md
gcc/config/arc/arc.opt
gcc/config/arc/constraints.md
gcc/config/arc/elf.h
gcc/config/arc/fpx.md
gcc/config/arc/linux.h
gcc/config/arc/simdext.md
gcc/doc/extend.texi
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arc/jli-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arc/jli-2.c [new file with mode: 0644]

index 6a02d9607a76e7f0f5fa4b2d5165deed121c7bdd..61a85f8c9d716dcf0a7db65c92a9257395790fa1 100644 (file)
@@ -1,3 +1,67 @@
+2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>
+           John Eric Martin <John.Martin@emmicro-us.com>
+
+       * config/arc/arc-protos.h: Add arc_is_jli_call_p proto.
+       * config/arc/arc.c (_arc_jli_section): New struct.
+       (arc_jli_section): New type.
+       (rc_jli_sections): New static variable.
+       (arc_handle_jli_attribute): New function.
+       (arc_attribute_table): Add jli_always and jli_fixed attribute.
+       (arc_file_end): New function.
+       (TARGET_ASM_FILE_END): Define.
+       (arc_print_operand): Reuse 'S' letter for JLI output instruction.
+       (arc_add_jli_section): New function.
+       (jli_call_scan): Likewise.
+       (arc_reorg): Call jli_call_scan.
+       (arc_output_addsi): Remove 'S' from printing asm operand.
+       (arc_is_jli_call_p): New function.
+       * config/arc/arc.md (movqi_insn): Remove 'S' from printing asm
+       operand.
+       (movhi_insn): Likewise.
+       (movsi_insn): Likewise.
+       (movsi_set_cc_insn): Likewise.
+       (loadqi_update): Likewise.
+       (load_zeroextendqisi_update): Likewise.
+       (load_signextendqisi_update): Likewise.
+       (loadhi_update): Likewise.
+       (load_zeroextendhisi_update): Likewise.
+       (load_signextendhisi_update): Likewise.
+       (loadsi_update): Likewise.
+       (loadsf_update): Likewise.
+       (movsicc_insn): Likewise.
+       (bset_insn): Likewise.
+       (bxor_insn): Likewise.
+       (bclr_insn): Likewise.
+       (bmsk_insn): Likewise.
+       (bicsi3_insn): Likewise.
+       (cmpsi_cc_c_insn): Likewise.
+       (movsi_ne): Likewise.
+       (movsi_cond_exec): Likewise.
+       (clrsbsi2): Likewise.
+       (norm_f): Likewise.
+       (normw): Likewise.
+       (swap): Likewise.
+       (divaw): Likewise.
+       (flag): Likewise.
+       (sr): Likewise.
+       (kflag): Likewise.
+       (ffs): Likewise.
+       (ffs_f): Likewise.
+       (fls): Likewise.
+       (call_i): Remove 'S' asm letter, add jli instruction.
+       (call_value_i): Likewise.
+       * config/arc/arc.op (mjli-always): New option.
+       * config/arc/constraints.md (Cji): New constraint.
+       * config/arc/fpx.md (addsf3_fpx): Remove 'S' from printing asm
+       operand.
+       (subsf3_fpx): Likewise.
+       (mulsf3_fpx): Likewise.
+       * config/arc/simdext.md (vendrec_insn): Remove 'S' from printing
+       asm operand.
+       * doc/extend.texi (ARC): Document 'jli-always' and 'jli-fixed'
+       function attrbutes.
+       * doc/invoke.texi (ARC): Document mjli-always option.
+
 2018-01-26  Sebastian Perta  <sebastian.perta@renesas.com>
 
        * config/rl78/rl78.c: if operand 2 is const avoid addition with 0
index d4315b3802f53af1aff40151b6471f0be23bb6ca..7274fe0e4a0b2942d7d554b06ff20e316a3102a1 100644 (file)
@@ -116,3 +116,5 @@ extern void arc_secondary_reload_conv (rtx, rtx, rtx, bool);
 extern void arc_cpu_cpp_builtins (cpp_reader *);
 extern bool arc_store_addr_hazard_p (rtx_insn *, rtx_insn *);
 extern rtx arc_eh_return_address_location (void);
+extern bool arc_is_jli_call_p (rtx);
+extern void arc_file_end (void);
index c7947912bdeb6c8d6ceddc416f22997c7b992315..78cf323a0367273931a1b79b0f8b24e0ba1b8120 100644 (file)
@@ -73,6 +73,14 @@ along with GCC; see the file COPYING3.  If not see
 static char arc_cpu_name[10] = "";
 static const char *arc_cpu_string = arc_cpu_name;
 
+typedef struct GTY (()) _arc_jli_section
+{
+  const char *name;
+  struct _arc_jli_section *next;
+} arc_jli_section;
+
+static arc_jli_section *arc_jli_sections = NULL;
+
 /* Track which regs are set fixed/call saved/call used from commnad line.  */
 HARD_REG_SET overrideregs;
 
@@ -217,6 +225,8 @@ static int get_arc_condition_code (rtx);
 
 static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
 static tree arc_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
+static tree arc_handle_jli_attribute (tree *, tree, tree, int, bool *);
+
 
 /* Initialized arc_attribute_table to NULL since arc doesnot have any
    machine specific supported attributes.  */
@@ -240,6 +250,13 @@ const struct attribute_spec arc_attribute_table[] =
      by the compiler.  */
   { "naked", 0, 0, true, false, false,  false, arc_handle_fndecl_attribute,
     NULL },
+  /* Functions calls made using jli instruction.  The pointer in JLI
+     table is found latter.  */
+  { "jli_always",    0, 0, false, true,  true,  NULL, NULL },
+  /* Functions calls made using jli instruction.  The pointer in JLI
+     table is given as input parameter.  */
+  { "jli_fixed",    1, 1, false, true,  true,  arc_handle_jli_attribute,
+    NULL },
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 static int arc_comp_type_attributes (const_tree, const_tree);
@@ -3754,7 +3771,7 @@ static int output_scaled = 0;
     'd'
     'D'
     'R': Second word
-    'S'
+    'S': JLI instruction
     'B': Branch comparison operand - suppress sda reference
     'H': Most significant word
     'L': Least significant word
@@ -3970,8 +3987,27 @@ arc_print_operand (FILE *file, rtx x, int code)
        output_operand_lossage ("invalid operand to %%R code");
       return;
     case 'S' :
-       /* FIXME: remove %S option.  */
-       break;
+      if (GET_CODE (x) == SYMBOL_REF
+         && arc_is_jli_call_p (x))
+       {
+         if (SYMBOL_REF_DECL (x))
+           {
+             tree attrs = (TREE_TYPE (SYMBOL_REF_DECL (x)) != error_mark_node
+                           ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x)))
+                           : NULL_TREE);
+             if (lookup_attribute ("jli_fixed", attrs))
+               {
+                 fprintf (file, "%ld\t; @",
+                          TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs))));
+                 assemble_name (file, XSTR (x, 0));
+                 return;
+               }
+           }
+         fprintf (file, "@__jli.");
+         assemble_name (file, XSTR (x, 0));
+         return;
+       }
+      break;
     case 'B' /* Branch or other LIMM ref - must not use sda references.  */ :
       if (CONSTANT_P (x))
        {
@@ -5084,6 +5120,36 @@ static void arc_file_start (void)
   fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
 }
 
+/* Implement `TARGET_ASM_FILE_END'.  */
+/* Outputs to the stdio stream FILE jli related text.  */
+
+void arc_file_end (void)
+{
+  arc_jli_section *sec = arc_jli_sections;
+
+  while (sec != NULL)
+    {
+      fprintf (asm_out_file, "\n");
+      fprintf (asm_out_file, "# JLI entry for function ");
+      assemble_name (asm_out_file, sec->name);
+      fprintf (asm_out_file, "\n\t.section .jlitab, \"axG\", @progbits, "
+              ".jlitab.");
+      assemble_name (asm_out_file, sec->name);
+      fprintf (asm_out_file,", comdat\n");
+
+      fprintf (asm_out_file, "\t.align\t4\n");
+      fprintf (asm_out_file, "__jli.");
+      assemble_name (asm_out_file, sec->name);
+      fprintf (asm_out_file, ":\n\t.weak __jli.");
+      assemble_name (asm_out_file, sec->name);
+      fprintf (asm_out_file, "\n\tb\t@");
+      assemble_name (asm_out_file, sec->name);
+      fprintf (asm_out_file, "\n");
+      sec = sec->next;
+    }
+  file_end_indicate_exec_stack ();
+}
+
 /* Cost functions.  */
 
 /* Compute a (partial) cost for rtx X.  Return true if the complete
@@ -6866,13 +6932,25 @@ check_if_valid_sleep_operand (rtx *operands, int opno)
 /* Return true if it is ok to make a tail-call to DECL.  */
 
 static bool
-arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+arc_function_ok_for_sibcall (tree decl,
                             tree exp ATTRIBUTE_UNUSED)
 {
+  tree attrs = NULL_TREE;
+
   /* Never tailcall from an ISR routine - it needs a special exit sequence.  */
   if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
     return false;
 
+  if (decl)
+    {
+      attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+
+      if (lookup_attribute ("jli_always", attrs))
+       return false;
+      if (lookup_attribute ("jli_fixed", attrs))
+       return false;
+    }
+
   /* Everything else is ok.  */
   return true;
 }
@@ -7577,6 +7655,73 @@ arc_reorg_loops (void)
   reorg_loops (true, &arc_doloop_hooks);
 }
 
+/* Add the given function declaration to emit code in JLI section.  */
+
+static void
+arc_add_jli_section (rtx pat)
+{
+  const char *name;
+  tree attrs;
+  arc_jli_section *sec = arc_jli_sections, *new_section;
+  tree decl = SYMBOL_REF_DECL (pat);
+
+  if (!pat)
+    return;
+
+  if (decl)
+    {
+      /* For fixed locations do not generate the jli table entry.  It
+        should be provided by the user as an asm file.  */
+      attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+      if (lookup_attribute ("jli_fixed", attrs))
+       return;
+    }
+
+  name = XSTR (pat, 0);
+
+  /* Don't insert the same symbol twice.  */
+  while (sec != NULL)
+    {
+      if(strcmp (name, sec->name) == 0)
+       return;
+      sec = sec->next;
+    }
+
+  /* New name, insert it.  */
+  new_section = (arc_jli_section *) xmalloc (sizeof (arc_jli_section));
+  gcc_assert (new_section != NULL);
+  new_section->name = name;
+  new_section->next = arc_jli_sections;
+  arc_jli_sections = new_section;
+}
+
+/* Scan all calls and add symbols to be emitted in the jli section if
+   needed.  */
+
+static void
+jli_call_scan (void)
+{
+  rtx_insn *insn;
+
+  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+    {
+      if (!CALL_P (insn))
+       continue;
+
+      rtx pat = PATTERN (insn);
+      if (GET_CODE (pat) == COND_EXEC)
+       pat = COND_EXEC_CODE (pat);
+      pat =  XVECEXP (pat, 0, 0);
+      if (GET_CODE (pat) == SET)
+       pat = SET_SRC (pat);
+
+      pat = XEXP (XEXP (pat, 0), 0);
+      if (GET_CODE (pat) == SYMBOL_REF
+         && arc_is_jli_call_p (pat))
+       arc_add_jli_section (pat);
+    }
+}
+
 static int arc_reorg_in_progress = 0;
 
 /* ARC's machince specific reorg function.  */
@@ -7601,6 +7746,7 @@ arc_reorg (void)
   arc_reorg_loops ();
 
   workaround_arc_anomaly ();
+  jli_call_scan ();
 
 /* FIXME: should anticipate ccfsm action, generate special patterns for
    to-be-deleted branches that have no delay slot and have at least the
@@ -8279,11 +8425,11 @@ arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
   /* Try to emit a 16 bit opcode with long immediate.  */
   ret = 6;
   if (short_p && match)
-    ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
+    ADDSI_OUTPUT1 ("add%? %0,%1,%2");
 
   /* We have to use a 32 bit opcode, and with a long immediate.  */
   ret = 8;
-  ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
+  ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%2");
 }
 
 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
@@ -10822,6 +10968,68 @@ arc_builtin_setjmp_frame_value (void)
   return gen_raw_REG (Pmode, FRAME_POINTER_REGNUM);
 }
 
+/* Return nonzero if a jli call should be generated for a call from
+   the current function to DECL.  */
+
+bool
+arc_is_jli_call_p (rtx pat)
+{
+  tree attrs;
+  tree decl = SYMBOL_REF_DECL (pat);
+
+  /* If it is not a well defined public function then return false.  */
+  if (!decl || !SYMBOL_REF_FUNCTION_P (pat) || !TREE_PUBLIC (decl))
+    return false;
+
+  attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+  if (lookup_attribute ("jli_always", attrs))
+    return true;
+
+  if (lookup_attribute ("jli_fixed", attrs))
+    return true;
+
+  return TARGET_JLI_ALWAYS;
+}
+
+/* Handle and "jli" attribute; arguments as in struct
+   attribute_spec.handler.  */
+
+static tree
+arc_handle_jli_attribute (tree *node ATTRIBUTE_UNUSED,
+                         tree name, tree args, int,
+                         bool *no_add_attrs)
+{
+  if (!TARGET_V2)
+    {
+      warning (OPT_Wattributes,
+              "%qE attribute only valid for ARCv2 architecture",
+              name);
+      *no_add_attrs = true;
+    }
+
+  if (args == NULL_TREE)
+    {
+      warning (OPT_Wattributes,
+              "argument of %qE attribute is missing",
+              name);
+      *no_add_attrs = true;
+    }
+  else
+    {
+      if (TREE_CODE (TREE_VALUE (args)) == NON_LVALUE_EXPR)
+       TREE_VALUE (args) = TREE_OPERAND (TREE_VALUE (args), 0);
+      tree arg = TREE_VALUE (args);
+      if (TREE_CODE (arg) != INTEGER_CST)
+       {
+         warning (0, "%qE attribute allows only an integer constant argument",
+                  name);
+         *no_add_attrs = true;
+       }
+      /* FIXME! add range check.  TREE_INT_CST_LOW (arg) */
+    }
+   return NULL_TREE;
+}
+
 /* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P.  We don't want to use
    anchors for small data: the GP register acts as an anchor in that
    case.  We also don't want to use them for PC-relative accesses,
index 10b027a89afc875c55d64694e09e40e3e61b590a..233e6f5379e61be1d5e57fdb6b702c27262066c5 100644 (file)
    mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1
-   mov%? %0,%S1
+   mov%? %0,%1
    ldb%? %0,%1%&
    stb%? %1,%0%&
    ldb%? %0,%1%&
    mov%? %0,%1
    mov%? %0,%1
    mov%? %0,%1
-   mov%? %0,%S1%&
-   mov%? %0,%S1
-   mov%? %0,%S1
+   mov%? %0,%1%&
+   mov%? %0,%1
+   mov%? %0,%1
    ld%_%? %0,%1%&
    st%_%? %1,%0%&
    xld%_%U1 %0,%1
    xst%_%U0 %1,%0
    st%_%U0%V0 %1,%0
    st%_%U0%V0 %1,%0
-   st%_%U0%V0 %S1,%0
-   st%_%U0%V0 %S1,%0"
+   st%_%U0%V0 %1,%0
+   st%_%U0%V0 %1,%0"
   [(set_attr "type" "move,move,move,move,move,move,move,move,move,move,move,load,store,load,load,store,store,store,store,store")
    (set_attr "iscompact" "maybe,maybe,maybe,true,true,false,false,false,maybe_limm,maybe_limm,false,true,true,false,false,false,false,false,false,false")
    (set_attr "predicable" "yes,no,yes,no,no,yes,no,yes,yes,yes,yes,no,no,no,no,no,no,no,no,no")
    movh.cl %0,%L1>>16   ;9
    * return INTVAL (operands[1]) & 0xffffff ? \"movbi.cl %0,%1 >> %p1,%p1,8;10\" : \"movbi.cl %0,%L1 >> 24,24,8;10\";
    mov%? %0,%1         ;11
-   add %0,%S1          ;12
+   add %0,%          ;12
    add %0,pcl,%1@pcl    ;13
    mov%? %0,%1         ;14
    mov%? %0,%1         ;15
    (set (match_operand:SI 0 "register_operand" "=w,w,w")
        (match_dup 1))]
   ""
-  "mov%?.f %0,%S1"
+  "mov%?.f %0,%1"
   ; splitting to 'tst' allows short insns and combination into brcc.
   "reload_completed && operands_match_p (operands[0], operands[1])"
   [(set (match_dup 2) (match_dup 3))]
    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ldb.a%V4 %3,[%0,%S2]"
+  "ldb.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ldb.a%V4 %3,[%0,%S2]"
+  "ldb.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ldb.x.a%V4 %3,[%0,%S2]"
+  "ldb.x.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ld%_.a%V4 %3,[%0,%S2]"
+  "ld%_.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=r,r")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ld%_.a%V4 %3,[%0,%S2]"
+  "ld%_.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ld%_.x.a%V4 %3,[%0,%S2]"
+  "ld%_.x.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ld.a%V4 %3,[%0,%S2]"
+  "ld.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
    (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
        (plus:SI (match_dup 1) (match_dup 2)))]
   ""
-  "ld.a%V4 %3,[%0,%S2]"
+  "ld.a%V4 %3,[%0,%2]"
   [(set_attr "type" "load,load")
    (set_attr "length" "4,8")])
 
       && rtx_equal_p (operands[1], constm1_rtx)
       && GET_CODE (operands[3]) == LTU)
     return "sbc.cs %0,%0,%0";
-  return "mov.%d3 %0,%S1";
+  return "mov.%d3 %0,%1";
 }
   [(set_attr "type" "cmove,cmove")
    (set_attr "length" "4,8")])
   "@
      bset%? %0,%1,%2 ;;peep2, constr 1
      bset %0,%1,%2 ;;peep2, constr 2
-     bset %0,%S1,%2 ;;peep2, constr 3"
+     bset %0,%1,%2 ;;peep2, constr 3"
   [(set_attr "length" "4,4,8")
    (set_attr "predicable" "yes,no,no")
    (set_attr "cond" "canuse,nocond,nocond")]
   "@
      bxor%? %0,%1,%2
      bxor %0,%1,%2
-     bxor %0,%S1,%2"
+     bxor %0,%1,%2"
   [(set_attr "length" "4,4,8")
    (set_attr "predicable" "yes,no,no")
    (set_attr "cond" "canuse,nocond,nocond")]
   "@
      bclr%? %0,%1,%2
      bclr %0,%1,%2
-     bclr %0,%S1,%2"
+     bclr %0,%1,%2"
   [(set_attr "length" "4,4,8")
    (set_attr "predicable" "yes,no,no")
    (set_attr "cond" "canuse,nocond,nocond")]
                         (const_int -1))))]
   ""
   "@
-     bmsk%? %0,%S1,%2
+     bmsk%? %0,%1,%2
      bmsk %0,%1,%2
-     bmsk %0,%S1,%2"
+     bmsk %0,%1,%2"
   [(set_attr "length" "4,4,8")
    (set_attr "predicable" "yes,no,no")
    (set_attr "cond" "canuse,nocond,nocond")]
    bic%? %0, %2, %1%& ;;constraint 0
    bic%? %0,%2,%1  ;;constraint 1
    bic %0,%2,%1    ;;constraint 2, FIXME: will it ever get generated ???
-   bic%? %0,%2,%S1 ;;constraint 3, FIXME: will it ever get generated ???
+   bic%? %0,%2,% ;;constraint 3, FIXME: will it ever get generated ???
    bic %0,%2,%1    ;;constraint 4
-   bic %0,%2,%S1   ;;constraint 5, FIXME: will it ever get generated ???
-   bic %0,%S2,%1   ;;constraint 6"
+   bic %0,%2,%   ;;constraint 5, FIXME: will it ever get generated ???
+   bic %0,%2,%1    ;;constraint 6"
   [(set_attr "length" "*,4,4,8,4,8,8")
   (set_attr "iscompact" "maybe, false, false, false, false, false, false")
   (set_attr "predicable" "no,yes,no,yes,no,no,no")
        (compare:CC_C (match_operand:SI 0 "register_operand"  "Rcqq,Rcqq,  h, c,Rcqq,  c")
                      (match_operand:SI 1 "nonmemory_operand"   "cO,  hO,Cm1,cI, Cal,Cal")))]
   ""
-  "cmp%? %0,%S1%&"
+  "cmp%? %0,%1%&"
   [(set_attr "type" "compare")
    (set_attr "iscompact" "true,true,true,false,true_limm,false")
    (set_attr "cond" "set")
        * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
        * current_insn_predicate = 0; return \"mov%?.ne %0,%1\";
        mov.ne %0,%1
-       mov.ne %0,%S1"
+       mov.ne %0,%1"
   [(set_attr "type" "cmove")
    (set_attr "iscompact" "true,true,true_limm,false,false")
    (set_attr "length" "2,2,6,4,8")
      (set (match_operand:SI 0 "dest_reg_operand" "=w,w")
          (match_operand:SI 1 "nonmemory_operand" "LRac,?Cal")))]
   ""
-  "mov.%d3 %0,%S1"
+  "mov.%d3 %0,%1"
   [(set_attr "type" "cmove")
    (set_attr "length" "4,8")])
 
   }
 ")
 
-
 ; Rcq, which is used in alternative 0, checks for conditional execution.
 ; At instruction output time, if it doesn't match and we end up with
 ; alternative 1 ("q"), that means that we can't use the short form.
 (define_insn "*call_i"
   [(call (mem:SI (match_operand:SI 0
-                 "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+                 "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
         (match_operand 1 "" ""))
    (clobber (reg:SI 31))]
   ""
    jl%!%* [%0]%&
    jl%!%* [%0]%&
    jl%!%* [%0]
+   jli_s %S0
    bl%!%* %P0
    bl%!%* %P0
-   jl%!%* %S0
-   jl%* %S0
-   jl%! %S0"
-  [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
-   (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
-   (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
-   (set_attr "length" "*,*,4,4,4,4,4,8")])
+   jl%!%* %0
+   jl%* %0
+   jl%! %0"
+  [(set_attr "type" "call,call,call,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
+   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*")
+   (set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes")
+   (set_attr "length" "*,*,4,2,4,4,4,4,8")])
 
 (define_expand "call_value"
   ;; operand 2 is stack_size_rtx
       XEXP (operands[1], 0) = force_reg (Pmode, callee);
   }")
 
-
 ; Rcq, which is used in alternative 0, checks for conditional execution.
 ; At instruction output time, if it doesn't match and we end up with
 ; alternative 1 ("q"), that means that we can't use the short form.
 (define_insn "*call_value_i"
-  [(set (match_operand 0 "dest_reg_operand"  "=Rcq,q,w,  w,  w,w,w,  w")
+  [(set (match_operand 0 "dest_reg_operand"  "=Rcq,q,w,  w,  w,  w,w,w,  w")
        (call (mem:SI (match_operand:SI 1
-                      "call_address_operand" "Rcq,q,c,Cbp,Cbr,L,I,Cal"))
+                      "call_address_operand" "Rcq,q,c,Cji,Cbp,Cbr,L,I,Cal"))
              (match_operand 2 "" "")))
    (clobber (reg:SI 31))]
   ""
    jl%!%* [%1]%&
    jl%!%* [%1]%&
    jl%!%* [%1]
+   jli_s %S1
    bl%!%* %P1;1
    bl%!%* %P1;1
-   jl%!%* %S1
-   jl%* %S1
-   jl%! %S1"
-  [(set_attr "type" "call,call,call,call,call,call,call,call_no_delay_slot")
-   (set_attr "iscompact" "maybe,false,*,*,*,*,*,*")
-   (set_attr "predicable" "no,no,yes,yes,no,yes,no,yes")
-   (set_attr "length" "*,*,4,4,4,4,4,8")])
+   jl%!%* %1
+   jl%* %1
+   jl%! %1"
+  [(set_attr "type" "call,call,call,call_no_delay_slot,call,call,call,call,call_no_delay_slot")
+   (set_attr "iscompact" "maybe,false,*,true,*,*,*,*,*")
+   (set_attr "predicable" "no,no,yes,no,yes,no,yes,no,yes")
+   (set_attr "length" "*,*,4,2,4,4,4,4,8")])
 
 ; There is a bl_s instruction (16 bit opcode branch-and-link), but we can't
 ; use it for lack of inter-procedural branch shortening.
   "TARGET_NORM"
   "@
    norm \t%0, %1
-   norm \t%0, %S1"
+   norm \t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
   "TARGET_NORM"
   "@
    norm.f\t%0, %1
-   norm.f\t%0, %S1"
+   norm.f\t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
   "TARGET_NORM"
   "@
    norm%_ \t%0, %1
-   norm%_ \t%0, %S1"
+   norm%_ \t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
   "TARGET_SWAP"
   "@
    swap \t%0, %1
-   swap \t%0, %S1
+   swap \t%0, %1
    swap \t%0, %1"
   [(set_attr "length" "4,8,4")
    (set_attr "type" "two_cycle_core,two_cycle_core,two_cycle_core")])
   "TARGET_ARC700 || TARGET_EA_SET"
   "@
    divaw \t%0, %1, %2
-   divaw \t%0, %S1, %2
-   divaw \t%0, %1, %S2"
+   divaw \t%0, %1, %2
+   divaw \t%0, %1, %2"
   [(set_attr "length" "4,8,8")
    (set_attr "type" "divaw,divaw,divaw")])
 
   "@
     flag%? %0
     flag %0
-    flag%? %S0"
+    flag%? %0"
   [(set_attr "length" "4,4,8")
    (set_attr "type" "misc,misc,misc")
    (set_attr "predicable" "yes,no,yes")
                     (match_operand:SI 1 "general_operand" "Ir,I,HCal,r")]
                   VUNSPEC_ARC_SR)]
   ""
-  "sr\t%S0, [%1]"
+  "sr\t%0, [%1]"
   [(set_attr "length" "8,4,8,4")
    (set_attr "type" "sr,sr,sr,sr")])
 
 ;; ??? Should this use arc_output_libcall and set is_sfunc?
 (define_insn "*millicode_thunk_st"
   [(match_parallel 0 "millicode_store_operation"
-     [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
+                  [(set (mem:SI (reg:SI SP_REG)) (reg:SI 13))])]
   ""
 {
   output_asm_insn ("bl%* __st_r13_to_%0",
 
 (define_insn "*millicode_thunk_ld"
   [(match_parallel 0 "millicode_load_clob_operation"
-     [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+                  [(set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
   ""
 {
   output_asm_insn ("bl%* __ld_r13_to_%0",
 ; the sibthunk restores blink, so we use the return rtx.
 (define_insn "*millicode_sibthunk_ld"
   [(match_parallel 0 "millicode_load_operation"
-     [(return)
-      (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
-      (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
+                  [(return)
+                   (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (reg:SI 12)))
+                   (set (reg:SI 13) (mem:SI (reg:SI SP_REG)))])]
   ""
 {
   output_asm_insn ("b%* __ld_r13_to_%0_ret",
   "@
     kflag%? %0
     kflag %0
-    kflag%? %S0"
+    kflag%? %0"
   [(set_attr "length" "4,4,8")
    (set_attr "type" "misc,misc,misc")
    (set_attr "predicable" "yes,no,yes")
   "TARGET_NORM && TARGET_V2"
   "@
    ffs \t%0, %1
-   ffs \t%0, %S1"
+   ffs \t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
   "TARGET_NORM && TARGET_V2"
   "@
    ffs.f\t%0, %1
-   ffs.f\t%0, %S1"
+   ffs.f\t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
   "TARGET_NORM && TARGET_V2"
   "@
    fls \t%0, %1
-   fls \t%0, %S1"
+   fls \t%0, %1"
   [(set_attr "length" "4,8")
    (set_attr "type" "two_cycle_core,two_cycle_core")])
 
index 593bd2dc30a32e267fe6c60130f954c40c4ce6ad..5f10c0ee0051715b70058da291128ccfafd97989 100644 (file)
@@ -53,6 +53,10 @@ mARC700
 Target Report
 Same as -mA7.
 
+mjli-always
+Target Report Mask(JLI_ALWAYS)
+Force all calls to be made via a jli instruction.
+
 mmpy-option=
 Target RejectNegative Joined Enum(arc_mpy) Var(arc_mpy_option) Init(DEFAULT_arc_mpy_option)
 -mmpy-option=MPY Compile ARCv2 code with a multiplier design option.
index 7c34ffd6779f6b1f818c37429600430b7b27a1ca..565d8608e85099fdc3ef43f9d12d5381217f095d 100644 (file)
            (match_test "arc_is_shortcall_p (op)"))
        (match_code "label_ref")))
 
+(define_constraint "Cji"
+  "JLI call"
+  (and (match_code "symbol_ref")
+       (match_test "TARGET_CODE_DENSITY")
+       (match_test "arc_is_jli_call_p (op)")))
+
 (define_constraint "Cpc"
   "pc-relative constant"
   (match_test "arc_legitimate_pic_addr_p (op)"))
index 5abafcab4e2dab0e21f6770a00ff8aad20cec234..3bb9cb012ae5947afcfafff75898290ccdb5efe0 100644 (file)
@@ -66,3 +66,6 @@ along with GCC; see the file COPYING3.  If not see
 /* Pre/post modify with register displacement are default.  */
 #undef TARGET_AUTO_MODIFY_REG_DEFAULT
 #define TARGET_AUTO_MODIFY_REG_DEFAULT 1
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END arc_file_end
index db7b64264833eb6d312af1af96aeef97fc0fbea8..8f65df1ba0f04d29165408e7d4b0b16491a22648 100644 (file)
@@ -59,9 +59,9 @@
   "@
    fadd %0,%1,%2
    fadd %0,%1,%2
-   fadd   %0,%S1,%2
-   fadd   %0,%1,%S2
-   fadd%? %0,%1,%S2"
+   fadd   %0,%1,%2
+   fadd   %0,%1,%2
+   fadd%? %0,%1,%2"
   [(set_attr "type" "spfp")
   (set_attr "length" "4,4,8,8,8")])
 
@@ -74,9 +74,9 @@
   "@
    fsub %0,%1,%2
    fsub %0,%1,%2
-   fsub   %0,%S1,%2
-   fsub   %0,%1,%S2
-   fsub%? %0,%1,%S2"
+   fsub   %0,%1,%2
+   fsub   %0,%1,%2
+   fsub%? %0,%1,%2"
   [(set_attr "type" "spfp")
   (set_attr "length" "4,4,8,8,8")])
 
@@ -89,9 +89,9 @@
   "@
    fmul %0,%1,%2
    fmul %0,%1,%2
-   fmul   %0,%S1,%2
-   fmul   %0,%1,%S2
-   fmul%? %0,%1,%S2"
+   fmul   %0,%1,%2
+   fmul   %0,%1,%2
+   fmul%? %0,%1,%2"
   [(set_attr "type" "spfp")
   (set_attr "length" "4,4,8,8,8")])
 
index 633ae9086f5142235be9984ef801f335b721ce7a..385083331d5469bfd36a33c797fc6577507734a3 100644 (file)
@@ -61,6 +61,7 @@ along with GCC; see the file COPYING3.  If not see
    %{shared:-lc} \
    %{!shared:%{profile:-lc_p}%{!profile:-lc}}"
 
+#undef TARGET_ASM_FILE_END
 #define TARGET_ASM_FILE_END file_end_indicate_exec_stack
 
 /* No SDATA default for linux.  */
index e742638b3434e7cedef0d8add7c3a9fddebce55a..8885a6ae47d923d991158108cde5c7ac04b0d545 100644 (file)
 (define_insn "vendrec_insn"
   [(unspec_volatile [(match_operand:SI 0 "nonmemory_operand"  "r")] UNSPEC_ARC_SIMD_VENDREC)]
   "TARGET_SIMD_SET"
-  "vendrec %S0"
+  "vendrec %0"
   [(set_attr "type" "simd_vcontrol")
    (set_attr "length" "4")
    (set_attr "cond" "nocond")])
index dce808f1eab1ff734fb5acf97a2d8a6ea270a788..478894be0ea80f2e3b3275807bac3fcffaeee0b4 100644 (file)
@@ -3762,6 +3762,19 @@ the call site.  A function marked with the @code{short_call}
 attribute will always be close enough to be called with a conditional
 branch-and-link instruction, which has a 21-bit offset from
 the call site.
+
+@item jli_always
+@cindex @code{jli_always} function attribute, ARC
+Forces a particular function to be called using @code{jli}
+instruction.  The @code{jli} instruction makes use of a table stored
+into @code{.jlitab} section, which holds the location of the functions
+which are addressed using this instruction.
+
+@item jli_fixed
+@cindex @code{jli_fixed} function attribute, ARC
+Identical like the above one, but the location of the function in the
+@code{jli} table is known and given as an attribute parameter.
+
 @end table
 
 @node ARM Function Attributes
index 4e21aa35da3aad4d8c46632f2c0d32bd2f680da5..328ee849b0beb00d3eaac9d639eea6cc97bc53fa 100644 (file)
@@ -611,7 +611,7 @@ Objective-C and Objective-C++ Dialects}.
 -msplit-vecmove-early  -m1reg-@var{reg}}
 
 @emph{ARC Options}
-@gccoptlist{-mbarrel-shifter @gol
+@gccoptlist{-mbarrel-shifter -mjli-always @gol
 -mcpu=@var{cpu}  -mA6  -mARC600  -mA7  -mARC700 @gol
 -mdpfp  -mdpfp-compact  -mdpfp-fast  -mno-dpfp-lrsr @gol
 -mea  -mno-mpy  -mmul32x16  -mmul64  -matomic @gol
@@ -14874,6 +14874,11 @@ is being compiled:
 Generate instructions supported by barrel shifter.  This is the default
 unless @option{-mcpu=ARC601} or @samp{-mcpu=ARCEM} is in effect.
 
+@item -mjli-always
+@opindex mjli-alawys
+Force to call a function using jli_s instruction.  This option is
+valid only for ARCv2 architecture.
+
 @item -mcpu=@var{cpu}
 @opindex mcpu
 Set architecture type, register usage, and instruction scheduling
index 2402caab4d78520ab6cc41a4b8a1c5a6fab5721d..4e02b1e6c6488237379fec14e20a307f906bedb0 100644 (file)
@@ -1,3 +1,8 @@
+2018-01-26  Claudiu Zissulescu  <claziss@synopsys.com>
+
+       * gcc.target/arc/jli-1.c: New file.
+       * gcc.target/arc/jli-2.c: Likewise.
+
 2018-01-26  Szabolcs Nagy  <szabolcs.nagy@arm.com>
 
        * gcc.target/aarch64/sve/peel_ind_1.c: Match (adrp|adr) in scan-assembler.
diff --git a/gcc/testsuite/gcc.target/arc/jli-1.c b/gcc/testsuite/gcc.target/arc/jli-1.c
new file mode 100644 (file)
index 0000000..f7259b3
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "jli only available for ARCv2" { arc700 || arc6xx } } */
+/* { dg-options "-O0 -mcode-density" } */
+
+int func(int i) __attribute__((jli_always));
+
+int func(int i)
+{
+  return i*i;
+}
+
+int main()
+{
+  return func(100);
+}
+
+/* { dg-final { scan-assembler "jli_s @__jli.func" } } */
+/* { dg-final { scan-assembler ".weak __jli.func" } } */
+/* { dg-final { scan-assembler "b\\\s+@func" } } */
diff --git a/gcc/testsuite/gcc.target/arc/jli-2.c b/gcc/testsuite/gcc.target/arc/jli-2.c
new file mode 100644 (file)
index 0000000..96a35a4
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-skip-if "jli only available for ARCv2" { arc700 || arc6xx } } */
+/* { dg-options "-O0 -mcode-density" } */
+
+int func(int i) __attribute__((jli_fixed(2)));
+
+int func(int i)
+{
+  return i*i;
+}
+
+int main()
+{
+  return func(100);
+}
+
+/* { dg-final { scan-assembler "jli_s 2" } } */
+/* { dg-final { scan-assembler-not ".weak __jli.func" } } */
+/* { dg-final { scan-assembler-not "b\\\s+@func" } } */