+2014-07-23 Jiong Wang <jiong.wang@arm.com>
+
+ * gcc.target/aarch64/test_frame_common.h: New file.
+ * gcc.target/aarch64/test_frame_1.c: Likewise.
+ * gcc.target/aarch64/test_frame_2.c: Likewise.
+ * gcc.target/aarch64/test_frame_3.c: Likewise.
+ * gcc.target/aarch64/test_frame_4.c: Likewise.
+ * gcc.target/aarch64/test_frame_5.c: Likewise.
+ * gcc.target/aarch64/test_frame_6.c: Likewise.
+ * gcc.target/aarch64/test_frame_7.c: Likewise.
+ * gcc.target/aarch64/test_frame_8.c: Likewise.
+ * gcc.target/aarch64/test_frame_9.c: Likewise.
+ * gcc.target/aarch64/test_frame_10.c: Likewise.
+ * gcc.target/aarch64/test_frame_11.c: Likewise.
+ * gcc.target/aarch64/test_frame_12.c: Likewise.
+ * gcc.target/aarch64/test_frame_13.c: Likewise.
+ * gcc.target/aarch64/test_frame_14.c: Likewise.
+ * gcc.target/aarch64/test_frame_15.c: Likewise.
+
2014-07-23 Marek Polacek <polacek@redhat.com>
* c-c++-common/ubsan/bounds-2.c (fn4): Adjust to check the array size
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * withoug outgoing.
+ * total frame size <= 256.
+ * number of callee-save reg == 1.
+ * optimized code should use "str !" for stack adjustment. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test1, 200, )
+t_frame_run (test1)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * with outgoing.
+ * total frame size > 512.
+ area except outgoing <= 512
+ * number of callee-saved reg >= 2.
+ * Split stack adjustment into two subtractions.
+ the first subtractions could be optimized into "stp !". */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test10, 480, "x19", 24, a[8], a[9], a[10])
+t_frame_run (test10)
--- /dev/null
+/* Verify:
+ * without outgoing.
+ * total frame size <= 512.
+ * number of callee-save reg >= 2.
+ * optimized code should use "stp !" for stack adjustment. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test11, 400, )
+t_frame_run (test11)
+
+/* { dg-final { scan-assembler-times "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Verify:
+ * with outgoing.
+ * total frame size <= 512.
+ * number of callee-save reg >= 2. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test12, 400, , 8, a[8])
+t_frame_run (test12)
+
+/* { dg-final { scan-assembler-times "sub\tsp, sp, #\[0-9\]+" 1 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Verify:
+ * without outgoing.
+ * total frame size > 512.
+ * number of callee-save reg >= 2.
+ * split the stack adjustment into two substractions,
+ the second could be optimized into "stp !". */
+
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test13, 700, )
+t_frame_run (test13)
+
+/* { dg-final { scan-assembler-times "sub\tsp, sp, #\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" 2 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Verify:
+ * with outgoing.
+ * total frame size > 512.
+ * number of callee-save reg >= 2. */
+
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test14, 700, , 8, a[8])
+t_frame_run (test14)
--- /dev/null
+/* Verify:
+ * with outgoing.
+ * total frame size > 512.
+ area except outgoing <= 512
+ * number of callee-save reg >= 2.
+ * split the stack adjustment into two substractions,
+ the first could be optimized into "stp !". */
+
+/* { dg-do run } */
+/* { dg-options "-O2 --save-temps" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test15, 480, , 8, a[8])
+t_frame_run (test15)
+
+/* { dg-final { scan-assembler-times "sub\tsp, sp, #\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "stp\tx29, x30, \\\[sp, -\[0-9\]+\\\]!" 3 } } */
+/* { dg-final { cleanup-saved-temps } } */
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * without outgoing.
+ * total frame size <= 256.
+ * number of callee-save regs >= 2.
+ * optimized code should use "stp !" for stack adjustment. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test2, 200, "x19")
+t_frame_run (test2)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * without outgoing.
+ * total frame size <= 512 but > 256.
+ * number of callee-save reg == 1.
+ * we can't use "str !" to optimize stack adjustment. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test3, 400, )
+t_frame_run (test3)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * without outgoing.
+ * total frame size <= 512 but > 256.
+ * number of callee-save reg >= 2.
+ * we can use "stp !" to optimize stack adjustment. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test4, 400, "x19")
+t_frame_run (test4)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * with outgoing.
+ * total frame size <= 512.
+ * one subtraction of the whole frame size. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test5, 300, "x19", 8, a[8])
+t_frame_run (test5)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * without outgoing.
+ * total frame size > 512.
+ * number of callee-saved reg == 1.
+ * split stack adjustment into two subtractions.
+ the second subtraction should use "str !". */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test6, 700, )
+t_frame_run (test6)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * without outgoing.
+ * total frame size > 512.
+ * number of callee-saved reg == 2.
+ * split stack adjustment into two subtractions.
+ the second subtraction should use "stp !". */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern (test7, 700, "x19")
+t_frame_run (test7)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * with outgoing.
+ * total frame size bigger than 512.
+ * number of callee-saved reg == 1. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test8, 700, , 8, a[8])
+t_frame_run (test8)
--- /dev/null
+/* Verify:
+ * -fomit-frame-pointer.
+ * with outgoing.
+ * total frame size > 512.
+ area except outgoing <= 512
+ * number of callee-saved reg = 1.
+ * Split stack adjustment into two subtractions.
+ the first subtractions couldn't be optimized
+ into "str !" as it's > 256. */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -fomit-frame-pointer" } */
+
+#include "test_frame_common.h"
+
+t_frame_pattern_outgoing (test9, 480, , 24, a[8], a[9], a[10])
+t_frame_run (test9)
--- /dev/null
+extern void abort ();
+
+#define CVT(v) ((unsigned char)(v))
+
+static void __attribute__((noinline))
+check_args_8 (int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8)
+{
+ if (a0 != 0
+ || a1 != 1
+ || a2 != 2
+ || a3 != 3
+ || a4 != 4
+ || a5 != 5
+ || a6 != 6
+ || a7 != 7
+ || a8 != 8)
+ abort ();
+}
+
+static void __attribute__((noinline))
+check_args_24 (int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7,
+ int a8, int a9, int a10)
+{
+ if (a0 != 0
+ || a1 != 1
+ || a2 != 2
+ || a3 != 3
+ || a4 != 4
+ || a5 != 5
+ || a6 != 6
+ || a7 != 7
+ || a8 != 8
+ || a9 != 9
+ || a10 != 10)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+initialize_array (unsigned char *a, int len)
+{
+ int i;
+
+ for (i = 0; i < (len / 2); i++)
+ {
+ a[i] = i;
+ a[len - i - 1] = i;
+ }
+
+ return;
+}
+
+#define t_frame_pattern(name, local_size, callee_saved)\
+int \
+name (void)\
+{\
+ unsigned char a[local_size];\
+ initialize_array (a, local_size); \
+ __asm__ ("":::callee_saved); \
+ if (a[0] != a[local_size - 1] \
+ || a[0] != 0) \
+ return 0; \
+ if (a[local_size / 2 - 1] != a[local_size / 2] \
+ || a[local_size / 2 - 1] != CVT (local_size / 2 - 1)) \
+ return 0; \
+ return 1; \
+}
+
+#define t_frame_pattern_outgoing(name, local_size, callee_saved, out_going_num, ...)\
+int \
+name (void)\
+{\
+ unsigned char a[local_size];\
+ initialize_array (a, local_size); \
+ __asm__ ("":::callee_saved); \
+ if (a[0] != a[local_size - 1] \
+ || a[0] != 0) \
+ return 0; \
+ if (a[local_size / 2 - 1] != a[local_size / 2] \
+ || a[local_size / 2 - 1] != CVT (local_size / 2 - 1)) \
+ return 0; \
+ check_args_ ## out_going_num (a[0], a[1], a[2], a[3], a[4], a[5], a[6],\
+ a[7], __VA_ARGS__); \
+ return 1; \
+}
+
+#define t_frame_run(name) \
+int \
+main (int argc, char **argv) \
+{\
+ if (!name ())\
+ abort ();\
+ return 0;\
+}