diff mbox series

Fix ICEs with "omp declare simd" attribute on versioned fns or omp_fn* (PR middle-end/83977)

Message ID 20180124154706.GD2063@tucnak
State New
Headers show
Series Fix ICEs with "omp declare simd" attribute on versioned fns or omp_fn* (PR middle-end/83977) | expand

Commit Message

Jakub Jelinek Jan. 24, 2018, 3:47 p.m. UTC
Hi!

The "omp declare simd" attribute refers to argument numbers of the
functions, so trying to apply it on versioned functions that can perhaps
have different number and types of arguments results in ICEs or wrong-code.
Unfortunately, if simd attribute or #pragma omp declare simd is used
on C++ ctors or dtors, those have DECL_ABSTRACT_ORIGIN of something that
really doesn't exist, abstract ctor or dtor, so checking if
the types of node->decl and its DECL_ABSTRACT_ORIGIN are compatible function
types doesn't work.

The following patch just keeps optimizing only the original functions, not
any versioned copies of them, but still allows simd attribute handling on
e.g. __builtin_sin.

Bootstrapped/regtested on x86_64-linux and i686-linux.

Richard, is the first hunk ok, the rest is OpenMP related and I can ack
myself.

2018-01-24  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/83977
	* tree.c (free_lang_data_in_decl): Don't clear DECL_ABSTRACT_ORIGIN
	here.
	* omp-low.c (create_omp_child_function): Remove "omp declare simd"
	attributes from DECL_ATTRIBUTES (decl) without affecting
	DECL_ATTRIBUTES (current_function_decl).
	* omp-simd-clone.c (expand_simd_clones): Ignore DECL_ARTIFICIAL
	functions with non-NULL DECL_ABSTRACT_ORIGIN.

	* c-c++-common/gomp/pr83977-1.c: New test.
	* c-c++-common/gomp/pr83977-2.c: New test.
	* c-c++-common/gomp/pr83977-3.c: New test.
	* gfortran.dg/gomp/pr83977.f90: New test.


	Jakub

Comments

Richard Biener Jan. 24, 2018, 4:08 p.m. UTC | #1
On January 24, 2018 4:47:06 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>Hi!
>
>The "omp declare simd" attribute refers to argument numbers of the
>functions, so trying to apply it on versioned functions that can
>perhaps
>have different number and types of arguments results in ICEs or
>wrong-code.
>Unfortunately, if simd attribute or #pragma omp declare simd is used
>on C++ ctors or dtors, those have DECL_ABSTRACT_ORIGIN of something
>that
>really doesn't exist, abstract ctor or dtor, so checking if
>the types of node->decl and its DECL_ABSTRACT_ORIGIN are compatible
>function
>types doesn't work.

So if the attribute is on the decl we clone it should be in the list of things that cloning adjusts or blocks cloning. 

>The following patch just keeps optimizing only the original functions,
>not
>any versioned copies of them, but still allows simd attribute handling
>on
>e.g. __builtin_sin.
>
>Bootstrapped/regtested on x86_64-linux and i686-linux.
>
>Richard, is the first hunk ok, the rest is OpenMP related and I can ack
>myself.

Yes. 

