D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 14214 - Internal error: backend/go.c 242
Summary: Internal error: backend/go.c 242
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 major
Assignee: No Owner
URL:
Keywords: ice
Depends on:
Blocks:
 
Reported: 2015-02-22 18:27 UTC by Mike Wey
Modified: 2020-03-21 03:56 UTC (History)
2 users (show)

See Also:


Attachments
Test case (3.37 KB, text/x-dsrc)
2015-02-22 18:27 UTC, Mike Wey
Details
hackfix (1.41 KB, patch)
2017-01-03 22:26 UTC, Ketmar Dark
Details | Diff

Note You need to log in before you can comment on or make changes to this issue.
Description Mike Wey 2015-02-22 18:27:48 UTC
Created attachment 1478 [details]
Test case

With the attached code dmd exits with an internal error, when compiling with optimizations on.

"dmd -O"

Commenting out line 13. or Making the Enum smaller the error no longer occurs.
Comment 1 Ketmar Dark 2015-02-22 21:54:01 UTC
this is general arch-independent optimiser bug, so i changed hardware section.
Comment 2 Kenji Hara 2015-06-22 07:03:25 UTC
Further reduced test case:

alias TypeTuple(T...) = T;
alias members = TypeTuple!(
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,
    0,  // error will disappear by removing one element
);

void main()
{
    int row = 0;
    foreach (_unused; members)  // copy the loop body 100 times
    {
        ++row;
        if (row)
            row = 0; // error triggered by this line.
    }
}

----------------------

The ICE seems happened by the assertion with incorrect assumption for "infinite loop check". But I'm not sure the correct iteration limit...

backend/go.c =======

    // Each pass through the loop can reduce only one level of comma expression.
    // The infinite loop check needs to take this into account.
    // Add 100 just to give optimizer more rope to try to converge.
    int iterationLimit = 0;
    for (b = startblock; b; b = b->Bnext)
    {
        if (!b->Belem)
            continue;
        int d = el_countCommas(b->Belem) + 100;
        if (d > iterationLimit)
            iterationLimit = d;
    }

    // Some functions can take enormous amounts of time to optimize.
    // We try to put a lid on it.
    starttime = clock();
    do
    {
        //printf("iter = %d\n", iter);
        if (++iter > 200)
        {   assert(iter < iterationLimit);      // infinite loop check
<-- the assert is on line 242
            break;
        }
Comment 3 Timothee Cour 2017-01-03 22:15:14 UTC
ping: hit this bug: https://github.com/gtkd-developers/GtkD/issues/176#issuecomment-270096196
Comment 4 Ketmar Dark 2017-01-03 22:26:48 UTC
Created attachment 1630 [details]
hackfix
Comment 5 Ketmar Dark 2017-01-03 22:29:28 UTC
the core issue is that optimizer is failed to distinguish comma expressions from enumerations, so it sees huge enumeration as alot of comma-expressions, tries to optimize that and fails. in my hackfix i just made optimizer to give up if it sees "alot of commas".
Comment 6 Timothee Cour 2017-01-03 22:50:17 UTC
NOTE: ldc doesn't have this issue and is faster; 
for this particular bug, a workaround as to use
```
s/foreach(_a; members)/foreach(_a; [members])/
```
but it won't work if types are distinct