From 9f532472da3e506db3609ebb03cff3d5f20f7353 Mon Sep 17 00:00:00 2001 From: Claudiu Zissulescu Date: Thu, 31 Aug 2017 16:25:55 +0200 Subject: [PATCH] [ARC] Use -G option to control sdata behavior gcc/ 2017-04-24 Claudiu Zissulescu * config.gcc: Use g.opt for arc. * config/arc/arc.c (LEGITIMATE_SCALED_ADDRESS_P): Deleted, functionality moved to ... (legitimate_scaled_address_p): New function, ...here. (LEGITIMATE_SMALL_DATA_OFFSET_P): New define. (LEGITIMATE_SMALL_DATA_ADDRESS_P): Use the above define. (legitimate_offset_address_p): Delete TARGET_NO_SDATA_SET condition. (arc_override_options): Handle G option. (arc_output_pic_addr_const): Correct function definition. (arc_legitimate_address_p): Use legitimate_scaled_address_p. (arc_decl_anon_ns_mem_p): Delete. (arc_in_small_data_p): Overhaul this function to take into consideration the value given via G option. (arc_rewrite_small_data_1): Renamed and corrected old arc_rewrite_small_data function. (arc_rewrite_small_data): New function. (small_data_pattern): Don't use pic_offset_table_rtx. * config/arc/arc.h (CC1_SPEC): Recognize G option. * config/arc/simdext.md (movmisalignv2hi): Use prepare_move_operands function. (mov*): Likewise. (movmisalign*): Likewise. gcc/testsuite/ 2017-04-24 Claudiu Zissulescu * gcc.target/arc/sdata-5.c: New test. * gcc.target/arc/arc700-stld-hazard.c: Update test options. Fix test From-SVN: r251564 --- gcc/ChangeLog | 27 ++ gcc/config.gcc | 2 +- gcc/config/arc/arc.c | 236 ++++++++++-------- gcc/config/arc/arc.h | 6 +- gcc/config/arc/simdext.md | 22 +- gcc/doc/invoke.texi | 9 +- gcc/testsuite/ChangeLog | 5 + .../gcc.target/arc/arc700-stld-hazard.c | 2 +- gcc/testsuite/gcc.target/arc/sdata-5.c | 15 ++ 9 files changed, 199 insertions(+), 125 deletions(-) create mode 100755 gcc/testsuite/gcc.target/arc/sdata-5.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0be29fc339..c0e032b1a77 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,30 @@ +2017-08-31 Claudiu Zissulescu + + * config.gcc: Use g.opt for arc. + * config/arc/arc.c (LEGITIMATE_SCALED_ADDRESS_P): Deleted, + functionality moved to ... + (legitimate_scaled_address_p): New function, ...here. + (LEGITIMATE_SMALL_DATA_OFFSET_P): New define. + (LEGITIMATE_SMALL_DATA_ADDRESS_P): Use the above define. + (legitimate_offset_address_p): Delete TARGET_NO_SDATA_SET + condition. + (arc_override_options): Handle G option. + (arc_output_pic_addr_const): Correct function definition. + (arc_legitimate_address_p): Use legitimate_scaled_address_p. + (arc_decl_anon_ns_mem_p): Delete. + (arc_in_small_data_p): Overhaul this function to take into + consideration the value given via G option. + (arc_rewrite_small_data_1): Renamed and corrected old + arc_rewrite_small_data function. + (arc_rewrite_small_data): New function. + (small_data_pattern): Don't use pic_offset_table_rtx. + * config/arc/arc.h (CC1_SPEC): Recognize G option. + * config/arc/simdext.md (movmisalignv2hi): Use + prepare_move_operands function. + (mov*): Likewise. + (movmisalign*): Likewise. + * doc/invoke.texi (ARC options): Document -G option. + 2017-08-31 Claudiu Zissulescu * config/arc/arc-protos.h (compact_sda_memory_operand): Update diff --git a/gcc/config.gcc b/gcc/config.gcc index cc56c576864..b5229766b31 100644 --- a/gcc/config.gcc +++ b/gcc/config.gcc @@ -318,7 +318,7 @@ arc*-*-*) cpu_type=arc c_target_objs="arc-c.o" cxx_target_objs="arc-c.o" - extra_options="${extra_options} arc/arc-tables.opt" + extra_options="${extra_options} arc/arc-tables.opt g.opt" extra_headers="arc-simd.h" ;; arm*-*-*) diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index c77a818bc6d..4dcac1892a7 100644 --- a/gcc/config/arc/arc.c +++ b/gcc/config/arc/arc.c @@ -79,26 +79,21 @@ static const char *arc_cpu_string = arc_cpu_name; ? 0 \ : -(-GET_MODE_SIZE (MODE) | -4) >> 1))) -#define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \ -(GET_CODE (X) == PLUS \ - && GET_CODE (XEXP (X, 0)) == MULT \ - && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \ - && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \ - && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \ - || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \ - && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \ - || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1))))) - -#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \ - (GET_CODE (X) == PLUS \ - && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \ - && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \ - && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \ - || (GET_CODE (XEXP ((X), 1)) == CONST \ - && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \ - && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \ - && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT))) +#define LEGITIMATE_SMALL_DATA_OFFSET_P(X) \ + (GET_CODE (X) == CONST \ + && GET_CODE (XEXP ((X), 0)) == PLUS \ + && GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \ + && SYMBOL_REF_SMALL_P (XEXP (XEXP ((X), 0), 0)) \ + && GET_CODE (XEXP(XEXP ((X), 0), 1)) == CONST_INT \ + && INTVAL (XEXP (XEXP ((X), 0), 1)) <= g_switch_value) + +#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \ + (GET_CODE (X) == PLUS \ + && REG_P (XEXP ((X), 0)) \ + && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM \ + && ((GET_CODE (XEXP ((X), 1)) == SYMBOL_REF \ + && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \ + || LEGITIMATE_SMALL_DATA_OFFSET_P (XEXP ((X), 1)))) /* Array of valid operand punctuation characters. */ char arc_punct_chars[256]; @@ -276,6 +271,61 @@ static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT, /* Globally visible information about currently selected cpu. */ const arc_cpu_t *arc_selected_cpu; +static bool +legitimate_scaled_address_p (machine_mode mode, rtx op, bool strict) +{ + if (GET_CODE (op) != PLUS) + return false; + + if (GET_CODE (XEXP (op, 0)) != MULT) + return false; + + /* Check multiplication operands. */ + if (!RTX_OK_FOR_INDEX_P (XEXP (XEXP (op, 0), 0), strict)) + return false; + + if (!CONST_INT_P (XEXP (XEXP (op, 0), 1))) + return false; + + switch (GET_MODE_SIZE (mode)) + { + case 2: + if (INTVAL (XEXP (XEXP (op, 0), 1)) != 2) + return false; + break; + case 8: + if (!TARGET_LL64) + return false; + /* Fall through. */ + case 4: + if (INTVAL (XEXP (XEXP (op, 0), 1)) != 4) + return false; + default: + return false; + } + + /* Check the base. */ + if (RTX_OK_FOR_BASE_P (XEXP (op, 1), (strict))) + return true; + + if (flag_pic) + { + if (CONST_INT_P (XEXP (op, 1))) + return true; + return false; + } + if (CONSTANT_P (XEXP (op, 1))) + { + /* Scalled addresses for sdata is done other places. */ + if (GET_CODE (XEXP (op, 1)) == SYMBOL_REF + && SYMBOL_REF_SMALL_P (XEXP (op, 1))) + return false; + return true; + } + + return false; +} + /* Check for constructions like REG + OFFS, where OFFS can be a register, an immediate or an long immediate. */ @@ -301,8 +351,7 @@ legitimate_offset_address_p (machine_mode mode, rtx x, bool index, bool strict) && (GET_MODE_SIZE (mode) <= 4) /* Avoid small data which ends in something like GP + symb@sda. */ - && (!SYMBOL_REF_SMALL_P (XEXP (x, 1)) - || TARGET_NO_SDATA_SET)) + && (!SYMBOL_REF_SMALL_P (XEXP (x, 1)))) return true; return false; @@ -1117,6 +1166,10 @@ arc_override_options (void) if (TARGET_COMPACT_CASESI) TARGET_CASE_VECTOR_PC_RELATIVE = 1; + /* Check for small data option */ + if (!global_options_set.x_g_switch_value && !TARGET_NO_SDATA_SET) + g_switch_value = TARGET_LL64 ? 8 : 4; + /* These need to be done at start up. It's convenient to do them here. */ arc_init (); } @@ -5422,7 +5475,7 @@ arc_legitimize_pic_address (rtx orig, rtx oldx) /* Output address constant X to FILE, taking PIC into account. */ -void +static void arc_output_pic_addr_const (FILE * file, rtx x, int code) { char buf[256]; @@ -5871,7 +5924,7 @@ arc_legitimate_address_p (machine_mode mode, rtx x, bool strict) return true; if (legitimate_offset_address_p (mode, x, TARGET_INDEXED_LOADS, strict)) return true; - if (LEGITIMATE_SCALED_ADDRESS_P (mode, x, strict)) + if (legitimate_scaled_address_p (mode, x, strict)) return true; if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x)) return true; @@ -7465,28 +7518,6 @@ valid_brcc_with_delay_p (rtx *operands) return brcc_nolimm_operator (operands[0], VOIDmode); } -/* ??? Hack. This should no really be here. See PR32143. */ -static bool -arc_decl_anon_ns_mem_p (const_tree decl) -{ - while (1) - { - if (decl == NULL_TREE || decl == error_mark_node) - return false; - if (TREE_CODE (decl) == NAMESPACE_DECL - && DECL_NAME (decl) == NULL_TREE) - return true; - /* Classes and namespaces inside anonymous namespaces have - TREE_PUBLIC == 0, so we can shortcut the search. */ - else if (TYPE_P (decl)) - return (TREE_PUBLIC (TYPE_NAME (decl)) == 0); - else if (TREE_CODE (decl) == NAMESPACE_DECL) - return (TREE_PUBLIC (decl) == 0); - else - decl = DECL_CONTEXT (decl); - } -} - /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to access DECL using %gp_rel(...)($gp). */ @@ -7495,60 +7526,43 @@ arc_in_small_data_p (const_tree decl) { HOST_WIDE_INT size; - /* Strings and functions are never in small data area. */ - if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) + /* Only variables are going into small data area. */ + if (TREE_CODE (decl) != VAR_DECL) return false; if (TARGET_NO_SDATA_SET) return false; - if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0) - { - const char *name; - - /* Reject anything that isn't in a known small-data section. */ - name = DECL_SECTION_NAME (decl); - if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0) - return false; - - /* If a symbol is defined externally, the assembler will use the - usual -G rules when deciding how to implement macros. */ - if (!DECL_EXTERNAL (decl)) - return true; - } - /* Only global variables go into sdata section for now. */ - else - { - /* Don't put constants into the small data section: we want them - to be in ROM rather than RAM. */ - if (TREE_CODE (decl) != VAR_DECL) - return false; - - if (TREE_READONLY (decl) - && !TREE_SIDE_EFFECTS (decl) - && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl)))) - return false; - - /* TREE_PUBLIC might change after the first call, because of the patch - for PR19238. */ - if (default_binds_local_p_1 (decl, 1) - || arc_decl_anon_ns_mem_p (decl)) - return false; - - /* To ensure -mvolatile-cache works - ld.di does not have a gp-relative variant. */ - if (TREE_THIS_VOLATILE (decl)) - return false; - } - /* Disable sdata references to weak variables. */ if (DECL_WEAK (decl)) return false; - size = int_size_in_bytes (TREE_TYPE (decl)); + /* Don't put constants into the small data section: we want them to + be in ROM rather than RAM. */ + if (TREE_READONLY (decl)) + return false; + + /* To ensure -mvolatile-cache works ld.di does not have a + gp-relative variant. */ + if (!TARGET_VOLATILE_CACHE_SET + && TREE_THIS_VOLATILE (decl)) + return false; - /* Allow only <=4B long data types into sdata. */ - return (size > 0 && size <= 4); + if (DECL_SECTION_NAME (decl) != 0) + { + const char *name = DECL_SECTION_NAME (decl); + if (strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) + return true; + } + /* If it's not public, there's no need to put it in the small data + section. */ + else if (TREE_PUBLIC (decl)) + { + size = int_size_in_bytes (TREE_TYPE (decl)); + return (size > 0 && size <= g_switch_value); + } + return false; } /* Return true if X is a small data address that can be rewritten @@ -7577,9 +7591,10 @@ arc_rewrite_small_data_p (const_rtx x) /* If possible, rewrite OP so that it refers to small data using explicit relocations. */ -rtx -arc_rewrite_small_data (rtx op) +static rtx +arc_rewrite_small_data_1 (rtx op) { + rtx rgp = gen_rtx_REG (Pmode, SDATA_BASE_REGNUM); op = copy_insn (op); subrtx_ptr_iterator::array_type array; FOR_EACH_SUBRTX_PTR (iter, array, &op, ALL) @@ -7587,28 +7602,33 @@ arc_rewrite_small_data (rtx op) rtx *loc = *iter; if (arc_rewrite_small_data_p (*loc)) { - gcc_assert (SDATA_BASE_REGNUM == PIC_OFFSET_TABLE_REGNUM); - *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc); - if (loc != &op) - { - if (GET_CODE (op) == MEM && &XEXP (op, 0) == loc) - ; /* OK. */ - else if (GET_CODE (op) == MEM - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 0)) == MULT) - *loc = force_reg (Pmode, *loc); - else - gcc_unreachable (); - } + *loc = gen_rtx_PLUS (Pmode, rgp, *loc); iter.skip_subrtxes (); } else if (GET_CODE (*loc) == PLUS - && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx)) + && rtx_equal_p (XEXP (*loc, 0), rgp)) iter.skip_subrtxes (); } return op; } +rtx +arc_rewrite_small_data (rtx op) +{ + op = arc_rewrite_small_data_1 (op); + + /* Check if we fit small data constraints. */ + if (MEM_P (op) + && !LEGITIMATE_SMALL_DATA_ADDRESS_P (XEXP (op, 0))) + { + rtx addr = XEXP (op, 0); + rtx tmp = gen_reg_rtx (Pmode); + emit_move_insn (tmp, addr); + op = replace_equiv_address_nv (op, tmp); + } + return op; +} + /* Return true if OP refers to small data symbols directly, not through a PLUS. */ @@ -7617,12 +7637,14 @@ small_data_pattern (rtx op, machine_mode) { if (GET_CODE (op) == SEQUENCE) return false; + + rtx rgp = gen_rtx_REG (Pmode, SDATA_BASE_REGNUM); subrtx_iterator::array_type array; FOR_EACH_SUBRTX (iter, array, op, ALL) { const_rtx x = *iter; if (GET_CODE (x) == PLUS - && rtx_equal_p (XEXP (x, 0), pic_offset_table_rtx)) + && rtx_equal_p (XEXP (x, 0), rgp)) iter.skip_subrtxes (); else if (arc_rewrite_small_data_p (x)) return true; diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h index 82cd0ad6217..2c06f9fc305 100644 --- a/gcc/config/arc/arc.h +++ b/gcc/config/arc/arc.h @@ -65,9 +65,9 @@ along with GCC; see the file COPYING3. If not see %(subtarget_cpp_spec)" #undef CC1_SPEC -#define CC1_SPEC "\ -%{EB:%{EL:%emay not use both -EB and -EL}} \ -%{EB:-mbig-endian} %{EL:-mlittle-endian} \ +#define CC1_SPEC "%{EB:%{EL:%emay not use both -EB and -EL}} \ +%{EB:-mbig-endian} %{EL:-mlittle-endian} \ +%{G*} \ " extern const char *arc_cpu_to_as (int argc, const char **argv); diff --git a/gcc/config/arc/simdext.md b/gcc/config/arc/simdext.md index 6c102d3c7f8..9f5b4a82e56 100644 --- a/gcc/config/arc/simdext.md +++ b/gcc/config/arc/simdext.md @@ -1383,19 +1383,18 @@ [(set (match_operand:V2HI 0 "general_operand" "") (match_operand:V2HI 1 "general_operand" ""))] "" -{ - if (!register_operand (operands[0], V2HImode) - && !register_operand (operands[1], V2HImode)) - operands[1] = force_reg (V2HImode, operands[1]); -}) + "{ + if (prepare_move_operands (operands, V2HImode)) + DONE; + }") (define_expand "mov" [(set (match_operand:VWH 0 "move_dest_operand" "") (match_operand:VWH 1 "general_operand" ""))] "" "{ - if (GET_CODE (operands[0]) == MEM) - operands[1] = force_reg (mode, operands[1]); + if (prepare_move_operands (operands, mode)) + DONE; }") (define_insn_and_split "*mov_insn" @@ -1440,11 +1439,10 @@ [(set (match_operand:VWH 0 "general_operand" "") (match_operand:VWH 1 "general_operand" ""))] "" -{ - if (!register_operand (operands[0], mode) - && !register_operand (operands[1], mode)) - operands[1] = force_reg (mode, operands[1]); -}) + "{ + if (prepare_move_operands (operands, mode)) + DONE; + }") (define_insn "bswapv2hi2" [(set (match_operand:V2HI 0 "register_operand" "=r,r") diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 64363e54a00..1241b1840ef 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -614,7 +614,7 @@ Objective-C and Objective-C++ Dialects}. -mcrc -mdsp-packa -mdvbf -mlock -mmac-d16 -mmac-24 -mrtsc -mswape @gol -mtelephony -mxy -misize -mannotate-align -marclinux -marclinux_prof @gol -mlong-calls -mmedium-calls -msdata -mirq-ctrl-saved @gol --mrgf-banked-regs @gol +-mrgf-banked-regs -G @var{num} @gol -mvolatile-cache -mtp-regno=@var{regno} @gol -malign-call -mauto-modify-reg -mbbit-peephole -mno-brcc @gol -mcase-vector-pcrel -mcompact-casesi -mno-cond-exec -mearly-cbranchsi @gol @@ -14896,6 +14896,13 @@ allow use of the 25-bit range, rather than the 21-bit range with conditional branch-and-link. This is the default for tool chains built for @w{@code{arc-linux-uclibc}} and @w{@code{arceb-linux-uclibc}} targets. +@item -G @var{num} +@opindex G +Put definitions of externally-visible data in a small data section if +that data is no bigger than @var{num} bytes. The default value of +@var{num} is 4 for any ARC configuration, or 8 when we have double +load/store operations. + @item -mno-sdata @opindex mno-sdata Do not generate sdata references. This is the default for tool chains diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9de87dd725b..cd63ace8250 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-08-31 Claudiu Zissulescu + + * gcc.target/arc/sdata-5.c: New test. + * gcc.target/arc/arc700-stld-hazard.c: Update test options. + 2017-08-31 Claudiu Zissulescu * gcc.target/arc/sdata-3.c: New file. diff --git a/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c b/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c index bf6ae334284..eba03d86256 100644 --- a/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c +++ b/gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c @@ -1,5 +1,5 @@ /* { dg-do compile } */ -/* { dg-options "-mcpu=arc700" } */ +/* { dg-options "-mcpu=arc700 -mno-sdata" } */ volatile int a; volatile int b; diff --git a/gcc/testsuite/gcc.target/arc/sdata-5.c b/gcc/testsuite/gcc.target/arc/sdata-5.c new file mode 100755 index 00000000000..0d4eae5c454 --- /dev/null +++ b/gcc/testsuite/gcc.target/arc/sdata-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -msdata" } */ + +/* Check interaction between section anchors and small data. */ + +const int a[1] = {}; +static short b[] = {}; + +int c; + +const int* fn1 (void) +{ + return a + b[c]; +} +/* { dg-final { scan-assembler "@c@sda" } } */ -- 2.30.2