>2018-01-24  Jakub Jelinek  <jakub@redhat.com>
>
>	PR middle-end/83977
>	* tree.c (free_lang_data_in_decl): Don't clear DECL_ABSTRACT_ORIGIN
>	here.
>	* omp-low.c (create_omp_child_function): Remove "omp declare simd"
>	attributes from DECL_ATTRIBUTES (decl) without affecting
>	DECL_ATTRIBUTES (current_function_decl).
>	* omp-simd-clone.c (expand_simd_clones): Ignore DECL_ARTIFICIAL
>	functions with non-NULL DECL_ABSTRACT_ORIGIN.
>
>	* c-c++-common/gomp/pr83977-1.c: New test.
>	* c-c++-common/gomp/pr83977-2.c: New test.
>	* c-c++-common/gomp/pr83977-3.c: New test.
>	* gfortran.dg/gomp/pr83977.f90: New test.
>
>--- gcc/tree.c.jj	2018-01-23 14:48:50.216265866 +0100
>+++ gcc/tree.c	2018-01-24 11:40:30.845519905 +0100
>@@ -5329,16 +5329,6 @@ free_lang_data_in_decl (tree decl)
> 	 At this point, it is not needed anymore.  */
>       DECL_SAVED_TREE (decl) = NULL_TREE;
> 
>-      /* Clear the abstract origin if it refers to a method.
>-         Otherwise dwarf2out.c will ICE as we splice functions out of
>-         TYPE_FIELDS and thus the origin will not be output
>-         correctly.  */
>-      if (DECL_ABSTRACT_ORIGIN (decl)
>-	  && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
>-	  && RECORD_OR_UNION_TYPE_P
>-	       (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
>-	DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
>-
>  /* Sometimes the C++ frontend doesn't manage to transform a temporary
>        DECL_VINDEX referring to itself into a vtable slot number as it
> 	 should.  Happens with functions that are copied and then forgotten
>--- gcc/omp-low.c.jj	2018-01-04 00:43:16.106702767 +0100
>+++ gcc/omp-low.c	2018-01-24 12:59:37.566218901 +0100
>@@ -1585,6 +1585,23 @@ create_omp_child_function (omp_context *
>   DECL_INITIAL (decl) = make_node (BLOCK);
>   BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
>   DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
>+  /* Remove omp declare simd attribute from the new attributes.  */
>+  if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES
>(decl)))
>+    {
>+      while (tree a2 = lookup_attribute ("omp declare simd",
>TREE_CHAIN (a)))
>+	a = a2;
>+      a = TREE_CHAIN (a);
>+      for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
>+	if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
>+	  *p = TREE_CHAIN (*p);
>+	else
>+	  {
>+	    tree chain = TREE_CHAIN (*p);
>+	    *p = copy_node (*p);
>+	    p = &TREE_CHAIN (*p);
>+	    *p = chain;
>+	  }
>+    }
>   DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
>     = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
>   DECL_FUNCTION_SPECIFIC_TARGET (decl)
>--- gcc/omp-simd-clone.c.jj	2018-01-23 14:48:47.275261492 +0100
>+++ gcc/omp-simd-clone.c	2018-01-24 11:45:28.484494749 +0100
>@@ -1574,6 +1574,10 @@ expand_simd_clones (struct cgraph_node *
>   tree attr = lookup_attribute ("omp declare simd",
> 				DECL_ATTRIBUTES (node->decl));
>   if (attr == NULL_TREE
>+      /* Ignore artificial decls with an abstract origin, results of
>function
>+	 cloning, versioning etc.  We want to handle certain builtins
>+	 with simd attribute, like __builtin_sin.  */
>+      || (DECL_ARTIFICIAL (node->decl) && DECL_ABSTRACT_ORIGIN
>(node->decl))
>       || node->global.inlined_to
>       || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
>     return;
>--- gcc/testsuite/c-c++-common/gomp/pr83977-1.c.jj	2018-01-24
>11:46:00.946492004 +0100
>+++ gcc/testsuite/c-c++-common/gomp/pr83977-1.c	2018-01-24
>11:46:29.181489615 +0100
>@@ -0,0 +1,19 @@
>+/* PR middle-end/83977 */
>+/* { dg-do compile } */
>+/* { dg-additional-options "-O2" } */
>+
>+struct S { int a, b, c; };
>+
>+#pragma omp declare simd uniform(z) linear(v:1)
>+__attribute__((noinline)) static int
>+foo (int x, int y, struct S z, int u, int v)
>+{
>+  return x + y + z.a;
>+}
>+
>+int
>+bar (int x, int y, int z)
>+{
>+  struct S s = { z, 1, 1 };
>+  return foo (x, y, s, 0, 0);
>+}
>--- gcc/testsuite/c-c++-common/gomp/pr83977-2.c.jj	2018-01-24
>11:46:42.259488509 +0100
>+++ gcc/testsuite/c-c++-common/gomp/pr83977-2.c	2018-01-24
>11:50:08.173471101 +0100
>@@ -0,0 +1,18 @@
>+/* PR middle-end/83977 */
>+/* { dg-do compile } */
>+
>+void bar (void);
>+
>+#pragma omp declare simd uniform (b) linear(a:b)
>+int
>+foo (int a, int b)
>+{
>+  a = a + 1;
>+/* This function can't be called from simd loops,
>+   because it violates declare simd restrictions.
>+   We shouldn't ICE on it though, nor attempt to generate
>+   simd clones for the *omp_fn* functions.  */
>+  #pragma omp parallel
>+  bar ();  
>+  return a;
>+}
>--- gcc/testsuite/c-c++-common/gomp/pr83977-3.c.jj	2018-01-24
>13:11:27.421111722 +0100
>+++ gcc/testsuite/c-c++-common/gomp/pr83977-3.c	2018-01-24
>13:12:08.945106675 +0100
>@@ -0,0 +1,21 @@
>+/* PR middle-end/83977 */
>+/* { dg-do compile } */
>+
>+void bar (void);
>+int foo (int, int) __attribute__((used));
>+
>+#pragma omp declare simd uniform (b) linear(a:b)
>+int
>+foo (int a, int b)
>+{
>+  a = a + 1;
>+/* This function can't be called from simd loops,
>+   because it violates declare simd restrictions.
>+   We shouldn't ICE on it though, nor attempt to generate
>+   simd clones for the *omp_fn* functions.  */
>+  #pragma omp parallel
>+  bar ();  
>+  return a;
>+}
>+
>+int foo (int, int)  __attribute__((unused));
>--- gcc/testsuite/gfortran.dg/gomp/pr83977.f90.jj	2018-01-24
>11:26:11.425592553 +0100
>+++ gcc/testsuite/gfortran.dg/gomp/pr83977.f90	2018-01-24
>11:26:11.425592553 +0100
>@@ -0,0 +1,15 @@
>+! PR middle-end/83977
>+! { dg-do compile }
>+
>+integer function foo (a, b)
>+   integer :: a, b
>+!$omp declare simd uniform(b) linear(ref(a):b)
>+   a = a + 1
>+! This function can't be called from simd loops,
>+! because it violates declare simd restrictions.
>+! We shouldn't ICE on it though, nor attempt to generate
>+! simd clones for the *omp_fn* functions.
>+!$omp parallel
>+   call sub
>+!$omp end parallel
>+end
>
>	Jakub
Jakub Jelinek Jan. 24, 2018, 4:16 p.m. UTC | #2
On Wed, Jan 24, 2018 at 05:08:10PM +0100, Richard Biener wrote:
> >The "omp declare simd" attribute refers to argument numbers of the
> >functions, so trying to apply it on versioned functions that can
> >perhaps
> >have different number and types of arguments results in ICEs or
> >wrong-code.
> >Unfortunately, if simd attribute or #pragma omp declare simd is used
> >on C++ ctors or dtors, those have DECL_ABSTRACT_ORIGIN of something
> >that
> >really doesn't exist, abstract ctor or dtor, so checking if
> >the types of node->decl and its DECL_ABSTRACT_ORIGIN are compatible
> >function
> >types doesn't work.
> 
> So if the attribute is on the decl we clone it should be in the list of things that cloning adjusts or blocks cloning. 

Yeah, guess I could move the attribute removal code from omp-low.c to some
helper function and in tree_function_versioning check if the attribute is
present and if yes and the old/new function types don't match, drop the
attribute.  Or, add some flag to cgraph whether the attribute should be
honored or not, and clear it in tree_function_versioning and
omp_create_child_function instead of removing the attribute.

I'd prefer to defer that to GCC9 though at this point.

	Jakub
Richard Biener Jan. 24, 2018, 4:33 p.m. UTC | #3
On January 24, 2018 5:16:45 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>On Wed, Jan 24, 2018 at 05:08:10PM +0100, Richard Biener wrote:
>> >The "omp declare simd" attribute refers to argument numbers of the
>> >functions, so trying to apply it on versioned functions that can
>> >perhaps
>> >have different number and types of arguments results in ICEs or
>> >wrong-code.
>> >Unfortunately, if simd attribute or #pragma omp declare simd is used
>> >on C++ ctors or dtors, those have DECL_ABSTRACT_ORIGIN of something
>> >that
>> >really doesn't exist, abstract ctor or dtor, so checking if
>> >the types of node->decl and its DECL_ABSTRACT_ORIGIN are compatible
>> >function
>> >types doesn't work.
>> 
>> So if the attribute is on the decl we clone it should be in the list
>of things that cloning adjusts or blocks cloning. 
>
>Yeah, guess I could move the attribute removal code from omp-low.c to
>some
>helper function and in tree_function_versioning check if the attribute
>is
>present and if yes and the old/new function types don't match, drop the
>attribute.  Or, add some flag to cgraph whether the attribute should be
>honored or not, and clear it in tree_function_versioning and
>omp_create_child_function instead of removing the attribute.

I think there's already a set of attributes that prevent cloning and or are adjusted by the IPA param machinery. The Martins or Honza should know better. 

>I'd prefer to defer that to GCC9 though at this point.

Sure. 

>	Jakub
Martin Jambor Jan. 24, 2018, 5:36 p.m. UTC | #4
On Wed, Jan 24 2018, Richard Biener wrote:
> On January 24, 2018 5:16:45 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>>On Wed, Jan 24, 2018 at 05:08:10PM +0100, Richard Biener wrote:
>>> >The "omp declare simd" attribute refers to argument numbers of the
>>> >functions, so trying to apply it on versioned functions that can
>>> >perhaps
>>> >have different number and types of arguments results in ICEs or
>>> >wrong-code.
>>> >Unfortunately, if simd attribute or #pragma omp declare simd is used
>>> >on C++ ctors or dtors, those have DECL_ABSTRACT_ORIGIN of something
>>> >that
>>> >really doesn't exist, abstract ctor or dtor, so checking if
>>> >the types of node->decl and its DECL_ABSTRACT_ORIGIN are compatible
>>> >function
>>> >types doesn't work.
>>> 
>>> So if the attribute is on the decl we clone it should be in the list
>>of things that cloning adjusts or blocks cloning. 
>>
>>Yeah, guess I could move the attribute removal code from omp-low.c to
>>some
>>helper function and in tree_function_versioning check if the attribute
>>is
>>present and if yes and the old/new function types don't match, drop the
>>attribute.  Or, add some flag to cgraph whether the attribute should be
>>honored or not, and clear it in tree_function_versioning and
>>omp_create_child_function instead of removing the attribute.
>
> I think there's already a set of attributes that prevent cloning and
> or are adjusted by the IPA param machinery. The Martins or Honza
> should know better.

I am not sure I understand the problem but if
tree_versionable_function_p returns false, the local.versionable bit is
not set and no cloning for that function happens.

If it is sufficient that IPA-CP and other IPA passes do not change the
function type in any way (in practice that they don't remove
parameters), it is sufficient to clear the local.can_change_signature
cgraph flag in compute_fn_summary() in ipa-fnsummary.c.  That is how we
handle, or rather avoid handling, fnspec attributes.

Martin
Jakub Jelinek Jan. 24, 2018, 5:40 p.m. UTC | #5
On Wed, Jan 24, 2018 at 06:36:02PM +0100, Martin Jambor wrote:
> > I think there's already a set of attributes that prevent cloning and
> > or are adjusted by the IPA param machinery. The Martins or Honza
> > should know better.
> 
> I am not sure I understand the problem but if
> tree_versionable_function_p returns false, the local.versionable bit is
> not set and no cloning for that function happens.
> 
> If it is sufficient that IPA-CP and other IPA passes do not change the
> function type in any way (in practice that they don't remove
> parameters), it is sufficient to clear the local.can_change_signature
> cgraph flag in compute_fn_summary() in ipa-fnsummary.c.  That is how we
> handle, or rather avoid handling, fnspec attributes.

Well, "omp declare simd" is a part of the ABI just for the original exported
functions, for everything else it is a pure optimization, but I'm not sure
if we want to deoptimize e.g. callers of these functions outside of loops
by disabling the signature changing cloning for those.  For calls from
within OpenMP simd regions or other loops where we try hard to vectorize
them, it might make sense not to change those callers, for callers from
other loops, a question.

	Jakub
Richard Biener Jan. 24, 2018, 5:51 p.m. UTC | #6
On January 24, 2018 6:40:25 PM GMT+01:00, Jakub Jelinek <jakub@redhat.com> wrote:
>On Wed, Jan 24, 2018 at 06:36:02PM +0100, Martin Jambor wrote:
>> > I think there's already a set of attributes that prevent cloning
>and
>> > or are adjusted by the IPA param machinery. The Martins or Honza
>> > should know better.
>> 
>> I am not sure I understand the problem but if
>> tree_versionable_function_p returns false, the local.versionable bit
>is
>> not set and no cloning for that function happens.
>> 
>> If it is sufficient that IPA-CP and other IPA passes do not change
>the
>> function type in any way (in practice that they don't remove
>> parameters), it is sufficient to clear the local.can_change_signature
>> cgraph flag in compute_fn_summary() in ipa-fnsummary.c.  That is how
>we
>> handle, or rather avoid handling, fnspec attributes.
>
>Well, "omp declare simd" is a part of the ABI just for the original
>exported
>functions, for everything else it is a pure optimization, but I'm not
>sure
>if we want to deoptimize e.g. callers of these functions outside of
>loops
>by disabling the signature changing cloning for those.  For calls from
>within OpenMP simd regions or other loops where we try hard to
>vectorize
>them, it might make sense not to change those callers, for callers from
>other loops, a question.

Until we can distinguish the cases I think not changing the signature by default might be a good thing. 

Richard. 

>	Jakub
Richard Biener Jan. 24, 2018, 5:54 p.m. UTC | #7
On January 24, 2018 6:51:54 PM GMT+01:00, Richard Biener <rguenther@suse.de> wrote:
>On January 24, 2018 6:40:25 PM GMT+01:00, Jakub Jelinek
><jakub@redhat.com> wrote:
>>On Wed, Jan 24, 2018 at 06:36:02PM +0100, Martin Jambor wrote:
>>> > I think there's already a set of attributes that prevent cloning
>>and
>>> > or are adjusted by the IPA param machinery. The Martins or Honza
>>> > should know better.
>>> 
>>> I am not sure I understand the problem but if
>>> tree_versionable_function_p returns false, the local.versionable bit
>>is
>>> not set and no cloning for that function happens.
>>> 
>>> If it is sufficient that IPA-CP and other IPA passes do not change
>>the
>>> function type in any way (in practice that they don't remove
>>> parameters), it is sufficient to clear the
>local.can_change_signature
>>> cgraph flag in compute_fn_summary() in ipa-fnsummary.c.  That is how
>>we
>>> handle, or rather avoid handling, fnspec attributes.
>>
>>Well, "omp declare simd" is a part of the ABI just for the original
>>exported
>>functions, for everything else it is a pure optimization, but I'm not
>>sure
>>if we want to deoptimize e.g. callers of these functions outside of
>>loops
>>by disabling the signature changing cloning for those.  For calls from
>>within OpenMP simd regions or other loops where we try hard to
>>vectorize
>>them, it might make sense not to change those callers, for callers
>from
>>other loops, a question.
>
>Until we can distinguish the cases I think not changing the signature
>by default might be a good thing. 

Otoh cloning for ipa cp and then inlining is OK. Not sure how the mitigation mechanism works. 

Richard. 

>Richard. 
>
>>	Jakub
Jakub Jelinek Jan. 25, 2018, 3:33 p.m. UTC | #8
On Wed, Jan 24, 2018 at 06:51:54PM +0100, Richard Biener wrote:
> >Well, "omp declare simd" is a part of the ABI just for the original
> >exported
> >functions, for everything else it is a pure optimization, but I'm not
> >sure
> >if we want to deoptimize e.g. callers of these functions outside of
> >loops
> >by disabling the signature changing cloning for those.  For calls from
> >within OpenMP simd regions or other loops where we try hard to
> >vectorize
> >them, it might make sense not to change those callers, for callers from
> >other loops, a question.
> 
> Until we can distinguish the cases I think not changing the signature by
> default might be a good thing.

Done thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
committed to trunk.

2018-01-25  Jakub Jelinek  <jakub@redhat.com>

	PR middle-end/83977
	* ipa-fnsummary.c (compute_fn_summary): Clear can_change_signature
	on functions with #pragma omp declare simd or functions with simd
	attribute.
	* omp-simd-clone.c (expand_simd_clones): Revert 2018-01-24 change.
	* config/i386/i386.c (ix86_simd_clone_compute_vecsize_and_simdlen):
	Remove trailing \n from warning_at calls.

	* c-c++-common/gomp/pr83977-1.c: Add -w to dg-options.

--- gcc/ipa-fnsummary.c.jj	2018-01-25 12:13:06.651327787 +0100
+++ gcc/ipa-fnsummary.c	2018-01-25 12:14:22.282340706 +0100
@@ -2467,7 +2467,11 @@ compute_fn_summary (struct cgraph_node *
 	 info->inlinable = tree_inlinable_function_p (node->decl);
 
        /* Type attributes can use parameter indices to describe them.  */
-       if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl)))
+       if (TYPE_ATTRIBUTES (TREE_TYPE (node->decl))
+	   /* Likewise for #pragma omp declare simd functions or functions
+	      with simd attribute.  */
+	   || lookup_attribute ("omp declare simd",
+				DECL_ATTRIBUTES (node->decl)))
 	 node->local.can_change_signature = false;
        else
 	 {
--- gcc/omp-simd-clone.c.jj	2018-01-25 12:13:06.624327783 +0100
+++ gcc/omp-simd-clone.c	2018-01-25 12:14:22.282340706 +0100
@@ -1574,10 +1574,6 @@ expand_simd_clones (struct cgraph_node *
   tree attr = lookup_attribute ("omp declare simd",
 				DECL_ATTRIBUTES (node->decl));
   if (attr == NULL_TREE
-      /* Ignore artificial decls with an abstract origin, results of function
-	 cloning, versioning etc.  We want to handle certain builtins
-	 with simd attribute, like __builtin_sin.  */
-      || (DECL_ARTIFICIAL (node->decl) && DECL_ABSTRACT_ORIGIN (node->decl))
       || node->global.inlined_to
       || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
     return;
--- gcc/config/i386/i386.c.jj	2018-01-24 23:41:33.714031847 +0100
+++ gcc/config/i386/i386.c	2018-01-25 12:16:02.231357778 +0100
@@ -50224,7 +50224,7 @@ ix86_simd_clone_compute_vecsize_and_simd
 	break;
       default:
 	warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
-		    "unsupported return type %qT for simd\n", ret_type);
+		    "unsupported return type %qT for simd", ret_type);
 	return 0;
       }
 
