diff mbox series

Reset proper type on vector types (PR middle-end/88587).

Message ID 0d2f9afa-b0fb-b81b-aba4-1f7f1faa5f35@suse.cz
State New
Headers show
Series Reset proper type on vector types (PR middle-end/88587). | expand

Commit Message

Martin Liška Jan. 16, 2019, 9:20 a.m. UTC
Hi.

The patch is about resetting TYPE_MODE of vector types. This is problematic
when an inlining among different ISAs happen. Then we end up with a different
mode than when it's expected from debug info.

When creating a new function decl in target_clones, we must valid_attribute_p early
so that the declaration has a proper cl_target_.. node and so that inliner can
fix modes.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

gcc/ChangeLog:

2019-01-16  Martin Liska  <mliska@suse.cz>
	    Richard Biener  <rguenther@suse.de>

	PR middle-end/88587
	* cgraph.h (create_version_clone_with_body): Add new argument
	with attributes.
	* cgraphclones.c (cgraph_node::create_version_clone): Add
	DECL_ATTRIBUTES to a newly created decl.  And call
	valid_attribute_p so that proper cl_target_optimization_node
	is set for the newly created declaration.
	* multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
	for declaration.
	(expand_target_clones): Do not call valid_attribute_p, it must
	be already done.
	* tree-inline.c (copy_decl_for_dup_finish): Reset mode for
	vector types.

gcc/testsuite/ChangeLog:

2019-01-16  Martin Liska  <mliska@suse.cz>

	PR middle-end/88587
	* g++.target/i386/pr88587.C: New test.
	* gcc.target/i386/mvc13.c: New test.
---
 gcc/cgraph.h                            |  7 +++++-
 gcc/cgraphclones.c                      | 18 +++++++++++++-
 gcc/multiple_target.c                   | 32 ++++++++-----------------
 gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
 gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
 gcc/tree-inline.c                       |  4 ++++
 6 files changed, 61 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
 create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c

Comments

Martin Liška Jan. 16, 2019, 9:26 a.m. UTC | #1
And there's patch with Richi's validation check that he provided.
It fails on following 2 tests in test-suite:

$ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.target/i386/pr68674.c
DECL_MODE BLK vs TYPE_MODE V8SI [V8SI]: a
...

$ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.target/i386/pr80583.c -c
DECL_MODE BLK vs TYPE_MODE V8SI [V8SI]: a
...

In both cases we access a global variable from a function with a different target
attributes. I guess Honza has seen that in inliner.

What to do with these, can it be potentially dangerous?

Thanks,
Martin
From bf22210f96a2ead9d50e351102f095aadf9d879f Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Wed, 16 Jan 2019 09:05:21 +0100
Subject: [PATCH] Sanitize about VECTOR_TYPEs.

