diff mbox

Fix another ipa-split caused ICE (PR ipa/69241)

Message ID 20160211161416.GC3017@tucnak.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek Feb. 11, 2016, 4:14 p.m. UTC
On Thu, Feb 11, 2016 at 10:22:24AM +0100, Richard Biener wrote:
> The other option is to simply not split the function in this case.

Here is a better fix (but it needs the other patch I've sent, so that
what is return_bb stays the same).

This patch arranges for the case where there is return_bb, but does not
return a value, in function that has return type TREE_ADDRESSABLE,
to just use void return type from the split part (because we would never
set lhs of the call to *.part.* in that case anyway).

Bootstrapped/regtested on x86_64-linux and i686-linux on top of the PR68672
patch, ok for trunk?

2016-02-10  Jakub Jelinek  <jakub@redhat.com>

	PR ipa/69241
	* ipa-split.c (split_function): If split part returns TREE_ADDRESSABLE
	type by reference, force lhs on the call.

	* g++.dg/ipa/pr69241-4.C: New test.


	Jakub

Comments

Richard Biener Feb. 12, 2016, 11:36 a.m. UTC | #1
On Thu, 11 Feb 2016, Jakub Jelinek wrote:

> On Thu, Feb 11, 2016 at 10:22:24AM +0100, Richard Biener wrote:
> > The other option is to simply not split the function in this case.
> 
> Here is a better fix (but it needs the other patch I've sent, so that
> what is return_bb stays the same).
> 
> This patch arranges for the case where there is return_bb, but does not
> return a value, in function that has return type TREE_ADDRESSABLE,
> to just use void return type from the split part (because we would never
> set lhs of the call to *.part.* in that case anyway).
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux on top of the PR68672
> patch, ok for trunk?

Ok.

Thanks,
Richard.

> 2016-02-10  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR ipa/69241
> 	* ipa-split.c (split_function): If split part returns TREE_ADDRESSABLE
> 	type by reference, force lhs on the call.
> 
> 	* g++.dg/ipa/pr69241-4.C: New test.
> 
> --- gcc/ipa-split.c.jj	2016-02-11 12:46:15.975777652 +0100
> +++ gcc/ipa-split.c	2016-02-11 13:06:57.715241871 +0100
> @@ -629,7 +629,18 @@ consider_split (struct split_point *curr
>         4) For non-SSA we need to look where the var is computed. */
>    retval = find_retval (return_bb);
>    if (!retval)
> -    current->split_part_set_retval = true;
> +    {
> +      /* If there is a return_bb with no return value in function returning
> +	 value by reference, also make the split part return void, otherwise
> +	 we expansion would try to create a non-POD temporary, which is
> +	 invalid.  */
> +      if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
> +	  && DECL_RESULT (current_function_decl)
> +	  && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
> +	current->split_part_set_retval = false;
> +      else
> +	current->split_part_set_retval = true;
> +    }
>    else if (is_gimple_min_invariant (retval))
>      current->split_part_set_retval = false;
>    /* Special case is value returned by reference we record as if it was non-ssa
> --- gcc/testsuite/g++.dg/ipa/pr69241-4.C.jj	2016-02-11 13:00:04.160075417 +0100
> +++ gcc/testsuite/g++.dg/ipa/pr69241-4.C	2016-02-11 13:00:04.160075417 +0100
> @@ -0,0 +1,55 @@
> +// PR ipa/69241
> +// { dg-do compile { target c++11 } }
> +// { dg-options "-O2 -Wno-return-type" }
> +
> +template <typename> class A;
> +struct B {
> +  using pointer = int *;
> +};
> +template <typename _CharT, typename = A<_CharT>> class basic_string {
> +  long _M_string_length;
> +  enum { _S_local_capacity = 15 } _M_local_buf[_S_local_capacity];
> +  B::pointer _M_local_data;
> +
> +public:
> +  ~basic_string();
> +};
> +template <typename _CharT, typename _Traits, typename _Alloc>
> +int operator<<(_Traits, basic_string<_CharT, _Alloc>);
> +class C {
> +  basic_string<A<char>> _M_string;
> +};
> +class D {
> +  C _M_stringbuf;
> +};
> +class F {
> +  int stream;
> +  D stream_;
> +};
> +class G {
> +public:
> +  void operator&(int);
> +};
> +class H {
> +public:
> +  H(unsigned);
> +  H(H &&);
> +  bool m_fn1();
> +};
> +class I {
> +  void m_fn2(const int &&);
> +  static H m_fn3(const int &);
> +};
> +template <typename Functor> void Bind(Functor);
> +class J {
> +public:
> +  static basic_string<char> m_fn4();
> +};
> +int a;
> +void I::m_fn2(const int &&) { Bind(m_fn3); }
> +H I::m_fn3(const int &) {
> +  !false ? (void)0 : G() & F() << J::m_fn4();
> +  H b(a);
> +  if (b.m_fn1())
> +    F();
> +}
> 
> 	Jakub
> 
>
diff mbox

Patch

--- gcc/ipa-split.c.jj	2016-02-11 12:46:15.975777652 +0100
+++ gcc/ipa-split.c	2016-02-11 13:06:57.715241871 +0100
@@ -629,7 +629,18 @@  consider_split (struct split_point *curr
        4) For non-SSA we need to look where the var is computed. */
   retval = find_retval (return_bb);
   if (!retval)
