aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2014-02-06 11:54:20 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2014-02-06 11:54:20 +0100
commit251901a027bfefffce90ca3d0776c677879d7124 (patch)
treeb4c321fa215aaa59ff62803b0e35d3ac473f9b33
parent79b49b879d3d96c1c7761b2d114dcdfaf7ceaad0 (diff)
downloadgcc-251901a027bfefffce90ca3d0776c677879d7124.zip
gcc-251901a027bfefffce90ca3d0776c677879d7124.tar.gz
gcc-251901a027bfefffce90ca3d0776c677879d7124.tar.bz2
re PR target/60062 (wrong code (for code with the optimize attribute) at -O1 and above on x86_64-linux-gnu in 32-bit mode)
PR target/60062 * tree.h (opts_for_fn): New inline function. (opt_for_fn): Define. * config/i386/i386.c (ix86_function_regparm): Use opt_for_fn (decl, optimize) instead of optimize. * gcc.c-torture/execute/pr60062.c: New test. * gcc.c-torture/execute/pr60072.c: New test. From-SVN: r207549
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/config/i386/i386.c7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60062.c25
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr60072.c16
-rw-r--r--gcc/tree.h14
6 files changed, 75 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 078192d..7028dd6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2014-02-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/60062
+ * tree.h (opts_for_fn): New inline function.
+ (opt_for_fn): Define.
+ * config/i386/i386.c (ix86_function_regparm): Use
+ opt_for_fn (decl, optimize) instead of optimize.
+
2014-02-06 Marcus Shawcroft <marcus.shawcroft@arm.com>
* config/aarch64/aarch64.c (aarch64_classify_symbol): Fix logic
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 58f36e0..abe05aa 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5608,7 +5608,12 @@ ix86_function_regparm (const_tree type, const_tree decl)
/* Use register calling convention for local functions when possible. */
if (decl
&& TREE_CODE (decl) == FUNCTION_DECL
- && optimize
+ /* Caller and callee must agree on the calling convention, so
+ checking here just optimize means that with
+ __attribute__((optimize (...))) caller could use regparm convention
+ and callee not, or vice versa. Instead look at whether the callee
+ is optimized or not. */
+ && opt_for_fn (decl, optimize)
&& !(profile_flag && !flag_fentry))
{
/* FIXME: remove this CONST_CAST when cgraph.[ch] is constified. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a91c110..552b591 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2014-02-06 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/60062
+ * gcc.c-torture/execute/pr60062.c: New test.
+ * gcc.c-torture/execute/pr60072.c: New test.
+
2014-02-06 Ian Bolton <ian.bolton@arm.com>
* gcc.dg/tree-ssa/pr59597.c: Make called function static
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60062.c b/gcc/testsuite/gcc.c-torture/execute/pr60062.c
new file mode 100644
index 0000000..62973d4
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60062.c
@@ -0,0 +1,25 @@
+/* PR target/60062 */
+
+int a;
+
+static void
+foo (const char *p1, int p2)
+{
+ if (__builtin_strcmp (p1, "hello") != 0)
+ __builtin_abort ();
+}
+
+static void
+bar (const char *p1)
+{
+ if (__builtin_strcmp (p1, "hello") != 0)
+ __builtin_abort ();
+}
+
+__attribute__((optimize (0))) int
+main ()
+{
+ foo ("hello", a);
+ bar ("hello");
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr60072.c b/gcc/testsuite/gcc.c-torture/execute/pr60072.c
new file mode 100644
index 0000000..566874d
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr60072.c
@@ -0,0 +1,16 @@
+/* PR target/60072 */
+
+int c = 1;
+
+__attribute__ ((optimize (1)))
+static int *foo (int *p)
+{
+ return p;
+}
+
+int
+main ()
+{
+ *foo (&c) = 2;
+ return c - 2;
+}
diff --git a/gcc/tree.h b/gcc/tree.h
index e918ec5..0dc8d0d 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4470,6 +4470,20 @@ may_be_aliased (const_tree var)
|| TREE_ADDRESSABLE (var)));
}
+/* Return pointer to optimization flags of FNDECL. */
+static inline struct cl_optimization *
+opts_for_fn (const_tree fndecl)
+{
+ tree fn_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl);
+ if (fn_opts == NULL_TREE)
+ fn_opts = optimization_default_node;
+ return TREE_OPTIMIZATION (fn_opts);
+}
+
+/* opt flag for function FNDECL, e.g. opts_for_fn (fndecl, optimize) is
+ the optimization level of function fndecl. */
+#define opt_for_fn(fndecl, opt) (opts_for_fn (fndecl)->x_##opt)
+
/* For anonymous aggregate types, we need some sort of name to
hold on to. In practice, this should not appear, but it should
not be harmful if it does. */