diff options
author | Claudiu Zissulescu <claziss@synopsys.com> | 2017-08-31 16:25:55 +0200 |
---|---|---|
committer | Claudiu Zissulescu <claziss@gcc.gnu.org> | 2017-08-31 16:25:55 +0200 |
commit | 9f532472da3e506db3609ebb03cff3d5f20f7353 (patch) | |
tree | 3f3874a38140210c975019239a1fa6b37d2220fe /gcc/config | |
parent | b6fb793374fd887aee2b08b44145961b28533be2 (diff) | |
download | gcc-9f532472da3e506db3609ebb03cff3d5f20f7353.zip gcc-9f532472da3e506db3609ebb03cff3d5f20f7353.tar.gz gcc-9f532472da3e506db3609ebb03cff3d5f20f7353.tar.bz2 |
[ARC] Use -G option to control sdata behavior
gcc/
2017-04-24 Claudiu Zissulescu <claziss@synopsys.com>
* 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 <claziss@synopsys.com>
* gcc.target/arc/sdata-5.c: New test.
* gcc.target/arc/arc700-stld-hazard.c: Update test options.
Fix test
From-SVN: r251564
Diffstat (limited to 'gcc/config')
-rw-r--r-- | gcc/config/arc/arc.c | 236 | ||||
-rw-r--r-- | gcc/config/arc/arc.h | 6 | ||||
-rw-r--r-- | gcc/config/arc/simdext.md | 22 |
3 files changed, 142 insertions, 122 deletions
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c index c77a818..4dcac18 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 82cd0ad..2c06f9f 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 6c102d3..9f5b4a8 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<mode>" [(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>mode, operands[1]); + if (prepare_move_operands (operands, <MODE>mode)) + DONE; }") (define_insn_and_split "*mov<mode>_insn" @@ -1440,11 +1439,10 @@ [(set (match_operand:VWH 0 "general_operand" "") (match_operand:VWH 1 "general_operand" ""))] "" -{ - if (!register_operand (operands[0], <MODE>mode) - && !register_operand (operands[1], <MODE>mode)) - operands[1] = force_reg (<MODE>mode, operands[1]); -}) + "{ + if (prepare_move_operands (operands, <MODE>mode)) + DONE; + }") (define_insn "bswapv2hi2" [(set (match_operand:V2HI 0 "register_operand" "=r,r") |