-    current->split_part_set_retval = true;
+    {
+      /* If there is a return_bb with no return value in function returning
+	 value by reference, also make the split part return void, otherwise
+	 we expansion would try to create a non-POD temporary, which is
+	 invalid.  */
+      if (return_bb != EXIT_BLOCK_PTR_FOR_FN (cfun)
+	  && DECL_RESULT (current_function_decl)
+	  && DECL_BY_REFERENCE (DECL_RESULT (current_function_decl)))
+	current->split_part_set_retval = false;
+      else
+	current->split_part_set_retval = true;
+    }
   else if (is_gimple_min_invariant (retval))
     current->split_part_set_retval = false;
   /* Special case is value returned by reference we record as if it was non-ssa
--- gcc/testsuite/g++.dg/ipa/pr69241-4.C.jj	2016-02-11 13:00:04.160075417 +0100
+++ gcc/testsuite/g++.dg/ipa/pr69241-4.C	2016-02-11 13:00:04.160075417 +0100
@@ -0,0 +1,55 @@ 
+// PR ipa/69241
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2 -Wno-return-type" }
+
+template <typename> class A;
+struct B {
+  using pointer = int *;
+};
+template <typename _CharT, typename = A<_CharT>> class basic_string {
+  long _M_string_length;
+  enum { _S_local_capacity = 15 } _M_local_buf[_S_local_capacity];
+  B::pointer _M_local_data;
+
+public:
+  ~basic_string();
+};
+template <typename _CharT, typename _Traits, typename _Alloc>
+int operator<<(_Traits, basic_string<_CharT, _Alloc>);
+class C {
+  basic_string<A<char>> _M_string;
+};
+class D {
+  C _M_stringbuf;
+};
+class F {
+  int stream;
+  D stream_;
+};
+class G {
+public:
+  void operator&(int);
+};
+class H {
+public:
+  H(unsigned);
+  H(H &&);
+  bool m_fn1();
+};
+class I {
+  void m_fn2(const int &&);
+  static H m_fn3(const int &);
+};
+template <typename Functor> void Bind(Functor);
+class J {
+public:
+  static basic_string<char> m_fn4();
+};
+int a;
+void I::m_fn2(const int &&) { Bind(m_fn3); }
+H I::m_fn3(const int &) {
+  !false ? (void)0 : G() & F() << J::m_fn4();
+  H b(a);
+  if (b.m_fn1())
+    F();
+}