[ARC] Improves and fixes for small data support.
authorClaudiu Zissulescu <claziss@synopsys.com>
Thu, 31 Aug 2017 13:52:31 +0000 (15:52 +0200)
committerClaudiu Zissulescu <claziss@gcc.gnu.org>
Thu, 31 Aug 2017 13:52:31 +0000 (15:52 +0200)
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

gcc/ChangeLog
gcc/config/arc/arc-protos.h
gcc/config/arc/arc.c
gcc/config/arc/constraints.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arc/sdata-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arc/sdata-4.c [new file with mode: 0644]

index 175759c54aad260cf98a5e962c7f0cc5ec15125e..f0be29fc339402e0d13b9c42635e3ef76da4d6fd 100644 (file)
@@ -1,3 +1,19 @@
+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>
 
        PR middle-end/82054
index 8a9af46486ece9dfe59cef42a89a41850170231e..1c7031c2894bafcae151ead01ec6ceb36db3593c 100644 (file)
@@ -27,7 +27,7 @@ extern struct rtx_def *gen_compare_reg (rtx, machine_mode);
 /* Declarations for various fns used in the .md file.  */
 extern void arc_output_function_epilogue (FILE *, HOST_WIDE_INT, int);
 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 void arc_print_operand (FILE *, rtx, int);
 extern void arc_print_operand_address (FILE *, rtx);
index 9b83a46e60a6bdd891306d26b2b035553d0302bd..c77a818bc6d22d75eba1b1d5ad7bbaa4f54ab5bc 100644 (file)
@@ -3804,6 +3804,26 @@ arc_print_operand (FILE *file, rtx x, int code)
                  fputs (".as", file);
                  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;
            case REG:
              break;
@@ -7475,12 +7495,10 @@ 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)
     return false;
 
-
-  /* We don't yet generate small-data references for -mabicalls.  See related
-     -G handling in override_options.  */
   if (TARGET_NO_SDATA_SET)
     return false;
 
@@ -7499,7 +7517,7 @@ arc_in_small_data_p (const_tree decl)
          return true;
     }
   /* 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
         to be in ROM rather than RAM.  */
@@ -7529,9 +7547,6 @@ arc_in_small_data_p (const_tree 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.  */
   return (size > 0 && size <= 4);
 }
@@ -7623,10 +7638,13 @@ small_data_pattern (rtx op, machine_mode)
 /* volatile cache option still to be handled.  */
 
 bool
-compact_sda_memory_operand (rtx op, machine_mode mode)
+compact_sda_memory_operand (rtx op, machine_mode mode, bool short_p)
 {
   rtx addr;
   int size;
+  tree decl = NULL_TREE;
+  int align = 0;
+  int mask = 0;
 
   /* Eliminate non-memory operations.  */
   if (GET_CODE (op) != MEM)
@@ -7644,7 +7662,35 @@ compact_sda_memory_operand (rtx op, machine_mode mode)
   /* Decode the address now.  */
   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.  */
index 6620daf18e398379ad4a9c95e6c9275c184746fe..0ad318c3dc3301979c9f9cb8de5f08c2afe95bf4 100644 (file)
    "@internal
     A valid _small-data_ memory operand for ARCompact instructions"
    (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"
   "@internal
   (and (match_code "mem")
        (match_test "!CONSTANT_P (XEXP (op,0))")
 ;; ??? 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<"
   "@internal
index ff5169ae1f7d33d1ad7099c05c4a528642d8b69e..9de87dd725b0b8ce7557297b33f81a9d98f4857a 100644 (file)
@@ -1,3 +1,8 @@
+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>
 
        PR middle-end/82054
diff --git a/gcc/testsuite/gcc.target/arc/sdata-3.c b/gcc/testsuite/gcc.target/arc/sdata-3.c
new file mode 100644 (file)
index 0000000..cdf3b6d
--- /dev/null
@@ -0,0 +1,32 @@
+/* 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\\\]" } } */
diff --git a/gcc/testsuite/gcc.target/arc/sdata-4.c b/gcc/testsuite/gcc.target/arc/sdata-4.c
new file mode 100644 (file)
index 0000000..45fe712
--- /dev/null
@@ -0,0 +1,15 @@
+/* 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" } } */