@@ -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*-*-*)
@@ -78,26 +78,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];
@@ -275,6 +270,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 (enum machine_mode mode, rtx x, bool index,
&& (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;
@@ -1120,6 +1169,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 ();
}
@@ -5518,7 +5571,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];
@@ -5967,7 +6020,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;
@@ -7561,28 +7614,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). */
@@ -7591,60 +7622,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
@@ -7673,9 +7687,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)
@@ -7683,28 +7698,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. */
@@ -7713,12 +7733,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;
@@ -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);
@@ -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")
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-mcpu=arc700" } */
+/* { dg-options "-mcpu=arc700 -mno-sdata" } */
volatile int a;
volatile int b;
new file mode 100755
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-w -Os" } */
+
+const a[1] = {};
+static short b[] = {};
+
+c;
+fn1() { return a + b[c]; }
From: claziss <claziss@synopsys.com> Add support for -G option to ARC backend. 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 --- gcc/config.gcc | 2 +- gcc/config/arc/arc.c | 236 ++++++++++++---------- gcc/config/arc/arc.h | 6 +- gcc/config/arc/simdext.md | 22 +- gcc/testsuite/gcc.target/arc/arc700-stld-hazard.c | 2 +- gcc/testsuite/gcc.target/arc/sdata-5.c | 8 + 6 files changed, 152 insertions(+), 124 deletions(-) create mode 100755 gcc/testsuite/gcc.target/arc/sdata-5.c