@@ -50246,7 +50246,7 @@ ix86_simd_clone_compute_vecsize_and_simd
 	break;
       default:
 	warning_at (DECL_SOURCE_LOCATION (node->decl), 0,
-		    "unsupported argument type %qT for simd\n", TREE_TYPE (t));
+		    "unsupported argument type %qT for simd", TREE_TYPE (t));
 	return 0;
       }
 
--- gcc/testsuite/c-c++-common/gomp/pr83977-1.c.jj	2018-01-24 17:26:25.217357997 +0100
+++ gcc/testsuite/c-c++-common/gomp/pr83977-1.c	2018-01-25 12:18:34.196383735 +0100
@@ -1,6 +1,6 @@
 /* PR middle-end/83977 */
 /* { dg-do compile } */
-/* { dg-additional-options "-O2" } */
+/* { dg-additional-options "-O2 -w" } */
 
 struct S { int a, b, c; };
 


	Jakub
diff mbox series

Patch

--- gcc/tree.c.jj	2018-01-23 14:48:50.216265866 +0100
+++ gcc/tree.c	2018-01-24 11:40:30.845519905 +0100
@@ -5329,16 +5329,6 @@  free_lang_data_in_decl (tree decl)
 	 At this point, it is not needed anymore.  */
       DECL_SAVED_TREE (decl) = NULL_TREE;
 
