Skip to content

Commit

Permalink
Merge pull request #5136 from WalterBright/partial9785
Browse files Browse the repository at this point in the history
partial fix for 9785 - dmd -inline should inline lambda delegates
  • Loading branch information
andralex committed Sep 30, 2015
2 parents 44b7865 + b88e0cc commit 1f70049
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 7 deletions.
62 changes: 62 additions & 0 deletions src/inline.d
Expand Up @@ -1523,6 +1523,35 @@ public:
}
}
}
else if (e.e1.op == TOKstar &&
(cast(PtrExp)e.e1).e1.op == TOKvar)
{
/* See if calling function pointer, and that function pointer is only
* assigned its _init.
* If so, do 'copy propagation' of the _init value and try to inline it.
*/
VarExp ve = cast(VarExp)(cast(PtrExp)e.e1).e1;
VarDeclaration v = ve.var.isVarDeclaration();
if (v && v._init && onlyOneAssign(v, parent))
{
//printf("init: %s\n", v._init.toChars());
auto ei = v._init.isExpInitializer();
if (ei && ei.exp.op == TOKblit)
{
Expression e2 = (cast(AssignExp)ei.exp).e2;
if (e2.op == TOKfunction)
{
auto fld = (cast(FuncExp)e2).fd;
assert(fld.tok == TOKfunction);
fd = fld;
if (fd && fd != parent && canInline(fd, false, false, asStatements))
{
expandInline(fd, parent, eret, null, e.arguments, asStatements, eresult, sresult, again);
}
}
}
}
}
else
return;

Expand Down Expand Up @@ -2154,3 +2183,36 @@ public Expression inlineCopy(Expression e, Scope* sc)
scope ids = new InlineDoState(sc.parent, null);
return doInline(e, ids);
}

/*************************************
* Determine if v is 'head const', meaning
* that once it is initialized it is not changed
* again.
*
* This is done using a primitive flow analysis.
*
* v is head const if v is const or immutable.
* Otherwise, v is assumed to be head const unless one of the
* following is true:
* 1. v is a `ref` or `out` variable
* 2. v is a parameter and fd is a variadic function
* 3. v is assigned to again
* 4. the address of v is taken
* 5. v is referred to by a function nested within fd
* 6. v is ever assigned to a `ref` or `out` variable
* 7. v is ever passed to another function as `ref` or `out`
*
* Params:
* v variable to check
* fd function that v is local to
* Returns:
* true if v's initializer is the only value assigned to v
*/

bool onlyOneAssign(VarDeclaration v, FuncDeclaration fd)
{
if (!v.type.isMutable())
return true; // currently the only case handled atm
return false;
}

35 changes: 28 additions & 7 deletions test/runnable/inline.d
@@ -1,5 +1,5 @@

import std.stdio;
import core.stdc.stdio;

// Test function inlining

Expand Down Expand Up @@ -78,10 +78,10 @@ void func(void function () v)
void test4()
{
static void f1() { }

func(&f1);
//func(f1);
}
//func(f1);
}


/************************************/
Expand Down Expand Up @@ -116,7 +116,7 @@ struct Struct
void bar(out Struct Q)
{
if (foo() < 0)
Q = this;
Q = this;
}
}

Expand Down Expand Up @@ -747,7 +747,7 @@ struct S14975 {
void test14975() {
S14975 baz = 1;
if (baz.bar != 1)
assert(0);
assert(0);
}

/**********************************/
Expand Down Expand Up @@ -776,9 +776,29 @@ void test7625()
{
int x = foo7625(1);
if (x != 1)
assert(0);
assert(0);
}

/**********************************/
// 9785 partial fix

void test9785()
{
int j = 3;

void loop(scope const void function(int x) dg) {
pragma(inline, true);
dg(++j);
}

loop((x) {
pragma(inline, true);
printf("%d\n", x);
assert(x == 4);
});
}


/**********************************/

int main()
Expand Down Expand Up @@ -807,6 +827,7 @@ int main()
test14606();
test14975();
test7625();
test9785();

printf("Success\n");
return 0;
Expand Down

0 comments on commit 1f70049

Please sign in to comment.