aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2018-01-13 17:56:52 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2018-01-13 17:56:52 +0000
commitdbc3af4fc620aeb6fbf088e961fe8658bbd959c7 (patch)
treecbbcda2f43cf257940616199a72d7b22c5d92a50 /gcc
parent825b856cd08968694085aa13d0b937520b67a19d (diff)
downloadgcc-dbc3af4fc620aeb6fbf088e961fe8658bbd959c7.zip
gcc-dbc3af4fc620aeb6fbf088e961fe8658bbd959c7.tar.gz
gcc-dbc3af4fc620aeb6fbf088e961fe8658bbd959c7.tar.bz2
SVE unwinding
This patch adds support for unwinding frames that use the SVE pseudo VG register. We want this register to act like a normal register if the CFI explicitly sets it, but want to provide a default value otherwise. Computing the default value requires an SVE target, so we only want to compute it on demand. aarch64_vg uses a hard-coded .inst in order to avoid a build dependency on binutils 2.28 or later. 2018-01-13 Richard Sandiford <richard.sandiford@linaro.org> gcc/ * doc/tm.texi.in (DWARF_LAZY_REGISTER_VALUE): Document. * doc/tm.texi: Regenerate. libgcc/ * config/aarch64/value-unwind.h (aarch64_vg): New function. (DWARF_LAZY_REGISTER_VALUE): Define. * unwind-dw2.c (_Unwind_GetGR): Use DWARF_LAZY_REGISTER_VALUE to provide a fallback register value. gcc/testsuite/ * g++.target/aarch64/sve/aarch64-sve.exp: New harness. * g++.target/aarch64/sve/catch_1.C: New test. * g++.target/aarch64/sve/catch_2.C: Likewise. * g++.target/aarch64/sve/catch_3.C: Likewise. * g++.target/aarch64/sve/catch_4.C: Likewise. * g++.target/aarch64/sve/catch_5.C: Likewise. * g++.target/aarch64/sve/catch_6.C: Likewise. Reviewed-by: James Greenhalgh <james.greenhalgh@arm.com> From-SVN: r256615
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/doc/tm.texi7
-rw-r--r--gcc/doc/tm.texi.in7
-rw-r--r--gcc/testsuite/ChangeLog10
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/aarch64-sve.exp45
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_1.C69
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_2.C4
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_3.C78
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_4.C4
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_5.C81
-rw-r--r--gcc/testsuite/g++.target/aarch64/sve/catch_6.C4
11 files changed, 314 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 40da1eb..64951e9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,4 +1,9 @@
2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * doc/tm.texi.in (DWARF_LAZY_REGISTER_VALUE): Document.
+ * doc/tm.texi: Regenerate.
+
+2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 11b560b..4cd8dce 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -3621,6 +3621,13 @@ defined and 0 otherwise.
@end defmac
+@defmac DWARF_LAZY_REGISTER_VALUE (@var{regno}, @var{value})
+Define this macro if the target has pseudo DWARF registers whose
+values need to be computed lazily on demand by the unwinder (such as when
+referenced in a CFA expression). The macro returns true if @var{regno}
+is such a register and stores its value in @samp{*@var{value}} if so.
+@end defmac
+
@node Elimination
@subsection Eliminating Frame Pointer and Arg Pointer
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 0cd694a..3a2c2f2 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -3002,6 +3002,13 @@ defined and 0 otherwise.
@end defmac
+@defmac DWARF_LAZY_REGISTER_VALUE (@var{regno}, @var{value})
+Define this macro if the target has pseudo DWARF registers whose
+values need to be computed lazily on demand by the unwinder (such as when
+referenced in a CFA expression). The macro returns true if @var{regno}
+is such a register and stores its value in @samp{*@var{value}} if so.
+@end defmac
+
@node Elimination
@subsection Eliminating Frame Pointer and Arg Pointer
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index eb1b229..48f40da 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,4 +1,14 @@
2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
+
+ * g++.target/aarch64/sve/aarch64-sve.exp: New harness.
+ * g++.target/aarch64/sve/catch_1.C: New test.
+ * g++.target/aarch64/sve/catch_2.C: Likewise.
+ * g++.target/aarch64/sve/catch_3.C: Likewise.
+ * g++.target/aarch64/sve/catch_4.C: Likewise.
+ * g++.target/aarch64/sve/catch_5.C: Likewise.
+ * g++.target/aarch64/sve/catch_6.C: Likewise.
+
+2018-01-13 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
diff --git a/gcc/testsuite/g++.target/aarch64/sve/aarch64-sve.exp b/gcc/testsuite/g++.target/aarch64/sve/aarch64-sve.exp
new file mode 100644
index 0000000..7557aa6
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/aarch64-sve.exp
@@ -0,0 +1,45 @@
+# Specific regression driver for AArch64.
+# Copyright (C) 2009-2017 Free Software Foundation, Inc.
+# Contributed by ARM Ltd.
+#
+# This file is part of GCC.
+#
+# GCC is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GCC is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING3. If not see
+# <http://www.gnu.org/licenses/>. */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } then {
+ return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE if we're not testing it already.
+if { [check_effective_target_aarch64_sve] } {
+ set sve_flags ""
+} else {
+ set sve_flags "-march=armv8.2-a+sve"
+}
+
+# Main loop.
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.C]] $sve_flags ""
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_1.C b/gcc/testsuite/g++.target/aarch64/sve/catch_1.C
new file mode 100644
index 0000000..39759cb
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_1.C
@@ -0,0 +1,69 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fno-omit-frame-pointer" } */
+
+/* Invoke X (P##n) for n in [0, 7]. */
+#define REPEAT8(X, P) \
+ X (P##0) X (P##1) X (P##2) X (P##3) X (P##4) X (P##5) X (P##6) X (P##7)
+
+/* Invoke X (n) for all octal n in [0, 39]. */
+#define REPEAT40(X) \
+ REPEAT8 (X, 0) REPEAT8 (X, 1) REPEAT8 (X, 2) REPEAT8 (X, 3) REPEAT8 (X, 4)
+
+volatile int testi;
+
+/* Throw to f3. */
+void __attribute__ ((weak))
+f1 (int x[40][100], int *y)
+{
+ /* A wild write to x and y. */
+ asm volatile ("" ::: "memory");
+ if (y[testi] == x[testi][testi])
+ throw 100;
+}
+
+/* Expect vector work to be done, with spilling of vector registers. */
+void __attribute__ ((weak))
+f2 (int x[40][100], int *y)
+{
+ /* Try to force some spilling. */
+#define DECLARE(N) int y##N = y[N];
+ REPEAT40 (DECLARE);
+ for (int j = 0; j < 20; ++j)
+ {
+ f1 (x, y);
+#pragma omp simd
+ for (int i = 0; i < 100; ++i)
+ {
+#define INC(N) x[N][i] += y##N;
+ REPEAT40 (INC);
+ }
+ }
+}
+
+/* Catch an exception thrown from f1, via f2. */
+void __attribute__ ((weak))
+f3 (int x[40][100], int *y, int *z)
+{
+ volatile int extra = 111;
+ try
+ {
+ f2 (x, y);
+ }
+ catch (int val)
+ {
+ *z = val + extra;
+ }
+}
+
+static int x[40][100];
+static int y[40];
+static int z;
+
+int
+main (void)
+{
+ f3 (x, y, &z);
+ if (z != 211)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_2.C b/gcc/testsuite/g++.target/aarch64/sve/catch_2.C
new file mode 100644
index 0000000..7722af1
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_2.C
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fomit-frame-pointer" } */
+
+#include "catch_1.C"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_3.C b/gcc/testsuite/g++.target/aarch64/sve/catch_3.C
new file mode 100644
index 0000000..7d17024
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_3.C
@@ -0,0 +1,78 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fno-omit-frame-pointer" } */
+
+/* Invoke X (P##n) for n in [0, 7]. */
+#define REPEAT8(X, P) \
+ X (P##0) X (P##1) X (P##2) X (P##3) X (P##4) X (P##5) X (P##6) X (P##7)
+
+/* Invoke X (n) for all octal n in [0, 39]. */
+#define REPEAT40(X) \
+ REPEAT8 (X, 0) REPEAT8 (X, 1) REPEAT8 (X, 2) REPEAT8 (X, 3) REPEAT8 (X, 4)
+
+volatile int testi, sink;
+
+/* Take 2 stack arguments and throw to f3. */
+void __attribute__ ((weak))
+f1 (int x[40][100], int *y, int z1, int z2, int z3, int z4,
+ int z5, int z6, int z7, int z8)
+{
+ /* A wild write to x and y. */
+ sink = z1;
+ sink = z2;
+ sink = z3;
+ sink = z4;
+ sink = z5;
+ sink = z6;
+ sink = z7;
+ sink = z8;
+ asm volatile ("" ::: "memory");
+ if (y[testi] == x[testi][testi])
+ throw 100;
+}
+
+/* Expect vector work to be done, with spilling of vector registers. */
+void __attribute__ ((weak))
+f2 (int x[40][100], int *y)
+{
+ /* Try to force some spilling. */
+#define DECLARE(N) int y##N = y[N];
+ REPEAT40 (DECLARE);
+ for (int j = 0; j < 20; ++j)
+ {
+ f1 (x, y, 1, 2, 3, 4, 5, 6, 7, 8);
+#pragma omp simd
+ for (int i = 0; i < 100; ++i)
+ {
+#define INC(N) x[N][i] += y##N;
+ REPEAT40 (INC);
+ }
+ }
+}
+
+/* Catch an exception thrown from f1, via f2. */
+void __attribute__ ((weak))
+f3 (int x[40][100], int *y, int *z)
+{
+ volatile int extra = 111;
+ try
+ {
+ f2 (x, y);
+ }
+ catch (int val)
+ {
+ *z = val + extra;
+ }
+}
+
+static int x[40][100];
+static int y[40];
+static int z;
+
+int
+main (void)
+{
+ f3 (x, y, &z);
+ if (z != 211)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_4.C b/gcc/testsuite/g++.target/aarch64/sve/catch_4.C
new file mode 100644
index 0000000..07841acf6
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_4.C
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fomit-frame-pointer" } */
+
+#include "catch_3.C"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_5.C b/gcc/testsuite/g++.target/aarch64/sve/catch_5.C
new file mode 100644
index 0000000..0eee6f0
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_5.C
@@ -0,0 +1,81 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fno-omit-frame-pointer" } */
+
+/* Invoke X (P##n) for n in [0, 7]. */
+#define REPEAT8(X, P) \
+ X (P##0) X (P##1) X (P##2) X (P##3) X (P##4) X (P##5) X (P##6) X (P##7)
+
+/* Invoke X (n) for all octal n in [0, 39]. */
+#define REPEAT40(X) \
+ REPEAT8 (X, 0) REPEAT8 (X, 1) REPEAT8 (X, 2) REPEAT8 (X, 3) REPEAT8 (X, 4)
+
+volatile int testi, sink;
+volatile void *ptr;
+
+/* Take 2 stack arguments and throw to f3. */
+void __attribute__ ((weak))
+f1 (int x[40][100], int *y, int z1, int z2, int z3, int z4,
+ int z5, int z6, int z7, int z8)
+{
+ /* A wild write to x and y. */
+ sink = z1;
+ sink = z2;
+ sink = z3;
+ sink = z4;
+ sink = z5;
+ sink = z6;
+ sink = z7;
+ sink = z8;
+ asm volatile ("" ::: "memory");
+ if (y[testi] == x[testi][testi])
+ throw 100;
+}
+
+/* Expect vector work to be done, with spilling of vector registers. */
+void __attribute__ ((weak))
+f2 (int x[40][100], int *y)
+{
+ /* Create a true variable-sized frame. */
+ ptr = __builtin_alloca (testi + 40);
+ /* Try to force some spilling. */
+#define DECLARE(N) int y##N = y[N];
+ REPEAT40 (DECLARE);
+ for (int j = 0; j < 20; ++j)
+ {
+ f1 (x, y, 1, 2, 3, 4, 5, 6, 7, 8);
+#pragma omp simd
+ for (int i = 0; i < 100; ++i)
+ {
+#define INC(N) x[N][i] += y##N;
+ REPEAT40 (INC);
+ }
+ }
+}
+
+/* Catch an exception thrown from f1, via f2. */
+void __attribute__ ((weak))
+f3 (int x[40][100], int *y, int *z)
+{
+ volatile int extra = 111;
+ try
+ {
+ f2 (x, y);
+ }
+ catch (int val)
+ {
+ *z = val + extra;
+ }
+}
+
+static int x[40][100];
+static int y[40];
+static int z;
+
+int
+main (void)
+{
+ f3 (x, y, &z);
+ if (z != 211)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/catch_6.C b/gcc/testsuite/g++.target/aarch64/sve/catch_6.C
new file mode 100644
index 0000000..45f204a
--- /dev/null
+++ b/gcc/testsuite/g++.target/aarch64/sve/catch_6.C
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O3 -fopenmp-simd -fomit-frame-pointer" } */
+
+#include "catch_5.C"