-      /* Clear the abstract origin if it refers to a method.
-         Otherwise dwarf2out.c will ICE as we splice functions out of
-         TYPE_FIELDS and thus the origin will not be output
-         correctly.  */
-      if (DECL_ABSTRACT_ORIGIN (decl)
-	  && DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))
-	  && RECORD_OR_UNION_TYPE_P
-	       (DECL_CONTEXT (DECL_ABSTRACT_ORIGIN (decl))))
-	DECL_ABSTRACT_ORIGIN (decl) = NULL_TREE;
-
       /* Sometimes the C++ frontend doesn't manage to transform a temporary
          DECL_VINDEX referring to itself into a vtable slot number as it
 	 should.  Happens with functions that are copied and then forgotten
--- gcc/omp-low.c.jj	2018-01-04 00:43:16.106702767 +0100
+++ gcc/omp-low.c	2018-01-24 12:59:37.566218901 +0100
@@ -1585,6 +1585,23 @@  create_omp_child_function (omp_context *
   DECL_INITIAL (decl) = make_node (BLOCK);
   BLOCK_SUPERCONTEXT (DECL_INITIAL (decl)) = decl;
   DECL_ATTRIBUTES (decl) = DECL_ATTRIBUTES (current_function_decl);
+  /* Remove omp declare simd attribute from the new attributes.  */
+  if (tree a = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (decl)))
+    {
+      while (tree a2 = lookup_attribute ("omp declare simd", TREE_CHAIN (a)))
+	a = a2;
+      a = TREE_CHAIN (a);
+      for (tree *p = &DECL_ATTRIBUTES (decl); *p != a;)
+	if (is_attribute_p ("omp declare simd", get_attribute_name (*p)))
+	  *p = TREE_CHAIN (*p);
+	else
+	  {
+	    tree chain = TREE_CHAIN (*p);
+	    *p = copy_node (*p);
+	    p = &TREE_CHAIN (*p);
+	    *p = chain;
+	  }
+    }
   DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl)
     = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (current_function_decl);
   DECL_FUNCTION_SPECIFIC_TARGET (decl)
