Bug 65263 - [5 Regression] ICE (error: unrecognizable insn / in insn_min_length, at config/rs6000/rs6000.md) on powerpc64le-linux-gnu
Summary: [5 Regression] ICE (error: unrecognizable insn / in insn_min_length, at confi...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 5.0
: P1 normal
Target Milestone: 5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
: 65278 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-03-01 12:44 UTC by Matthias Klose
Modified: 2015-03-03 16:04 UTC (History)
10 users (show)

See Also:
Host:
Target: powerpc64le-linux-gnu
Build:
Known to work: 4.9.2
Known to fail: 5.0
Last reconfirmed: 2015-03-02 00:00:00


Attachments
Suggested patch (1.34 KB, patch)
2015-03-02 13:41 UTC, Martin Liška
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Matthias Klose 2015-03-01 12:44:07 UTC
seen with r221076 on powerpc64le-linux-gnu

$ g++ -c -g -O3 -fPIC eigenvalue.ii 
eigenvalue.ii:26:19: warning: direct base 'VirtualMatrice<int>' inaccessible in 'C<int>' due to ambiguity
 template <> class C<int> : H<Complex>, VirtualMatrice<Complex> {
                   ^
eigenvalue.ii: In member function 'virtual bool C<int>::_ZThn8_NK1CIiE5m_fn1Ei(int) const':
eigenvalue.ii:47:1: error: unrecognizable insn:
 }
 ^
(call_insn/j 3 2 4 (parallel [
            (call (mem:SI (symbol_ref/i:DI ("_ZNK14VirtualMatriceIiE5m_fn1Ei") [flags 0x1] <function_decl 0x3fff9696fdf8 m_fn1>) [0  S4 A8])
                (const_int 0 [0]))
            (use (const_int 0 [0]))
            (use (reg:SI 65 lr))
            (simple_return)
        ]) eigenvalue.ii:27 -1
     (nil)
    (nil))
eigenvalue.ii:47:1: internal compiler error: in insn_min_length, at config/rs6000/rs6000.md:7813
Please submit a full bug report,
with preprocessed source if appropriate.

$cat eigenvalue.ii
template <class> class A;
template <class R> struct VirtualMatrice {
  virtual bool m_fn1(int) const { return true; }
  struct B {
    A<R> x;
    B(VirtualMatrice *p1, A<R> p2) : x(p2) { p1->m_fn1(0) ?: throw; }
  };
  void operator*(A<R> p1) { B(this, p1); }
  ~VirtualMatrice();
}
;
template <class> class A {
public:
  operator int *();
  A(int *, long);
};

class G : public A<int> {
public:
  G(long);
};
int typedef Complex;
template <class> class H : VirtualMatrice<int> {};
template <class> class C;
template <> class C<int> : H<Complex>, VirtualMatrice<Complex> {
  bool m_fn1(int) const { return true; }
};
template <class K, class Mat>
void DoIdoAction(int, int, A<K> p3, A<K>, A<K>, A<K>, Mat, Mat &p8) {
  p8 *p3;
}

class D {
  typedef int K;
  class F {
    int operator()() const;
  };
};
int D::F::operator()() const {
  VirtualMatrice<K> *a;
  VirtualMatrice<K> b, &B = *a;
  G c(0), g(1);
  int d, e, f;
  A<K> h(&g[f], 0), i(&g[e], 0), j(&g[d], 0);
  DoIdoAction(0, 3, h, i, j, c, b, B);
}
Comment 1 Alan Modra 2015-03-02 01:20:38 UTC
This is caused by revision 221040
+2015-02-26  Jan Hubicka  <hubicka@ucw.cz>
+           Martin Liska  <mliska@suse.cz>
+
+       PR bootstrap/65150
[snip]

#2  0x0000000000bca3fa in _fatal_insn_not_found (insn=insn@entry=0x7ffff6ae4ca8, file=file@entry=0x13852e0 "/src/gcc-current/gcc/config/rs6000/rs6000.md", line=line@entry=7813, function=function@entry=0x139c330 <insn_min_length(rtx_insn*)::__FUNCTION__> "insn_min_length") at /src/gcc-current/gcc/rtl-error.c:118
#3  0x0000000000f1e9f2 in insn_min_length (insn=insn@entry=0x7ffff6ae4ca8) at /src/gcc-current/gcc/config/rs6000/rs6000.md:7813
#4  0x000000000095c8e2 in shorten_branches (first=0x7ffff6ad8038) at /src/gcc-current/gcc/final.c:1221
#5  0x0000000000eea239 in rs6000_output_mi_thunk (file=0x1c37950, thunk_fndecl=<optimised out>, delta=<optimised out>, vcall_offset=<optimised out>, function=<optimised out>) at /src/gcc-current/gcc/config/rs6000/rs6000.c:25835

That's here:
  /* Run just enough of rest_of_compilation to get the insns emitted.
     There's not really enough bulk here to make other passes such as
     instruction scheduling worth while.  Note that use_thunk calls
     assemble_start_function and assemble_end_function.  */
  insn = get_insns ();
  shorten_branches (insn);
Comment 2 Jan Hubicka 2015-03-02 01:37:51 UTC
Hmm, this seems interesting.  The revision enabled more merging in ICF. The expansion dies in output MI thunk that is not ICF produced thunk. So only conclussion I can think of is that ICF redirected call in thunk that made the target dependent code go wrong.

What is wrong about the insn? Does the declaration of functions differ significantly?
Let me see if I can reproduce that in a cross.
Comment 3 Jan Hubicka 2015-03-02 01:56:02 UTC
Semantic equality hit:bool VirtualMatrice<R>::m_fn1(int) const [with R = int]->virtual bool C<int>::m_fn1(int) const
Assembler symbol names:_ZNK14VirtualMatriceIiE5m_fn1Ei->_ZNK1CIiE5m_fn1Ei       
Wrapper cannot be created because of COMDAT                                     
1 local calls have been redirected.                                             
Unified; Function body was removed.                                             

I assume the problem is that thunk can not be generated to non-local symbol. I specifically prevent comdat local symbols to be produced because these makes inlining harder.

There are couple options.  First would be to punt redirection on thunks calls, second would be to produce local alias for thunk calls. I.e. check TARGET_USE_LOCAL_THUNK_ALIAS_P and produce the local alias specifically for thunks.  Third would be to produce the local alias always.

I guess first is safest - while I plan to turn thunks to use noninterposable alias path, I did not because I fear undocumented target issues.  Bettter to not start with these in stage4.

I will prepare patch after dinner
Comment 4 Alan Modra 2015-03-02 03:05:42 UTC
> I assume the problem is that thunk can not be generated to non-local symbol.

Yes, that is at the root of this problem.  The thunk can't be allowed to jump to anything outside the current object file.

The pattern is a sibcall_local64 except that the symbol_ref doesn't match rs6000/predicates.md: current_file_function_operand.
Comment 5 Jan Hubicka 2015-03-02 07:07:06 UTC
Hi,
the following (untested) patch should prevent redirection to happen.  
Index: ipa-icf.c
===================================================================
--- ipa-icf.c	(revision 221096)
+++ ipa-icf.c	(working copy)
@@ -697,12 +697,22 @@ redirect_all_callers (cgraph_node *n, cg
 {
   int nredirected = 0;
   ipa_ref *ref;
+  cgraph_edge *e = n->callers;
 
-  while (n->callers)
+  while (e)
     {
-      cgraph_edge *e = n->callers;
-      e->redirect_callee (to);
-      nredirected++;
+      /* Redirecting thunks to interposable symbols or symbols in other sections
+	 may not be supported by target output code.  Play safe for now and
+	 punt on redirection.  */
+      if (!e->caller->thunk.thunk_p)
+	{
+	  struct cgraph_edge *nexte = e->next_callee;
+          e->redirect_callee (to);
+	  e = nexte;
+          nredirected++;
+	}
+      else
+	e = e->next_callee;
     }
   for (unsigned i = 0; n->iterate_direct_aliases (i, ref);)
     {
@@ -726,6 +736,17 @@ redirect_all_callers (cgraph_node *n, cg
   return nredirected;
 }
 
+/* Return true if NODE has thunk.  */
+
+bool
+has_thunk_p (cgraph_node *node, void *)
+{
+  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+    if (e->caller->thunk.thunk_p)
+      return true;
+  return false;
+}
+
 /* Merges instance with an ALIAS_ITEM, where alias, thunk or redirection can
    be applied.  */
 
@@ -907,6 +928,7 @@ sem_function::merge (sem_item *alias_ite
 	  return false;
 	}
       if (!create_wrapper
+	  && !alias->call_for_symbol_and_aliases (has_thunk_p, NULL, true)
 	  && !alias->can_remove_if_no_direct_calls_p ())
 	{
 	  if (dump_file)
Comment 6 Alan Modra 2015-03-02 08:33:24 UTC
rev 221098 plus the patch segfaults on the testcase in cgraph_node::function_symbol.  node->callees is NULL.
Comment 7 Martin Liška 2015-03-02 13:41:53 UTC
Created attachment 34922 [details]
Suggested patch

There's fixed version of the patch:

1) If I see correctly, there was error in: struct cgraph_edge *nexte = e->next_callee
2) We should not remove alias if there's a thunk that wasn't redirected
3) gcc_assert must be changed for these cases

Patch can run the testcase and survives FF with -O3 and -flto. Regression tests have been running.

Martin
Comment 8 Paul Pluzhnikov 2015-03-02 22:50:12 UTC
r221040 is also possibly causing:

  ../sysdeps/gnu/siglist.c:77:1: internal compiler error: in address_matters_p, at symtab.c:1908

when building trunk GLIBC (seen with GCC @r221125; same source builds with GCC @r220312).
Comment 9 Jan Hubicka 2015-03-02 23:12:06 UTC
Paul, I fixed similar bug yesterday, so please check if it works now for you and if not, please make new PR with a preprocessed source.
Comment 10 Paul Pluzhnikov 2015-03-02 23:33:44 UTC
(In reply to Jan Hubicka from comment #9)
> Paul, I fixed similar bug yesterday, so please check if it works now

I just built at current SVN trunk (r221126).
Filed PR 65287
Comment 11 Alan Modra 2015-03-03 03:10:42 UTC
Martin, your patch passes bootstrap and regression testing on powerpc64-linux.
Comment 12 Martin Liška 2015-03-03 09:26:52 UTC
Author: marxin
Date: Tue Mar  3 09:26:20 2015
New Revision: 221134

URL: https://gcc.gnu.org/viewcvs?rev=221134&root=gcc&view=rev
Log:
Fix PR ipa/65263.

	PR ipa/65263
	* cgraph.c (cgraph_node::has_thunk_p): New function.
	* cgraph.h (cgraph_node::has_thunk_p: Likewise.
	* ipa-icf.c (redirect_all_callers): Do not redirect thunks.
	(sem_function::merge): Assert is changed.
	* g++.dg/ipa/pr65263.C: New test.


Added:
    trunk/gcc/testsuite/g++.dg/ipa/pr65263.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cgraph.c
    trunk/gcc/cgraph.h
    trunk/gcc/ipa-icf.c
    trunk/gcc/testsuite/ChangeLog
Comment 13 Martin Liška 2015-03-03 09:28:20 UTC
Fixed in 5.0.
Comment 14 Aldy Hernandez 2015-03-03 16:04:53 UTC
*** Bug 65278 has been marked as a duplicate of this bug. ***