Commit 6b55f8c9 by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Add JLI support.

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
parent c921c45f
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
......
......@@ -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);
......@@ -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,
......
......@@ -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.
......
......@@ -401,6 +401,12 @@
(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)"))
......
......@@ -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
......@@ -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")])
......
......@@ -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. */
......
......@@ -1190,7 +1190,7 @@
(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")])
......
......@@ -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
......
......@@ -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
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.
......
/* { 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" } } */
/* { 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" } } */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment