Commit b6fb7933 by Claudiu Zissulescu Committed by Claudiu Zissulescu

[ARC] Improves and fixes for small data support.

Add alignment check for short load/store instructions used for sdata,
as they request 32-bit aligned short immediate.  Use sdata symbol
alignment information and emit scalled loads/stores whenever is
possible. The scalled address will extend the access range for sdata
symbols.  Allow 64-bit datum into small data section, if double
load/store instructions are present.

gcc/
2017-04-12  Claudiu Zissulescu  <claziss@synopsys.com>

	* config/arc/arc-protos.h (compact_sda_memory_operand): Update
	prototype.
	* config/arc/arc.c (arc_print_operand): Output scalled address for
	sdata whenever is possible.
	(arc_in_small_data_p): Allow sdata for 64bit datum when double
	load/stores are available.
	(compact_sda_memory_operand): Check for the alignment required by
	code density instructions.
	* config/arc/arc.md (movsi_insn): Use newly introduced Us0
	constraint.
	* config/arc/constraints.md (Usd): Update constraint.
	(Us0): New constraint.
	(Usc): Update constraint.

gcc/testsuite/
2017-04-12  Claudiu Zissulescu  <claziss@synopsys.com>

	* gcc.target/arc/sdata-3.c: New file.

From-SVN: r251562
parent a621861e
2017-08-31 Claudiu Zissulescu <claziss@synopsys.com>
* config/arc/arc-protos.h (compact_sda_memory_operand): Update
prototype.
* config/arc/arc.c (arc_print_operand): Output scalled address for
sdata whenever is possible.
(arc_in_small_data_p): Allow sdata for 64bit datum when double
load/stores are available.
(compact_sda_memory_operand): Check for the alignment required by
code density instructions.
* config/arc/arc.md (movsi_insn): Use newly introduced Us0
constraint.
* config/arc/constraints.md (Usd): Update constraint.
(Us0): New constraint.
(Usc): Update constraint.
2017-08-31 Richard Biener <rguenther@suse.de> 2017-08-31 Richard Biener <rguenther@suse.de>
PR middle-end/82054 PR middle-end/82054
......
...@@ -27,7 +27,7 @@ extern struct rtx_def *gen_compare_reg (rtx, machine_mode); ...@@ -27,7 +27,7 @@ extern struct rtx_def *gen_compare_reg (rtx, machine_mode);
/* Declarations for various fns used in the .md file. */ /* Declarations for various fns used in the .md file. */
extern void arc_output_function_epilogue (FILE *, HOST_WIDE_INT, int); extern void arc_output_function_epilogue (FILE *, HOST_WIDE_INT, int);
extern const char *output_shift (rtx *); extern const char *output_shift (rtx *);
extern bool compact_sda_memory_operand (rtx op,machine_mode mode); extern bool compact_sda_memory_operand (rtx, machine_mode, bool);
extern bool arc_double_limm_p (rtx); extern bool arc_double_limm_p (rtx);
extern void arc_print_operand (FILE *, rtx, int); extern void arc_print_operand (FILE *, rtx, int);
extern void arc_print_operand_address (FILE *, rtx); extern void arc_print_operand_address (FILE *, rtx);
......
...@@ -3804,6 +3804,26 @@ arc_print_operand (FILE *file, rtx x, int code) ...@@ -3804,6 +3804,26 @@ arc_print_operand (FILE *file, rtx x, int code)
fputs (".as", file); fputs (".as", file);
output_scaled = 1; output_scaled = 1;
} }
else if (LEGITIMATE_SMALL_DATA_ADDRESS_P (addr)
&& GET_MODE_SIZE (GET_MODE (x)) > 1)
{
tree decl = NULL_TREE;
int align = 0;
if (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
decl = SYMBOL_REF_DECL (XEXP (addr, 1));
else if (GET_CODE (XEXP (XEXP (XEXP (addr, 1), 0), 0))
== SYMBOL_REF)
decl = SYMBOL_REF_DECL (XEXP (XEXP (XEXP (addr, 1), 0), 0));
if (decl)
align = DECL_ALIGN (decl);
align = align / BITS_PER_UNIT;
if ((GET_MODE_SIZE (GET_MODE (x)) == 2)
&& align && ((align & 1) == 0))
fputs (".as", file);
if ((GET_MODE_SIZE (GET_MODE (x)) >= 4)
&& align && ((align & 3) == 0))
fputs (".as", file);
}
break; break;
case REG: case REG:
break; break;
...@@ -7475,12 +7495,10 @@ arc_in_small_data_p (const_tree decl) ...@@ -7475,12 +7495,10 @@ arc_in_small_data_p (const_tree decl)
{ {
HOST_WIDE_INT size; HOST_WIDE_INT size;
/* Strings and functions are never in small data area. */
if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
return false; return false;
/* We don't yet generate small-data references for -mabicalls. See related
-G handling in override_options. */
if (TARGET_NO_SDATA_SET) if (TARGET_NO_SDATA_SET)
return false; return false;
...@@ -7499,7 +7517,7 @@ arc_in_small_data_p (const_tree decl) ...@@ -7499,7 +7517,7 @@ arc_in_small_data_p (const_tree decl)
return true; return true;
} }
/* Only global variables go into sdata section for now. */ /* Only global variables go into sdata section for now. */
else if (1) else
{ {
/* Don't put constants into the small data section: we want them /* Don't put constants into the small data section: we want them
to be in ROM rather than RAM. */ to be in ROM rather than RAM. */
...@@ -7529,9 +7547,6 @@ arc_in_small_data_p (const_tree decl) ...@@ -7529,9 +7547,6 @@ arc_in_small_data_p (const_tree decl)
size = int_size_in_bytes (TREE_TYPE (decl)); size = int_size_in_bytes (TREE_TYPE (decl));
/* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
/* return false; */
/* Allow only <=4B long data types into sdata. */ /* Allow only <=4B long data types into sdata. */
return (size > 0 && size <= 4); return (size > 0 && size <= 4);
} }
...@@ -7623,10 +7638,13 @@ small_data_pattern (rtx op, machine_mode) ...@@ -7623,10 +7638,13 @@ small_data_pattern (rtx op, machine_mode)
/* volatile cache option still to be handled. */ /* volatile cache option still to be handled. */
bool bool
compact_sda_memory_operand (rtx op, machine_mode mode) compact_sda_memory_operand (rtx op, machine_mode mode, bool short_p)
{ {
rtx addr; rtx addr;
int size; int size;
tree decl = NULL_TREE;
int align = 0;
int mask = 0;
/* Eliminate non-memory operations. */ /* Eliminate non-memory operations. */
if (GET_CODE (op) != MEM) if (GET_CODE (op) != MEM)
...@@ -7644,7 +7662,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode) ...@@ -7644,7 +7662,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode)
/* Decode the address now. */ /* Decode the address now. */
addr = XEXP (op, 0); addr = XEXP (op, 0);
return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr); if (!LEGITIMATE_SMALL_DATA_ADDRESS_P (addr))
return false;
if (!short_p || size == 1)
return true;
/* Now check for the alignment, the short loads using gp require the
addresses to be aligned. */
if (GET_CODE (XEXP (addr, 1)) == SYMBOL_REF)
decl = SYMBOL_REF_DECL (XEXP (addr, 1));
else if (GET_CODE (XEXP (XEXP (XEXP (addr, 1), 0), 0)) == SYMBOL_REF)
decl = SYMBOL_REF_DECL (XEXP (XEXP (XEXP (addr, 1), 0), 0));
if (decl)
align = DECL_ALIGN (decl);
align = align / BITS_PER_UNIT;
switch (mode)
{
case E_HImode:
mask = 1;
break;
default:
mask = 3;
break;
}
if (align && ((align & mask) == 0))
return true;
return false;
} }
/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */ /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
......
...@@ -355,7 +355,7 @@ ...@@ -355,7 +355,7 @@
"@internal "@internal
A valid _small-data_ memory operand for ARCompact instructions" A valid _small-data_ memory operand for ARCompact instructions"
(and (match_code "mem") (and (match_code "mem")
(match_test "compact_sda_memory_operand (op, VOIDmode)"))) (match_test "compact_sda_memory_operand (op, VOIDmode, true)")))
(define_memory_constraint "Usc" (define_memory_constraint "Usc"
"@internal "@internal
...@@ -363,7 +363,7 @@ ...@@ -363,7 +363,7 @@
(and (match_code "mem") (and (match_code "mem")
(match_test "!CONSTANT_P (XEXP (op,0))") (match_test "!CONSTANT_P (XEXP (op,0))")
;; ??? the assembler rejects stores of immediates to small data. ;; ??? the assembler rejects stores of immediates to small data.
(match_test "!compact_sda_memory_operand (op, VOIDmode)"))) (match_test "!compact_sda_memory_operand (op, VOIDmode, false)")))
(define_constraint "Us<" (define_constraint "Us<"
"@internal "@internal
......
2017-08-31 Claudiu Zissulescu <claziss@synopsys.com>
* gcc.target/arc/sdata-3.c: New file.
* gcc.target/arc/sdata-4.c: Likewise.
2017-08-31 Richard Biener <rguenther@suse.de> 2017-08-31 Richard Biener <rguenther@suse.de>
PR middle-end/82054 PR middle-end/82054
......
/* Check if sdata access is done correctly, specially
for variables which are having a different alignment
than the default data type indicates. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
int g_a __attribute__ ((aligned (1)));
int g_b;
short g_c;
char g_d;
#define TEST(name, optype) \
void test_ ## name (optype x) \
{ \
g_ ## name += x; \
}
TEST (a, int)
TEST (b, int)
TEST (c, short)
TEST (d, char)
/* { dg-final { scan-assembler "ld r2,\\\[gp,@g_a@sda\\\]" } } */
/* { dg-final { scan-assembler "ld.as r2,\\\[gp,@g_b@sda\\\]" } } */
/* { dg-final { scan-assembler "ld\[hw\]\\\.as r2,\\\[gp,@g_c@sda\\\]" } } */
/* { dg-final { scan-assembler "ldb r2,\\\[gp,@g_d@sda\\\]" } } */
/* { dg-final { scan-assembler "st r0,\\\[gp,@g_a@sda\\\]" } } */
/* { dg-final { scan-assembler "st_s r0,\\\[gp,@g_b@sda\\\]" { target { arcem || archs } } } } */
/* { dg-final { scan-assembler "st\\\.as r0,\\\[gp,@g_b@sda\\\]" { target { arc700 || arc6xx } } } } */
/* { dg-final { scan-assembler "st\[hw\]\\\.as r0,\\\[gp,@g_c@sda\\\]" } } */
/* { dg-final { scan-assembler "stb r0,\\\[gp,@g_d@sda\\\]" } } */
/* Check if sdata access is done correctly, specially
for variables which are having a different alignment
than the default data type indicates. */
/* { dg-do compile } */
/* { dg-options "-O2" } */
short gA __attribute__ ((aligned(1)));
void foo (void)
{
gA += gA + 3;
}
/* { dg-final { scan-assembler-not "ld\[wh\]_s r0,\\\[gp" } } */
/* { dg-final { scan-assembler-not "st\[wh\]\\\.as.*gp" } } */
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