Bug 56756 - [4.9 Regression] ICE: verify_ssa failed (definition in block n follows the use !)
Summary: [4.9 Regression] ICE: verify_ssa failed (definition in block n follows the us...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.9.0
: P3 normal
Target Milestone: 4.9.0
Assignee: Richard Biener
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-03-27 20:48 UTC by Antoine Balestrat
Modified: 2013-04-16 15:41 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work: 4.7.3, 4.8.0
Known to fail: 4.9.0
Last reconfirmed: 2013-03-28 00:00:00


Attachments
patch (3.01 KB, application/octet-stream)
2013-03-28 12:42 UTC, Richard Biener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Antoine Balestrat 2013-03-27 20:48:48 UTC
Using GCC 4.9.0 as of 20130327 :

$ cat ssa.c
int a, *b;

void f(void)
{
    if(a)
    {
        int k;

        for(a = 0; a < 1; a++)
        {
            int **q;
            f();

            for(; **q; ++**q)
lbl:
                if(a)
                {
                    a = 0;
                    goto lbl;
                }

            b = &k;
        }
    }
    goto lbl;
}

$ xgcc -O1 -w ssa.c
ssa.c: In function ‘f’:
ssa.c:3:6: error: definition in block 12 follows the use
 void f(void)
      ^
for SSA_NAME: _17 in statement:
# VUSE <.MEM_21>
D__lsm.5_2 = *_17;
ssa.c:3:6: internal compiler error: verify_ssa failed
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
Comment 1 Marek Polacek 2013-03-28 07:10:23 UTC
Confirmed.  Bisecting...
Comment 2 Marek Polacek 2013-03-28 07:38:04 UTC
Something goes wrong in LIM.
Comment 3 Richard Biener 2013-03-28 09:45:59 UTC
Mine.
Comment 4 Marek Polacek 2013-03-28 09:54:58 UTC
It seems that move_computations_stmt firstly inserts into bb 11
# VUSE <.MEM_21>
D__lsm.5 = *_17;
and then
# VUSE <.MEM_21>
_17 = *q_8(D);

move_computations then commits these inserts.
Comment 5 rguenther@suse.de 2013-03-28 10:07:29 UTC
On Thu, 28 Mar 2013, mpolacek at gcc dot gnu.org wrote:

> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56756
> 
> --- Comment #4 from Marek Polacek <mpolacek at gcc dot gnu.org> 2013-03-28 09:54:58 UTC ---
> It seems that move_computations_stmt firstly inserts into bb 11
> # VUSE <.MEM_21>
> D__lsm.5 = *_17;
> and then
> # VUSE <.MEM_21>
> _17 = *q_8(D);
> 
> move_computations then commits these inserts.

LIM relies on dom-walk to walk blocks in a order that processes
SSA definitions before uses.  But that is not what a dom-walk
guarantees ...
Comment 6 Marek Polacek 2013-03-28 10:11:55 UTC
FWIW, started with http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=196769
Comment 7 rguenther@suse.de 2013-03-28 10:26:48 UTC
On Thu, 28 Mar 2013, mpolacek at gcc dot gnu.org wrote:

> 
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56756
> 
> --- Comment #6 from Marek Polacek <mpolacek at gcc dot gnu.org> 2013-03-28 10:11:55 UTC ---
> FWIW, started with http://gcc.gnu.org/viewcvs/gcc?view=revision&revision=196769

Yes, I was expecting that.  This orders blocks in a different
"random" order when visiting dominator children.  It tries
to order them in inverted postorder - which is exactly deterministically
"wrong" for LIM, as it visits loop blocks with a loop exit edge
last.
Comment 8 Richard Biener 2013-03-28 12:34:24 UTC
Ok, so one reason is that we simply "ignore" dependencies when computing
what stmts to move (which happens in the same processing order):

static bool
add_dependency (tree def, struct lim_aux_data *data, struct loop *loop,
                bool add_cost)
{
...
  max_loop = outermost_invariant_loop (def, loop);
  if (!max_loop)
    return false;
...
  def_data = get_lim_data (def_stmt);
  if (!def_data)
    return true;

so, when we don't know anything about the stmt we depend on because we
didn't visit it yet outermost_invariant_loop returns garbage in this case.

But I got side-tracked by the above (which still should be fixed IMHO),
as also store-motion does not properly initialize dependence.
Comment 9 Richard Biener 2013-03-28 12:42:17 UTC
Created attachment 29744 [details]
patch

This patch makes us not rely on a dominator walk to magically get us process
stmts in the correct order but instead uses the dependences we record for
each stmt to make sure we moved them before uses.  And fixes things to
actually record all dependences (translating stmt to bb dependencies before
that walk may speed up things for some testcases, processing in a good
order from the start can avoid the recursion - processing stmts rather than
BBs with a worklist is another possibility - we should be able to "drain"
the depends vector into the worklist).
Comment 10 Richard Biener 2013-04-16 11:56:26 UTC
The issue is that

static void
execute_sm (struct loop *loop, vec<edge> exits, mem_ref_p ref)
{
...
  /* Emit the load code into the latch, so that we are sure it will
     be processed after all dependencies.  */
  latch_edge = loop_latch_edge (loop);

is no longer working.  It wasn't working by design before either.
We temporarily create

    <header> <-----------\
       |                 |
      if ()              |
     /   \               |
         _17 = *q_8(D);  |
     \   /               |
     D__lsm.5 = *_17;-----

that is invalid SSA form and expect a dominator walk to visit
_17 = *q_8(D) before visiting D__lsm.5 = *_17;

So a simpler fix than the attached one finds a better temporary
insertion place for D__lsm.5 =  *_17;

Placing the load at a random existing load or store would be the
best.  I'm reworking the patch to do that.
Comment 11 Richard Biener 2013-04-16 15:41:05 UTC
Author: rguenth
Date: Tue Apr 16 15:32:26 2013
New Revision: 198001

URL: http://gcc.gnu.org/viewcvs?rev=198001&root=gcc&view=rev
Log:
2013-04-16  Richard Biener  <rguenther@suse.de>

	PR tree-optimization/56756
	* tree-ssa-loop-im.c (struct first_mem_ref_loc_1): New functor.
	(first_mem_ref_loc): New.
	(execute_sm): Place the load temporarily before a previous
	access instead of in the latch edge to ensure its SSA dependencies
	are defined at points dominating the load.

	* gcc.dg/torture/pr56756.c: New testcase.

Added:
    trunk/gcc/testsuite/gcc.dg/torture/pr56756.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-ssa-loop-im.c