From: Claudiu Zissulescu Date: Fri, 26 Jan 2018 11:33:22 +0000 (+0100) Subject: [ARC] Add JLI support. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6b55f8c92b1ea138ac851389c456820fde8cf026;p=gcc.git [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 John Eric Martin * 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 * gcc.target/arc/jli-1.c: New file. * gcc.target/arc/jli-2.c: Likewise. Co-Authored-By: John Eric Martin From-SVN: r257081 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6a02d9607a7..61a85f8c9d7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,67 @@ +2018-01-26 Claudiu Zissulescu + John Eric Martin + + * 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 * config/rl78/rl78.c: if operand 2 is const avoid addition with 0 diff --git a/gcc/config/arc/arc-protos.h b/gcc/config/arc/arc-protos.h index d4315b3802f..7274fe0e4a0 100644 --- a/gcc/config/arc/arc-protos.h +++ b/gcc/config/arc/arc-protos.h @@ -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); diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index c7947912bde..78cf323a036 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -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, diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md index 10b027a89af..233e6f5379e 100644 --- a/gcc/config/arc/arc.md +++ b/gcc/config/arc/arc.md @@ -641,7 +641,7 @@ mov%? %0,%1 mov%? %0,%1 mov%? %0,%1 - mov%? %0,%S1 + mov%? %0,%1 ldb%? %0,%1%& stb%? %1,%0%& ldb%? %0,%1%& @@ -682,9 +682,9 @@ 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 @@ -692,8 +692,8 @@ 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") @@ -738,7 +738,7 @@ 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,%1 ;12 add %0,pcl,%1@pcl ;13 mov%? %0,%1 ;14 mov%? %0,%1 ;15 @@ -799,7 +799,7 @@ (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))] @@ -1287,7 +1287,7 @@ (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")]) @@ -1299,7 +1299,7 @@ (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")]) @@ -1311,7 +1311,7 @@ (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")]) @@ -1337,7 +1337,7 @@ (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")]) @@ -1349,7 +1349,7 @@ (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")]) @@ -1362,7 +1362,7 @@ (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")]) @@ -1387,7 +1387,7 @@ (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")]) @@ -1411,7 +1411,7 @@ (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")]) @@ -1479,7 +1479,7 @@ && 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")]) @@ -3144,7 +3144,7 @@ "@ 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")] @@ -3160,7 +3160,7 @@ "@ 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")] @@ -3176,7 +3176,7 @@ "@ 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")] @@ -3192,9 +3192,9 @@ (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")] @@ -3306,10 +3306,10 @@ 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,%1 ;;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,%1 ;;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") @@ -3640,7 +3640,7 @@ (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") @@ -3747,7 +3747,7 @@ * 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") @@ -3760,7 +3760,7 @@ (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")]) @@ -4228,13 +4228,12 @@ } ") - ; 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))] "" @@ -4242,15 +4241,16 @@ 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 @@ -4272,14 +4272,13 @@ 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))] "" @@ -4287,15 +4286,16 @@ 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. @@ -4467,7 +4467,7 @@ "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")]) @@ -4479,7 +4479,7 @@ "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")]) @@ -4499,7 +4499,7 @@ "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")]) @@ -4588,7 +4588,7 @@ "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")]) @@ -4601,8 +4601,8 @@ "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")]) @@ -4613,7 +4613,7 @@ "@ 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") @@ -4707,7 +4707,7 @@ (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")]) @@ -5283,7 +5283,7 @@ ;; ??? 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", @@ -5295,7 +5295,7 @@ (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", @@ -5308,9 +5308,9 @@ ; 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", @@ -5629,7 +5629,7 @@ "@ 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") @@ -5651,7 +5651,7 @@ "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")]) @@ -5664,7 +5664,7 @@ "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")]) @@ -5691,7 +5691,7 @@ "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")]) diff --git a/gcc/config/arc/arc.opt b/gcc/config/arc/arc.opt index 593bd2dc30a..5f10c0ee005 100644 --- a/gcc/config/arc/arc.opt +++ b/gcc/config/arc/arc.opt @@ -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. diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md index 7c34ffd6779..565d8608e85 100644 --- a/gcc/config/arc/constraints.md +++ b/gcc/config/arc/constraints.md @@ -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)")) diff --git a/gcc/config/arc/elf.h b/gcc/config/arc/elf.h index 5abafcab4e2..3bb9cb012ae 100644 --- a/gcc/config/arc/elf.h +++ b/gcc/config/arc/elf.h @@ -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 diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md index db7b6426483..8f65df1ba0f 100644 --- a/gcc/config/arc/fpx.md +++ b/gcc/config/arc/fpx.md @@ -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")]) diff --git a/gcc/config/arc/linux.h b/gcc/config/arc/linux.h index 633ae9086f5..385083331d5 100644 --- a/gcc/config/arc/linux.h +++ b/gcc/config/arc/linux.h @@ -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. */ diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md index e742638b343..8885a6ae47d 100644 --- a/gcc/config/arc/simdext.md +++ b/gcc/config/arc/simdext.md @@ -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")]) diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index dce808f1eab..478894be0ea 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -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 diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4e21aa35da3..328ee849b0b 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2402caab4d7..4e02b1e6c64 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-01-26 Claudiu Zissulescu + + * gcc.target/arc/jli-1.c: New file. + * gcc.target/arc/jli-2.c: Likewise. + 2018-01-26 Szabolcs Nagy * 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 index 00000000000..f7259b35772 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/jli-1.c @@ -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 index 00000000000..96a35a4c090 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/jli-2.c @@ -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" } } */