---
 gcc/tree-cfg.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index 6041f4208b0..fc1dd36fbb7 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -5108,6 +5108,17 @@ verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data)
 {
   hash_set<void *> *visited = (hash_set<void *> *) data;
 
+  if (DECL_P (*tp)
+      && VECTOR_TYPE_P (TREE_TYPE (*tp))
+      && DECL_MODE (*tp) != TYPE_MODE (TREE_TYPE (*tp)))
+    {
+      fprintf (stderr, "DECL_MODE %s vs TYPE_MODE %s [%s]: ",
+              mode_name[DECL_MODE (*tp)],
+              mode_name[TYPE_MODE (TREE_TYPE (*tp))],
+              mode_name[TYPE_MODE_RAW (TREE_TYPE (*tp))]);
+      print_generic_expr (stderr, *tp);
+      fprintf (stderr, "\n");
+    }
   if (tree_node_can_be_shared (*tp))
     {
       *walk_subtrees = false;
Richard Biener Jan. 16, 2019, 11:50 a.m. UTC | #2
On Wed, Jan 16, 2019 at 10:26 AM Martin Liška <mliska@suse.cz> wrote:
>
> And there's patch with Richi's validation check that he provided.
> It fails on following 2 tests in test-suite:
>
> $ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.target/i386/pr68674.c
> DECL_MODE BLK vs TYPE_MODE V8SI [V8SI]: a
> ...
>
> $ ./xgcc -B. /home/marxin/Programming/gcc/gcc/testsuite/gcc.target/i386/pr80583.c -c
> DECL_MODE BLK vs TYPE_MODE V8SI [V8SI]: a
> ...
>
> In both cases we access a global variable from a function with a different target
> attributes. I guess Honza has seen that in inliner.
>
> What to do with these, can it be potentially dangerous?

I guess so.  There's not much we can do about this other than making
DECL_MODE dynamic the same way as TYPE_MODE.  I still believe
this is the wrong direction and instead RTL expansion should properly
adjust DECL_RTL and generally on GIMPLE we shouldn't need to
commit to modes early at all...

[but then we eventually want to expose more ABI details to GIMPLE]

Richard.

>
> Thanks,
> Martin
>
Jakub Jelinek Jan. 16, 2019, 11:59 a.m. UTC | #3
On Wed, Jan 16, 2019 at 12:50:23PM +0100, Richard Biener wrote:
> I guess so.  There's not much we can do about this other than making
> DECL_MODE dynamic the same way as TYPE_MODE.  I still believe
> this is the wrong direction and instead RTL expansion should properly
> adjust DECL_RTL and generally on GIMPLE we shouldn't need to
> commit to modes early at all...

Are there cases where DECL_MODE (decl) should not be equal to
TYPE_MODE (TREE_TYPE (decl))?  Is that for structs with flexible array
members where the initializer is filling up the flexible array member, or
something different?

E.g. in expand_debug* it shouldn't be hard to use TYPE_MODE if
VECTOR_TYPE_P (TREE_TYPE (decl)), but there are many other uses of
DECL_MODE.

	Jakub
Richard Biener Jan. 16, 2019, 12:01 p.m. UTC | #4
On Wed, Jan 16, 2019 at 12:59 PM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, Jan 16, 2019 at 12:50:23PM +0100, Richard Biener wrote:
> > I guess so.  There's not much we can do about this other than making
> > DECL_MODE dynamic the same way as TYPE_MODE.  I still believe
> > this is the wrong direction and instead RTL expansion should properly
> > adjust DECL_RTL and generally on GIMPLE we shouldn't need to
> > commit to modes early at all...
>
> Are there cases where DECL_MODE (decl) should not be equal to
> TYPE_MODE (TREE_TYPE (decl))?  Is that for structs with flexible array
> members where the initializer is filling up the flexible array member, or
> something different?

ISTR seeing the most differences in FIELD_DECL modes (bitfields?
packed fields getting BLKmode but types not being packed/etc.?)

> E.g. in expand_debug* it shouldn't be hard to use TYPE_MODE if
> VECTOR_TYPE_P (TREE_TYPE (decl)), but there are many other uses of
> DECL_MODE.
>
>         Jakub
Richard Biener Jan. 16, 2019, 12:06 p.m. UTC | #5
On Wed, Jan 16, 2019 at 10:20 AM Martin Liška <mliska@suse.cz> wrote:
>
> Hi.
>
> The patch is about resetting TYPE_MODE of vector types. This is problematic
> when an inlining among different ISAs happen. Then we end up with a different
> mode than when it's expected from debug info.
>
> When creating a new function decl in target_clones, we must valid_attribute_p early
> so that the declaration has a proper cl_target_.. node and so that inliner can
> fix modes.
>
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
>
> Ready to be installed?

I don't like the new failure mode too much.  It looks like
create_version_clone_with_body
can fail so why not simply return NULL when
targetm.target_option.valid_attribute_p
returns false and handle that case in multi-versioning?

That is,

+  return !seen_error ();

that looks very wrong to me.

Richard.

> Thanks,
> Martin
>
> gcc/ChangeLog:
>
> 2019-01-16  Martin Liska  <mliska@suse.cz>
>             Richard Biener  <rguenther@suse.de>
>
>         PR middle-end/88587
>         * cgraph.h (create_version_clone_with_body): Add new argument
>         with attributes.
>         * cgraphclones.c (cgraph_node::create_version_clone): Add
>         DECL_ATTRIBUTES to a newly created decl.  And call
>         valid_attribute_p so that proper cl_target_optimization_node
>         is set for the newly created declaration.
>         * multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
>         for declaration.
>         (expand_target_clones): Do not call valid_attribute_p, it must
>         be already done.
>         * tree-inline.c (copy_decl_for_dup_finish): Reset mode for
>         vector types.
>
> gcc/testsuite/ChangeLog:
>
> 2019-01-16  Martin Liska  <mliska@suse.cz>
>
>         PR middle-end/88587
>         * g++.target/i386/pr88587.C: New test.
>         * gcc.target/i386/mvc13.c: New test.
> ---
>  gcc/cgraph.h                            |  7 +++++-
>  gcc/cgraphclones.c                      | 18 +++++++++++++-
>  gcc/multiple_target.c                   | 32 ++++++++-----------------
>  gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
>  gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
>  gcc/tree-inline.c                       |  4 ++++
>  6 files changed, 61 insertions(+), 24 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
>  create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c
>
>
Martin Liška Jan. 17, 2019, 11:21 a.m. UTC | #6
On 1/16/19 1:06 PM, Richard Biener wrote:
> On Wed, Jan 16, 2019 at 10:20 AM Martin Liška <mliska@suse.cz> wrote:
>>
>> Hi.
>>
>> The patch is about resetting TYPE_MODE of vector types. This is problematic
>> when an inlining among different ISAs happen. Then we end up with a different
>> mode than when it's expected from debug info.
>>
>> When creating a new function decl in target_clones, we must valid_attribute_p early
>> so that the declaration has a proper cl_target_.. node and so that inliner can
>> fix modes.
>>
>> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
>>
>> Ready to be installed?
> 
> I don't like the new failure mode too much.  It looks like
> create_version_clone_with_body
> can fail so why not simply return NULL when
> targetm.target_option.valid_attribute_p
> returns false and handle that case in multi-versioning?
> 
> That is,
> 
> +  return !seen_error ();
> 
> that looks very wrong to me.

Yep, update patch should be better.

Patch can bootstrap on x86_64-linux-gnu and survives regression tests.

Ready to be installed?
Thanks,
Martin

> 
> Richard.
> 
>> Thanks,
>> Martin
>>
>> gcc/ChangeLog:
>>
>> 2019-01-16  Martin Liska  <mliska@suse.cz>
>>             Richard Biener  <rguenther@suse.de>
>>
>>         PR middle-end/88587
>>         * cgraph.h (create_version_clone_with_body): Add new argument
>>         with attributes.
>>         * cgraphclones.c (cgraph_node::create_version_clone): Add
>>         DECL_ATTRIBUTES to a newly created decl.  And call
>>         valid_attribute_p so that proper cl_target_optimization_node
>>         is set for the newly created declaration.
>>         * multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
>>         for declaration.
>>         (expand_target_clones): Do not call valid_attribute_p, it must
>>         be already done.
>>         * tree-inline.c (copy_decl_for_dup_finish): Reset mode for
>>         vector types.
>>
>> gcc/testsuite/ChangeLog:
>>
>> 2019-01-16  Martin Liska  <mliska@suse.cz>
>>
>>         PR middle-end/88587
>>         * g++.target/i386/pr88587.C: New test.
>>         * gcc.target/i386/mvc13.c: New test.
>> ---
>>  gcc/cgraph.h                            |  7 +++++-
>>  gcc/cgraphclones.c                      | 18 +++++++++++++-
>>  gcc/multiple_target.c                   | 32 ++++++++-----------------
>>  gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
>>  gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
>>  gcc/tree-inline.c                       |  4 ++++
>>  6 files changed, 61 insertions(+), 24 deletions(-)
>>  create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
>>  create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c
>>
>>
From 3deeb24418fa5078a407ff6fee6d9d958b9ea869 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Wed, 16 Jan 2019 09:05:02 +0100
Subject: [PATCH] Reset proper type on vector types (PR middle-end/88587).

gcc/ChangeLog:

2019-01-16  Martin Liska  <mliska@suse.cz>
	    Richard Biener  <rguenther@suse.de>

	PR middle-end/88587
	* cgraph.h (create_version_clone_with_body): Add new argument
	with attributes.
	* cgraphclones.c (cgraph_node::create_version_clone): Add
	DECL_ATTRIBUTES to a newly created decl.  And call
	valid_attribute_p so that proper cl_target_optimization_node
	is set for the newly created declaration.
	* multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
	for declaration.
	(expand_target_clones): Do not call valid_attribute_p, it must
	be already done.
	* tree-inline.c (copy_decl_for_dup_finish): Reset mode for
	vector types.

gcc/testsuite/ChangeLog:

2019-01-16  Martin Liska  <mliska@suse.cz>

	PR middle-end/88587
	* g++.target/i386/pr88587.C: New test.
	* gcc.target/i386/mvc13.c: New test.
---
 gcc/cgraph.h                            |  7 ++++-
 gcc/cgraphclones.c                      | 20 +++++++++++++-
 gcc/multiple_target.c                   | 36 ++++++++++---------------
 gcc/testsuite/g++.target/i386/pr88587.C | 15 +++++++++++
 gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
 gcc/tree-inline.c                       |  4 +++
 6 files changed, 67 insertions(+), 24 deletions(-)
 create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
 create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c016da3875c..bb231833328 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1019,12 +1019,17 @@ public:
      If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
      If non_NULL NEW_ENTRY determine new entry BB of the clone.
 
+     If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
+     add the attributes to DECL_ATTRIBUTES.  And call valid_attribute_p
+     that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
+     of the declaration.
+
      Return the new version's cgraph node.  */
   cgraph_node *create_version_clone_with_body
     (vec<cgraph_edge *> redirect_callers,
      vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
      bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
-     const char *clone_name);
+     const char *clone_name, tree target_attributes = NULL_TREE);
 
   /* Insert a new cgraph_function_version_info node into cgraph_fnver_htab
      corresponding to cgraph_node.  */
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 4688de91cfe..15f7e119d18 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -1012,6 +1012,11 @@ cgraph_node::create_version_clone (tree new_decl,
    If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
    If non_NULL NEW_ENTRY determine new entry BB of the clone.
 
+   If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
+   add the attributes to DECL_ATTRIBUTES.  And call valid_attribute_p
+   that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
+   of the declaration.
+
    Return the new version's cgraph node.  */
 
 cgraph_node *
@@ -1019,7 +1024,7 @@ cgraph_node::create_version_clone_with_body
   (vec<cgraph_edge *> redirect_callers,
    vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
    bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
-   const char *suffix)
+   const char *suffix, tree target_attributes)
 {
   tree old_decl = decl;
   cgraph_node *new_version_node = NULL;
@@ -1044,6 +1049,19 @@ cgraph_node::create_version_clone_with_body
 
   DECL_VIRTUAL_P (new_decl) = 0;
 
+  if (target_attributes)
+    {
+      DECL_ATTRIBUTES (new_decl) = target_attributes;
+
+      location_t saved_loc = input_location;
+      tree v = TREE_VALUE (target_attributes);
+      input_location = DECL_SOURCE_LOCATION (new_decl);
+      bool r = targetm.target_option.valid_attribute_p (new_decl, NULL, v, 0);
+      input_location = saved_loc;
+      if (!r)
+	return NULL;
+    }
+
   /* When the old decl was a con-/destructor make sure the clone isn't.  */
   DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
   DECL_STATIC_DESTRUCTOR (new_decl) = 0;
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 589d059424a..6126f42d7bf 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -294,7 +294,8 @@ create_new_asm_name (char *old_asm_name, char *new_asm_name)
 /*  Creates target clone of NODE.  */
 
 static cgraph_node *
-create_target_clone (cgraph_node *node, bool definition, char *name)
+create_target_clone (cgraph_node *node, bool definition, char *name,
+		     tree attributes)
 {
   cgraph_node *new_node;
 
@@ -303,13 +304,16 @@ create_target_clone (cgraph_node *node, bool definition, char *name)
       new_node = node->create_version_clone_with_body (vNULL, NULL,
     						       NULL, false,
 						       NULL, NULL,
-						       name);
+						       name, attributes);
+      if (new_node == NULL)
+	return NULL;
       new_node->force_output = true;
     }
   else
     {
       tree new_decl = copy_node (node->decl);
       new_node = cgraph_node::get_create (new_decl);
+      DECL_ATTRIBUTES (new_decl) = attributes;
       /* Generate a new name for the new version.  */
       symtab->change_decl_assembler_name (new_node->decl,
 					  clone_function_name_numbered (
@@ -400,22 +404,16 @@ expand_target_clones (struct cgraph_node *node, bool definition)
 
       create_new_asm_name (attr, suffix);
       /* Create new target clone.  */
-      cgraph_node *new_node = create_target_clone (node, definition, suffix);
-      new_node->local.local = false;
-      XDELETEVEC (suffix);
-
-      /* Set new attribute for the clone.  */
       tree attributes = make_attribute ("target", attr,
-					DECL_ATTRIBUTES (new_node->decl));
-      DECL_ATTRIBUTES (new_node->decl) = attributes;
-      location_t saved_loc = input_location;
-      input_location = DECL_SOURCE_LOCATION (node->decl);
-      if (!targetm.target_option.valid_attribute_p (new_node->decl, NULL,
-						    TREE_VALUE (attributes),
-						    0))
+					DECL_ATTRIBUTES (node->decl));
+
+      cgraph_node *new_node = create_target_clone (node, definition, suffix,
+						   attributes);
+      if (new_node == NULL)
 	return false;
+      new_node->local.local = false;
+      XDELETEVEC (suffix);
 
-      input_location = saved_loc;
       decl2_v = new_node->function_version ();
       if (decl2_v != NULL)
         continue;
@@ -442,13 +440,7 @@ expand_target_clones (struct cgraph_node *node, bool definition)
 				    DECL_ATTRIBUTES (node->decl));
   DECL_ATTRIBUTES (node->decl) = attributes;
   node->local.local = false;
-  location_t saved_loc = input_location;
-  input_location = DECL_SOURCE_LOCATION (node->decl);
-  bool ret
-    = targetm.target_option.valid_attribute_p (node->decl, NULL,
-					       TREE_VALUE (attributes), 0);
-  input_location = saved_loc;
-  return ret;
+  return true;
 }
 
 /* When NODE is a target clone, consider all callees and redirect
diff --git a/gcc/testsuite/g++.target/i386/pr88587.C b/gcc/testsuite/g++.target/i386/pr88587.C
new file mode 100644
index 00000000000..6808ab68cbb
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr88587.C
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O -m32 -g -mno-sse -Wno-attributes" } */
+
+__attribute__((target("default"),always_inline))
+void a()
+{
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
+
+__attribute__((target("sse2"))) void a2()
+{
+  a ();
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
diff --git a/gcc/testsuite/gcc.target/i386/mvc13.c b/gcc/testsuite/gcc.target/i386/mvc13.c
new file mode 100644
index 00000000000..9e31ef7c4da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mvc13.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O -m32 -g -mno-sse" } */
+
+__attribute__((target_clones("default,sse2")))
+void a()
+{
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 88620770212..1c2766d4799 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -5479,6 +5479,10 @@ copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy)
   if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL)
       && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
     SET_DECL_RTL (copy, 0);
+  /* For vector typed decls make sure to update DECL_MODE according
+     to the new function context.  */
+  if (VECTOR_TYPE_P (TREE_TYPE (copy)))
+    SET_DECL_MODE (copy, TYPE_MODE (TREE_TYPE (copy)));
 
   /* These args would always appear unused, if not for this.  */
   TREE_USED (copy) = 1;
Richard Biener Jan. 17, 2019, 12:50 p.m. UTC | #7
On Thu, Jan 17, 2019 at 12:21 PM Martin Liška <mliska@suse.cz> wrote:
>
> On 1/16/19 1:06 PM, Richard Biener wrote:
> > On Wed, Jan 16, 2019 at 10:20 AM Martin Liška <mliska@suse.cz> wrote:
> >>
> >> Hi.
> >>
> >> The patch is about resetting TYPE_MODE of vector types. This is problematic
> >> when an inlining among different ISAs happen. Then we end up with a different
> >> mode than when it's expected from debug info.
> >>
> >> When creating a new function decl in target_clones, we must valid_attribute_p early
> >> so that the declaration has a proper cl_target_.. node and so that inliner can
> >> fix modes.
> >>
> >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> >>
> >> Ready to be installed?
> >
> > I don't like the new failure mode too much.  It looks like
> > create_version_clone_with_body
> > can fail so why not simply return NULL when
> > targetm.target_option.valid_attribute_p
> > returns false and handle that case in multi-versioning?
> >
> > That is,
> >
> > +  return !seen_error ();
> >
> > that looks very wrong to me.
>
> Yep, update patch should be better.
>
> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
>
> Ready to be installed?

OK.

Thanks,
Richard.

> Thanks,
> Martin
>
> >
> > Richard.
> >
> >> Thanks,
> >> Martin
> >>
> >> gcc/ChangeLog:
> >>
> >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> >>             Richard Biener  <rguenther@suse.de>
> >>
> >>         PR middle-end/88587
> >>         * cgraph.h (create_version_clone_with_body): Add new argument
> >>         with attributes.
> >>         * cgraphclones.c (cgraph_node::create_version_clone): Add
> >>         DECL_ATTRIBUTES to a newly created decl.  And call
> >>         valid_attribute_p so that proper cl_target_optimization_node
> >>         is set for the newly created declaration.
> >>         * multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
> >>         for declaration.
> >>         (expand_target_clones): Do not call valid_attribute_p, it must
> >>         be already done.
> >>         * tree-inline.c (copy_decl_for_dup_finish): Reset mode for
> >>         vector types.
> >>
> >> gcc/testsuite/ChangeLog:
> >>
> >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> >>
> >>         PR middle-end/88587
> >>         * g++.target/i386/pr88587.C: New test.
> >>         * gcc.target/i386/mvc13.c: New test.
> >> ---
> >>  gcc/cgraph.h                            |  7 +++++-
> >>  gcc/cgraphclones.c                      | 18 +++++++++++++-
> >>  gcc/multiple_target.c                   | 32 ++++++++-----------------
> >>  gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
> >>  gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
> >>  gcc/tree-inline.c                       |  4 ++++
> >>  6 files changed, 61 insertions(+), 24 deletions(-)
> >>  create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
> >>  create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c
> >>
> >>
>
H.J. Lu Jan. 18, 2019, 2:25 p.m. UTC | #8
On Thu, Jan 17, 2019 at 4:51 AM Richard Biener
<richard.guenther@gmail.com> wrote:
>
> On Thu, Jan 17, 2019 at 12:21 PM Martin Liška <mliska@suse.cz> wrote:
> >
> > On 1/16/19 1:06 PM, Richard Biener wrote:
> > > On Wed, Jan 16, 2019 at 10:20 AM Martin Liška <mliska@suse.cz> wrote:
> > >>
> > >> Hi.
> > >>
> > >> The patch is about resetting TYPE_MODE of vector types. This is problematic
> > >> when an inlining among different ISAs happen. Then we end up with a different
> > >> mode than when it's expected from debug info.
> > >>
> > >> When creating a new function decl in target_clones, we must valid_attribute_p early
> > >> so that the declaration has a proper cl_target_.. node and so that inliner can
> > >> fix modes.
> > >>
> > >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> > >>
> > >> Ready to be installed?
> > >
> > > I don't like the new failure mode too much.  It looks like
> > > create_version_clone_with_body
> > > can fail so why not simply return NULL when
> > > targetm.target_option.valid_attribute_p
> > > returns false and handle that case in multi-versioning?
> > >
> > > That is,
> > >
> > > +  return !seen_error ();
> > >
> > > that looks very wrong to me.
> >
> > Yep, update patch should be better.
> >
> > Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> >
> > Ready to be installed?
>
> OK.
>
> Thanks,
> Richard.
>
> > Thanks,
> > Martin
> >
> > >
> > > Richard.
> > >
> > >> Thanks,
> > >> Martin
> > >>
> > >> gcc/ChangeLog:
> > >>
> > >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> > >>             Richard Biener  <rguenther@suse.de>
> > >>
> > >>         PR middle-end/88587
> > >>         * cgraph.h (create_version_clone_with_body): Add new argument
> > >>         with attributes.
> > >>         * cgraphclones.c (cgraph_node::create_version_clone): Add
> > >>         DECL_ATTRIBUTES to a newly created decl.  And call
> > >>         valid_attribute_p so that proper cl_target_optimization_node
> > >>         is set for the newly created declaration.
> > >>         * multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
> > >>         for declaration.
> > >>         (expand_target_clones): Do not call valid_attribute_p, it must
> > >>         be already done.
> > >>         * tree-inline.c (copy_decl_for_dup_finish): Reset mode for
> > >>         vector types.
> > >>
> > >> gcc/testsuite/ChangeLog:
> > >>
> > >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> > >>
> > >>         PR middle-end/88587
> > >>         * g++.target/i386/pr88587.C: New test.
> > >>         * gcc.target/i386/mvc13.c: New test.
> > >> ---
> > >>  gcc/cgraph.h                            |  7 +++++-
> > >>  gcc/cgraphclones.c                      | 18 +++++++++++++-
> > >>  gcc/multiple_target.c                   | 32 ++++++++-----------------
> > >>  gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
> > >>  gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
> > >>  gcc/tree-inline.c                       |  4 ++++
> > >>  6 files changed, 61 insertions(+), 24 deletions(-)
> > >>  create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
> > >>  create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c
> > >>
> > >>
> >

It is wrong to use -m32 in dg-options:

/* { dg-do compile } */
/* { dg-require-ifunc "" } */
/* { dg-options "-O -m32 -g -mno-sse" } */

You should use

/* { dg-do compile { target ia32 } } */

Since g++.target/i386/pr88587.C doesn't support -fPIC,

[hjl@gnu-cfl-1 gcc]$ ./xgcc -B./
/export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C
-mx32 -fpic -S
/export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:6:6:
warning: always_inline function might not be inlinable [-Wattributes]
    6 | void a()
      |      ^
/export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:
In function \u2018void a2()\u2019:
/export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:6:6:
error: inlining failed in call to always_inline \u2018void a()\u2019:
function body can be overwritten at link time
/export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:13:5:
note: called from here
   13 |   a ();
      |   ~~^~
[hjl@gnu-cfl-1 gcc]$

you should add -fno-pic.
H.J. Lu Jan. 18, 2019, 2:29 p.m. UTC | #9
On Fri, Jan 18, 2019 at 6:25 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Thu, Jan 17, 2019 at 4:51 AM Richard Biener
> <richard.guenther@gmail.com> wrote:
> >
> > On Thu, Jan 17, 2019 at 12:21 PM Martin Liška <mliska@suse.cz> wrote:
> > >
> > > On 1/16/19 1:06 PM, Richard Biener wrote:
> > > > On Wed, Jan 16, 2019 at 10:20 AM Martin Liška <mliska@suse.cz> wrote:
> > > >>
> > > >> Hi.
> > > >>
> > > >> The patch is about resetting TYPE_MODE of vector types. This is problematic
> > > >> when an inlining among different ISAs happen. Then we end up with a different
> > > >> mode than when it's expected from debug info.
> > > >>
> > > >> When creating a new function decl in target_clones, we must valid_attribute_p early
> > > >> so that the declaration has a proper cl_target_.. node and so that inliner can
> > > >> fix modes.
> > > >>
> > > >> Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> > > >>
> > > >> Ready to be installed?
> > > >
> > > > I don't like the new failure mode too much.  It looks like
> > > > create_version_clone_with_body
> > > > can fail so why not simply return NULL when
> > > > targetm.target_option.valid_attribute_p
> > > > returns false and handle that case in multi-versioning?
> > > >
> > > > That is,
> > > >
> > > > +  return !seen_error ();
> > > >
> > > > that looks very wrong to me.
> > >
> > > Yep, update patch should be better.
> > >
> > > Patch can bootstrap on x86_64-linux-gnu and survives regression tests.
> > >
> > > Ready to be installed?
> >
> > OK.
> >
> > Thanks,
> > Richard.
> >
> > > Thanks,
> > > Martin
> > >
> > > >
> > > > Richard.
> > > >
> > > >> Thanks,
> > > >> Martin
> > > >>
> > > >> gcc/ChangeLog:
> > > >>
> > > >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> > > >>             Richard Biener  <rguenther@suse.de>
> > > >>
> > > >>         PR middle-end/88587
> > > >>         * cgraph.h (create_version_clone_with_body): Add new argument
> > > >>         with attributes.
> > > >>         * cgraphclones.c (cgraph_node::create_version_clone): Add
> > > >>         DECL_ATTRIBUTES to a newly created decl.  And call
> > > >>         valid_attribute_p so that proper cl_target_optimization_node
> > > >>         is set for the newly created declaration.
> > > >>         * multiple_target.c (create_target_clone): Set DECL_ATTRIBUTES
> > > >>         for declaration.
> > > >>         (expand_target_clones): Do not call valid_attribute_p, it must
> > > >>         be already done.
> > > >>         * tree-inline.c (copy_decl_for_dup_finish): Reset mode for
> > > >>         vector types.
> > > >>
> > > >> gcc/testsuite/ChangeLog:
> > > >>
> > > >> 2019-01-16  Martin Liska  <mliska@suse.cz>
> > > >>
> > > >>         PR middle-end/88587
> > > >>         * g++.target/i386/pr88587.C: New test.
> > > >>         * gcc.target/i386/mvc13.c: New test.
> > > >> ---
> > > >>  gcc/cgraph.h                            |  7 +++++-
> > > >>  gcc/cgraphclones.c                      | 18 +++++++++++++-
> > > >>  gcc/multiple_target.c                   | 32 ++++++++-----------------
> > > >>  gcc/testsuite/g++.target/i386/pr88587.C | 15 ++++++++++++
> > > >>  gcc/testsuite/gcc.target/i386/mvc13.c   |  9 +++++++
> > > >>  gcc/tree-inline.c                       |  4 ++++
> > > >>  6 files changed, 61 insertions(+), 24 deletions(-)
> > > >>  create mode 100644 gcc/testsuite/g++.target/i386/pr88587.C
> > > >>  create mode 100644 gcc/testsuite/gcc.target/i386/mvc13.c
> > > >>
> > > >>
> > >
>
> It is wrong to use -m32 in dg-options:
>
> /* { dg-do compile } */
> /* { dg-require-ifunc "" } */
> /* { dg-options "-O -m32 -g -mno-sse" } */
>
> You should use
>
> /* { dg-do compile { target ia32 } } */
>
> Since g++.target/i386/pr88587.C doesn't support -fPIC,
>
> [hjl@gnu-cfl-1 gcc]$ ./xgcc -B./
> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C
> -mx32 -fpic -S
> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:6:6:
> warning: always_inline function might not be inlinable [-Wattributes]
>     6 | void a()
>       |      ^
> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:
> In function \u2018void a2()\u2019:
> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:6:6:
> error: inlining failed in call to always_inline \u2018void a()\u2019:
> function body can be overwritten at link time
> /export/gnu/import/git/sources/gcc/gcc/testsuite/g++.target/i386/pr88587.C:13:5:
> note: called from here
>    13 |   a ();
>       |   ~~^~
> [hjl@gnu-cfl-1 gcc]$
>
> you should add -fno-pic.
>

I am checking in this patch as an obvious fix.
Martin Liška April 15, 2019, 6:48 a.m. UTC | #10
Hi.

Apparently, there's one another PR:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90083

May I backport the patch to GCC-8 branch?

Thanks,
Martin
Richard Biener April 15, 2019, 7:27 a.m. UTC | #11
On Mon, Apr 15, 2019 at 8:48 AM Martin Liška <mliska@suse.cz> wrote:
>
> Hi.
>
> Apparently, there's one another PR:
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90083
>
> May I backport the patch to GCC-8 branch?

Hmm, it isn't a regression, right?  But it only
affects multi-versioning, so yes, go ahead.
Might as well consider GCC 7 then - do you have
an overall idea of the state of the MV stuff on branches?
IIRC you've done most of the "fixes"?

Richard.

> Thanks,
> Martin
Martin Liška April 15, 2019, 8:02 a.m. UTC | #12
On 4/15/19 9:27 AM, Richard Biener wrote:
> On Mon, Apr 15, 2019 at 8:48 AM Martin Liška <mliska@suse.cz> wrote:
>>
>> Hi.
>>
>> Apparently, there's one another PR:
>> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90083
>>
>> May I backport the patch to GCC-8 branch?
> 
> Hmm, it isn't a regression, right?  But it only
> affects multi-versioning, so yes, go ahead.

No, it's not. The issue is very old.

> Might as well consider GCC 7 then - do you have
> an overall idea of the state of the MV stuff on branches?

Well, I've made quite some changes to target_clone pass
(multiple_target.c). Thus I would ignore GCC-7 if possible.

Martin

> IIRC you've done most of the "fixes"?
> 
> Richard.
> 
>> Thanks,
>> Martin
diff mbox series

Patch

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index c016da3875c..bb231833328 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1019,12 +1019,17 @@  public:
      If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
      If non_NULL NEW_ENTRY determine new entry BB of the clone.
 
+     If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
+     add the attributes to DECL_ATTRIBUTES.  And call valid_attribute_p
+     that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
+     of the declaration.
+
      Return the new version's cgraph node.  */
   cgraph_node *create_version_clone_with_body
     (vec<cgraph_edge *> redirect_callers,
      vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
      bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
-     const char *clone_name);
+     const char *clone_name, tree target_attributes = NULL_TREE);
 
   /* Insert a new cgraph_function_version_info node into cgraph_fnver_htab
      corresponding to cgraph_node.  */
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index 4688de91cfe..f1c0351584d 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -1012,6 +1012,11 @@  cgraph_node::create_version_clone (tree new_decl,
    If non-NULL BLOCK_TO_COPY determine what basic blocks to copy.
    If non_NULL NEW_ENTRY determine new entry BB of the clone.
 
+   If TARGET_ATTRIBUTES is non-null, when creating a new declaration,
+   add the attributes to DECL_ATTRIBUTES.  And call valid_attribute_p
+   that will promote value of the attribute DECL_FUNCTION_SPECIFIC_TARGET
+   of the declaration.
+
    Return the new version's cgraph node.  */
 
 cgraph_node *
@@ -1019,7 +1024,7 @@  cgraph_node::create_version_clone_with_body
   (vec<cgraph_edge *> redirect_callers,
    vec<ipa_replace_map *, va_gc> *tree_map, bitmap args_to_skip,
    bool skip_return, bitmap bbs_to_copy, basic_block new_entry_block,
-   const char *suffix)
+   const char *suffix, tree target_attributes)
 {
   tree old_decl = decl;
   cgraph_node *new_version_node = NULL;
@@ -1044,6 +1049,17 @@  cgraph_node::create_version_clone_with_body
 
   DECL_VIRTUAL_P (new_decl) = 0;
 
+  if (target_attributes)
+    {
+      DECL_ATTRIBUTES (new_decl) = target_attributes;
+
+      location_t saved_loc = input_location;
+      tree v = TREE_VALUE (target_attributes);
+      input_location = DECL_SOURCE_LOCATION (new_decl);
+      targetm.target_option.valid_attribute_p (new_decl, NULL, v, 0);
+      input_location = saved_loc;
+    }
+
   /* When the old decl was a con-/destructor make sure the clone isn't.  */
   DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
   DECL_STATIC_DESTRUCTOR (new_decl) = 0;
diff --git a/gcc/multiple_target.c b/gcc/multiple_target.c
index 589d059424a..fcec0f4676d 100644
--- a/gcc/multiple_target.c
+++ b/gcc/multiple_target.c
@@ -294,7 +294,8 @@  create_new_asm_name (char *old_asm_name, char *new_asm_name)
 /*  Creates target clone of NODE.  */
 
 static cgraph_node *
-create_target_clone (cgraph_node *node, bool definition, char *name)
+create_target_clone (cgraph_node *node, bool definition, char *name,
+		     tree attributes)
 {
   cgraph_node *new_node;
 
@@ -303,13 +304,14 @@  create_target_clone (cgraph_node *node, bool definition, char *name)
       new_node = node->create_version_clone_with_body (vNULL, NULL,
     						       NULL, false,
 						       NULL, NULL,
-						       name);
+						       name, attributes);
       new_node->force_output = true;
     }
   else
     {
       tree new_decl = copy_node (node->decl);
       new_node = cgraph_node::get_create (new_decl);
+      DECL_ATTRIBUTES (new_decl) = attributes;
       /* Generate a new name for the new version.  */
       symtab->change_decl_assembler_name (new_node->decl,
 					  clone_function_name_numbered (
@@ -400,22 +402,14 @@  expand_target_clones (struct cgraph_node *node, bool definition)
 
       create_new_asm_name (attr, suffix);
       /* Create new target clone.  */
-      cgraph_node *new_node = create_target_clone (node, definition, suffix);
+      tree attributes = make_attribute ("target", attr,
+					DECL_ATTRIBUTES (node->decl));
+
+      cgraph_node *new_node = create_target_clone (node, definition, suffix,
+						   attributes);
       new_node->local.local = false;
       XDELETEVEC (suffix);
 
-      /* Set new attribute for the clone.  */
-      tree attributes = make_attribute ("target", attr,
-					DECL_ATTRIBUTES (new_node->decl));
-      DECL_ATTRIBUTES (new_node->decl) = attributes;
-      location_t saved_loc = input_location;
-      input_location = DECL_SOURCE_LOCATION (node->decl);
-      if (!targetm.target_option.valid_attribute_p (new_node->decl, NULL,
-						    TREE_VALUE (attributes),
-						    0))
-	return false;
-
-      input_location = saved_loc;
       decl2_v = new_node->function_version ();
       if (decl2_v != NULL)
         continue;
@@ -442,13 +436,7 @@  expand_target_clones (struct cgraph_node *node, bool definition)
 				    DECL_ATTRIBUTES (node->decl));
   DECL_ATTRIBUTES (node->decl) = attributes;
   node->local.local = false;
-  location_t saved_loc = input_location;
-  input_location = DECL_SOURCE_LOCATION (node->decl);
-  bool ret
-    = targetm.target_option.valid_attribute_p (node->decl, NULL,
-					       TREE_VALUE (attributes), 0);
-  input_location = saved_loc;
-  return ret;
+  return !seen_error ();
 }
 
 /* When NODE is a target clone, consider all callees and redirect
diff --git a/gcc/testsuite/g++.target/i386/pr88587.C b/gcc/testsuite/g++.target/i386/pr88587.C
new file mode 100644
index 00000000000..6808ab68cbb
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr88587.C
@@ -0,0 +1,15 @@ 
+/* { dg-do compile } */
+/* { dg-require-ifunc "" }  */
+/* { dg-options "-O -m32 -g -mno-sse -Wno-attributes" } */
+
+__attribute__((target("default"),always_inline))
+void a()
+{
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
+
+__attribute__((target("sse2"))) void a2()
+{
+  a ();
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
diff --git a/gcc/testsuite/gcc.target/i386/mvc13.c b/gcc/testsuite/gcc.target/i386/mvc13.c
new file mode 100644
index 00000000000..9e31ef7c4da
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/mvc13.c
@@ -0,0 +1,9 @@ 
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O -m32 -g -mno-sse" } */
+
+__attribute__((target_clones("default,sse2")))
+void a()
+{
+  __attribute__((__vector_size__(4 * sizeof(float)))) int b = {};
+}
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index 88620770212..1c2766d4799 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -5479,6 +5479,10 @@  copy_decl_for_dup_finish (copy_body_data *id, tree decl, tree copy)
   if (CODE_CONTAINS_STRUCT (TREE_CODE (copy), TS_DECL_WRTL)
       && !TREE_STATIC (copy) && !DECL_EXTERNAL (copy))
     SET_DECL_RTL (copy, 0);
+  /* For vector typed decls make sure to update DECL_MODE according
+     to the new function context.  */
+  if (VECTOR_TYPE_P (TREE_TYPE (copy)))
+    SET_DECL_MODE (copy, TYPE_MODE (TREE_TYPE (copy)));
 
   /* These args would always appear unused, if not for this.  */
   TREE_USED (copy) = 1;