[PR,85421] Call expand_all_artificial_thunks in ipa-cp if necessary

Message ID ri6y3hmb9v6.fsf@suse.cz
State New
Headers show
Series
  • [PR,85421] Call expand_all_artificial_thunks in ipa-cp if necessary
Related show

Commit Message

Martin Jambor April 17, 2018, 6:55 a.m.
Hi,

my fix from last week caused an ICE described in PR 85421 because I did
not read my own comment and forgot that after calls to
redirect_callee_duplicating_thunks, one must finish the work by calling
expand_all_artificial_thunks, otherwise we end up with unanalyzed thunks
and hit some assert sooner or later, like we did in this bug.

Fixed with the patch below, bootstrapped, LTO-bootstrapped and tested on
x86_64-linux.  OK for trunk?

I'm sorry for introducing an ICE so late in stage4,

Martin


2018-04-17  Martin Jambor  <mjambor@suse.cz>

	PR ipa/85421
	* ipa-cp.c (create_specialized_node): Call
	expand_all_artificial_thunks if necessary.
	* testsuite/g++.dg/ipa/pr85421.C: New test.

2018-04-08  Martin Jambor  <mjambor@suse.cz>
---
 gcc/ipa-cp.c                       |   3 +
 gcc/testsuite/g++.dg/ipa/pr85421.C | 131 +++++++++++++++++++++++++++++++++++++
 2 files changed, 134 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/ipa/pr85421.C

Comments

Jakub Jelinek April 17, 2018, 7 a.m. | #1
On Tue, Apr 17, 2018 at 08:55:09AM +0200, Martin Jambor wrote:
> Hi,
> 
> my fix from last week caused an ICE described in PR 85421 because I did
> not read my own comment and forgot that after calls to
> redirect_callee_duplicating_thunks, one must finish the work by calling
> expand_all_artificial_thunks, otherwise we end up with unanalyzed thunks
> and hit some assert sooner or later, like we did in this bug.
> 
> Fixed with the patch below, bootstrapped, LTO-bootstrapped and tested on
> x86_64-linux.  OK for trunk?
> 
> I'm sorry for introducing an ICE so late in stage4,
> 
> Martin
> 
> 
> 2018-04-17  Martin Jambor  <mjambor@suse.cz>
> 
> 	PR ipa/85421
> 	* ipa-cp.c (create_specialized_node): Call
> 	expand_all_artificial_thunks if necessary.
> 	* testsuite/g++.dg/ipa/pr85421.C: New test.

Ok for trunk.
No testsuite/ prefix for files going into testsuite/ChangeLog.

	Jakub

Patch

diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index b2627ffd05f..4e0e20af409 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -3863,6 +3863,7 @@  create_specialized_node (struct cgraph_node *node,
   new_node = node->create_virtual_clone (callers, replace_trees,
 					 args_to_skip, "constprop");
 
+  bool have_self_recursive_calls = !self_recursive_calls.is_empty ();
   for (unsigned j = 0; j < self_recursive_calls.length (); j++)
     {
       cgraph_edge *cs = next_edge_clone[self_recursive_calls[j]->uid];
@@ -3870,6 +3871,8 @@  create_specialized_node (struct cgraph_node *node,
       gcc_assert (cs->caller == new_node);
       cs->redirect_callee_duplicating_thunks (new_node);
     }
+  if (have_self_recursive_calls)
+    new_node->expand_all_artificial_thunks ();
 
   ipa_set_node_agg_value_chain (new_node, aggvals);
   for (av = aggvals; av; av = av->next)
diff --git a/gcc/testsuite/g++.dg/ipa/pr85421.C b/gcc/testsuite/g++.dg/ipa/pr85421.C
new file mode 100644
index 00000000000..517d99ae8f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr85421.C
@@ -0,0 +1,131 @@ 
+// { dg-do compile }
+// { dg-options "-O3 -std=gnu++1y -w" }
+
+namespace {
+template <typename b> b c(b);
+template <typename d, typename, template <typename> class> struct f {
+  using g = d;
+};
+template <typename d, template <typename> class aa> using h = f<d, void, aa>;
+template <typename d, template <typename> class aa>
+using i = typename h<d, aa>::g;
+template <typename b> struct j { typedef b k; };
+} // namespace
+namespace l {
+template <typename b> class m {
+public:
+  typedef b k;
+};
+} // namespace l
+namespace a {
+template <typename b> using n = l::m<b>;
+template <typename b> class ac : public n<b> {};
+struct s {
+  template <typename b> using ad = typename b::e;
+};
+template <typename o> struct p : s {
+  typedef typename o::k k;
+  using ag = i<k *, ad>;
+};
+} // namespace a
+namespace l {
+template <typename o> struct t : a::p<o> {};
+} // namespace l
+namespace a {
+template <bool> struct al {
+  template <typename am> static void an(am ao, am) { c(*ao); }
+};
+template <typename am> void aq(am ao, am ap) {
+  typedef typename j<am>::k ar;
+  al<__has_trivial_destructor(ar)>::an(ao, ap);
+}
+namespace {
+typedef char au;
+}
+} // namespace a
+typedef char av;
+typedef int aw;
+typedef av ay;
+typedef aw az;
+namespace a {
+template <typename, typename o> struct ba {
+  typedef typename l::t<o>::ag ag;
+  struct {
+    ag bb;
+    ag bc;
+  } bd;
+};
+template <typename b, typename o = ac<b>> class be : ba<b, o> {
+  typedef ba<b, o> bf;
+  typedef typename bf::ag ag;
+
+public:
+  void bh() { bi(this->bd.bb); }
+  void bi(ag bj) { aq(bj, this->bd.bc); }
+};
+} // namespace a
+namespace bk {
+enum bl {};
+enum bn { bo };
+class q {
+public:
+  static a::au bp(bn);
+  static bool bq(a::au *br, bn g) { return bs(br, g); }
+  static bl bs(a::au *br, bn g) {
+    if (br) {
+      auto bt = bp(g);
+      if (bt)
+        return bl();
+    }
+  }
+};
+template <typename, typename> class bu {};
+} // namespace bk
+namespace bv {
+namespace bw {
+class bx;
+}
+} // namespace bv
+namespace bk {
+enum by { bz };
+struct ca;
+class cb {
+public:
+  class cc {
+  public:
+    virtual void cd(by) = 0;
+  };
+  virtual bu<ca, by> e();
+  cc *cf;
+};
+class cg {
+public:
+  ~cg() { q::bq(ch, bo); }
+  a::au *ch;
+};
+class ci {
+  cg cj;
+};
+namespace ck {
+enum cl : ay;
+}
+class r : ci {};
+class cn {
+public:
+  ck::cl co();
+};
+by cp(ck::cl);
+class cq : cb, cb::cc {
+  bu<ca, by> ce(bv::bw::bx &, az) noexcept;
+  void cd(by);
+  void cr(bv::bw::bx &, az, cb::cc *) noexcept;
+  cn cs;
+  a::be<r> ct;
+};
+} // namespace bk
+using bv::bw::bx;
+namespace bk {
+bu<ca, by> cq::ce(bx &, az) noexcept { ct.bh(); }
+void cq::cr(bx &, az, cb::cc *) noexcept { cd(bz); }
+void cq::cd(by) { cf->cd(cp(cs.co())); }
+} // namespace bk