attribs: Restrict decl_attributes DECL_FUNCTION_SPECIFIC_TARGET changes to targets that care about target attributes/pragmas [PR105234]
Commit Message
Hi!
The following code is rejected e.g. on mips64el-linux (but I think many
other targets which don't support target attribute or pragma).
The problem is that the change to decl_attributes below is done
unconditionally and with just #pragma GCC push_options/pop_options pair
we have target_option_default_node NULL, but after popping options
target_option_current_node becomes non-NULL and this decl_attribute
spot fills in DECL_FUNCTION_SPECIFIC_TARGET of a subset of a functions.
Those appearing before push_options/pop_options will have it NULL and
as target_option_default_node is also NULL on those targets, the default
can_inline_p will refuse to inline any functions defined with NULL
DECL_FUNCTION_SPECIFIC_TARGET into any function with non-NULL
DECL_FUNCTION_SPECIFIC_TARGET (even when nothing in the options really
changed).
The following patch restricts that snippet to targets that care (initialize
target_option_default_node to non-NULL to the command line options early)
which include all targets that actually implement target attribute and/or
pragma.
Bootstrapped/regtested on x86_64-linux and i686-linux, tested on the
testcase with cross-compiler to mips64el-linux, ok for trunk?
2022-04-13 Jakub Jelinek <jakub@redhat.com>
PR target/105234
* attribs.cc (decl_attributes): Don't set
DECL_FUNCTION_SPECIFIC_TARGET if target_option_default_node is
NULL.
* gcc.c-torture/compile/pr105234.c: New test.
Jakub
Comments
On Wed, 13 Apr 2022, Jakub Jelinek wrote:
> Hi!
>
> The following code is rejected e.g. on mips64el-linux (but I think many
> other targets which don't support target attribute or pragma).
> The problem is that the change to decl_attributes below is done
> unconditionally and with just #pragma GCC push_options/pop_options pair
> we have target_option_default_node NULL, but after popping options
> target_option_current_node becomes non-NULL and this decl_attribute
> spot fills in DECL_FUNCTION_SPECIFIC_TARGET of a subset of a functions.
> Those appearing before push_options/pop_options will have it NULL and
> as target_option_default_node is also NULL on those targets, the default
> can_inline_p will refuse to inline any functions defined with NULL
> DECL_FUNCTION_SPECIFIC_TARGET into any function with non-NULL
> DECL_FUNCTION_SPECIFIC_TARGET (even when nothing in the options really
> changed).
>
> The following patch restricts that snippet to targets that care (initialize
> target_option_default_node to non-NULL to the command line options early)
> which include all targets that actually implement target attribute and/or
> pragma.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, tested on the
> testcase with cross-compiler to mips64el-linux, ok for trunk?
OK.
Thanks,
Richard.
> 2022-04-13 Jakub Jelinek <jakub@redhat.com>
>
> PR target/105234
> * attribs.cc (decl_attributes): Don't set
> DECL_FUNCTION_SPECIFIC_TARGET if target_option_default_node is
> NULL.
>
> * gcc.c-torture/compile/pr105234.c: New test.
>
> --- gcc/attribs.cc.jj 2022-02-04 14:36:53.947620076 +0100
> +++ gcc/attribs.cc 2022-04-12 12:52:36.630967329 +0200
> @@ -636,15 +636,20 @@ decl_attributes (tree *node, tree attrib
> && !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
> {
> DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
> - tree cur_tree
> - = build_target_option_node (&global_options, &global_options_set);
> - tree old_tree = DECL_FUNCTION_SPECIFIC_TARGET (*node);
> - if (!old_tree)
> - old_tree = target_option_default_node;
> - /* The changes on optimization options can cause the changes in
> - target options, update it accordingly if it's changed. */
> - if (old_tree != cur_tree)
> - DECL_FUNCTION_SPECIFIC_TARGET (*node) = cur_tree;
> + /* Don't set DECL_FUNCTION_SPECIFIC_TARGET for targets that don't
> + support #pragma GCC target or target attribute. */
> + if (target_option_default_node)
> + {
> + tree cur_tree
> + = build_target_option_node (&global_options, &global_options_set);
> + tree old_tree = DECL_FUNCTION_SPECIFIC_TARGET (*node);
> + if (!old_tree)
> + old_tree = target_option_default_node;
> + /* The changes on optimization options can cause the changes in
> + target options, update it accordingly if it's changed. */
> + if (old_tree != cur_tree)
> + DECL_FUNCTION_SPECIFIC_TARGET (*node) = cur_tree;
> + }
> }
>
> /* If this is a function and the user used #pragma GCC target, add the
> --- gcc/testsuite/gcc.c-torture/compile/pr105234.c.jj 2022-04-12 13:07:55.021142913 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr105234.c 2022-04-12 13:07:43.596302442 +0200
> @@ -0,0 +1,14 @@
> +/* PR target/105234 */
> +/* { dg-do compile } */
> +
> +static inline __attribute__((always_inline)) int foo (int x) { return x + 1; }
> +#pragma GCC push_options
> +static inline __attribute__((always_inline)) int bar (int x) { return x + 2; }
> +#pragma GCC pop_options
> +static inline __attribute__((always_inline)) int baz (int x) { return x + 3; }
> +
> +int
> +qux (void)
> +{
> + return foo (bar (baz (42)));
> +}
>
> Jakub
>
>
@@ -636,15 +636,20 @@ decl_attributes (tree *node, tree attrib
&& !DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node))
{
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node) = optimization_current_node;
- tree cur_tree
- = build_target_option_node (&global_options, &global_options_set);
- tree old_tree = DECL_FUNCTION_SPECIFIC_TARGET (*node);
- if (!old_tree)
- old_tree = target_option_default_node;
- /* The changes on optimization options can cause the changes in
- target options, update it accordingly if it's changed. */
- if (old_tree != cur_tree)
- DECL_FUNCTION_SPECIFIC_TARGET (*node) = cur_tree;
+ /* Don't set DECL_FUNCTION_SPECIFIC_TARGET for targets that don't
+ support #pragma GCC target or target attribute. */
+ if (target_option_default_node)
+ {
+ tree cur_tree
+ = build_target_option_node (&global_options, &global_options_set);
+ tree old_tree = DECL_FUNCTION_SPECIFIC_TARGET (*node);
+ if (!old_tree)
+ old_tree = target_option_default_node;
+ /* The changes on optimization options can cause the changes in
+ target options, update it accordingly if it's changed. */
+ if (old_tree != cur_tree)
+ DECL_FUNCTION_SPECIFIC_TARGET (*node) = cur_tree;
+ }
}
/* If this is a function and the user used #pragma GCC target, add the
@@ -0,0 +1,14 @@
+/* PR target/105234 */
+/* { dg-do compile } */
+
+static inline __attribute__((always_inline)) int foo (int x) { return x + 1; }
+#pragma GCC push_options
+static inline __attribute__((always_inline)) int bar (int x) { return x + 2; }
+#pragma GCC pop_options
+static inline __attribute__((always_inline)) int baz (int x) { return x + 3; }
+
+int
+qux (void)
+{
+ return foo (bar (baz (42)));
+}