--- gcc/omp-simd-clone.c.jj	2018-01-23 14:48:47.275261492 +0100
+++ gcc/omp-simd-clone.c	2018-01-24 11:45:28.484494749 +0100
@@ -1574,6 +1574,10 @@  expand_simd_clones (struct cgraph_node *
   tree attr = lookup_attribute ("omp declare simd",
 				DECL_ATTRIBUTES (node->decl));
   if (attr == NULL_TREE
+      /* Ignore artificial decls with an abstract origin, results of function
+	 cloning, versioning etc.  We want to handle certain builtins
+	 with simd attribute, like __builtin_sin.  */
+      || (DECL_ARTIFICIAL (node->decl) && DECL_ABSTRACT_ORIGIN (node->decl))
       || node->global.inlined_to
       || lookup_attribute ("noclone", DECL_ATTRIBUTES (node->decl)))
     return;
--- gcc/testsuite/c-c++-common/gomp/pr83977-1.c.jj	2018-01-24 11:46:00.946492004 +0100
+++ gcc/testsuite/c-c++-common/gomp/pr83977-1.c	2018-01-24 11:46:29.181489615 +0100
@@ -0,0 +1,19 @@ 
+/* PR middle-end/83977 */
+/* { dg-do compile } */
+/* { dg-additional-options "-O2" } */
+
+struct S { int a, b, c; };
+
+#pragma omp declare simd uniform(z) linear(v:1)
+__attribute__((noinline)) static int
+foo (int x, int y, struct S z, int u, int v)
+{
+  return x + y + z.a;
+}
+
+int
+bar (int x, int y, int z)
+{
+  struct S s = { z, 1, 1 };
+  return foo (x, y, s, 0, 0);
+}
--- gcc/testsuite/c-c++-common/gomp/pr83977-2.c.jj	2018-01-24 11:46:42.259488509 +0100
+++ gcc/testsuite/c-c++-common/gomp/pr83977-2.c	2018-01-24 11:50:08.173471101 +0100
@@ -0,0 +1,18 @@ 
+/* PR middle-end/83977 */
+/* { dg-do compile } */
+
+void bar (void);
+
+#pragma omp declare simd uniform (b) linear(a:b)
+int
+foo (int a, int b)
+{
+  a = a + 1;
+/* This function can't be called from simd loops,
+   because it violates declare simd restrictions.
+   We shouldn't ICE on it though, nor attempt to generate
+   simd clones for the *omp_fn* functions.  */
+  #pragma omp parallel
+  bar ();  
+  return a;
+}
--- gcc/testsuite/c-c++-common/gomp/pr83977-3.c.jj	2018-01-24 13:11:27.421111722 +0100
+++ gcc/testsuite/c-c++-common/gomp/pr83977-3.c	2018-01-24 13:12:08.945106675 +0100
@@ -0,0 +1,21 @@ 
+/* PR middle-end/83977 */
+/* { dg-do compile } */
+
+void bar (void);
+int foo (int, int) __attribute__((used));
+
+#pragma omp declare simd uniform (b) linear(a:b)
+int
+foo (int a, int b)
+{
+  a = a + 1;
+/* This function can't be called from simd loops,
+   because it violates declare simd restrictions.
+   We shouldn't ICE on it though, nor attempt to generate
+   simd clones for the *omp_fn* functions.  */
+  #pragma omp parallel
+  bar ();  
+  return a;
+}
+
+int foo (int, int)  __attribute__((unused));
--- gcc/testsuite/gfortran.dg/gomp/pr83977.f90.jj	2018-01-24 11:26:11.425592553 +0100
+++ gcc/testsuite/gfortran.dg/gomp/pr83977.f90	2018-01-24 11:26:11.425592553 +0100
@@ -0,0 +1,15 @@ 
+! PR middle-end/83977
+! { dg-do compile }
+
+integer function foo (a, b)
+   integer :: a, b
+!$omp declare simd uniform(b) linear(ref(a):b)
+   a = a + 1
+! This function can't be called from simd loops,
+! because it violates declare simd restrictions.
+! We shouldn't ICE on it though, nor attempt to generate
+! simd clones for the *omp_fn* functions.
+!$omp parallel
+   call sub
+!$omp end parallel
+end