Skip to content

Commit

Permalink
more inlining of delegates
Browse files Browse the repository at this point in the history
  • Loading branch information
WalterBright committed Oct 2, 2015
1 parent e779ffc commit 6ad132d
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 16 deletions.
3 changes: 2 additions & 1 deletion src/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -2120,7 +2120,8 @@ extern (C++) Expression castTo(Expression e, Scope* sc, Type t)
int offset;
if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
e.error("%s", msg);
f.tookAddressOf++;
if (f != e.func) // if address not already marked as taken
f.tookAddressOf++;
result = new DelegateExp(e.loc, e.e1, f);
result.type = t;
return;
Expand Down
18 changes: 17 additions & 1 deletion src/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -1598,7 +1598,7 @@ extern (C++) bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type t
if (f)
{
f.tookAddressOf--;
//printf("tookAddressOf = %d\n", f->tookAddressOf);
//printf("--tookAddressOf = %d\n", f.tookAddressOf);
}
}
}
Expand Down Expand Up @@ -5848,6 +5848,14 @@ public:
{
v.visit(this);
}

override void printAST(int indent)
{
Expression.printAST(indent);
foreach (i; 0 .. indent + 2)
printf(" ");
printf(".var: %s\n", var ? var.toChars() : "");
}
}

/***********************************************************
Expand Down Expand Up @@ -8665,6 +8673,14 @@ public:
{
v.visit(this);
}

override void printAST(int indent)
{
UnaExp.printAST(indent);
foreach (i; 0 .. indent + 2)
printf(" ");
printf(".func: %s\n", func ? func.toChars() : "");
}
}

/***********************************************************
Expand Down
64 changes: 50 additions & 14 deletions src/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -1495,13 +1495,57 @@ public:
{
//printf("CallExp.inlineScan() %s\n", e.toChars());
FuncDeclaration fd;

void inlineFd()
{
if (fd && fd != parent && canInline(fd, false, false, asStatements))
{
expandInline(fd, parent, eret, null, e.arguments, asStatements, eresult, sresult, again);
}
}

/* Pattern match various ASTs looking for indirect function calls, delegate calls,
* function literal calls, delegate literal calls, and dot member calls.
* If so, and that is only assigned its _init.
* If so, do 'copy propagation' of the _init value and try to inline it.
*/
if (e.e1.op == TOKvar)
{
VarExp ve = cast(VarExp)e.e1;
fd = ve.var.isFuncDeclaration();
if (fd && fd != parent && canInline(fd, false, false, asStatements))
if (fd)
// delegate call
inlineFd();
else
{
expandInline(fd, parent, eret, null, e.arguments, asStatements, eresult, sresult, again);
// delegate literal call
auto v = ve.var.isVarDeclaration();
if (v && v._init && v.type.ty == Tdelegate && 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 == TOKdelegate);
fd = fld;
inlineFd();
}
else if (e2.op == TOKdelegate)
{
auto de = cast(DelegateExp)e2;
if (de.e1.op == TOKvar)
{
auto ve2 = cast(VarExp)de.e1;
fd = ve2.var.isFuncDeclaration();
inlineFd();
}
}
}
}
}
}
else if (e.e1.op == TOKdotvar)
Expand All @@ -1526,10 +1570,6 @@ 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))
Expand All @@ -1539,24 +1579,20 @@ public:
if (ei && ei.exp.op == TOKblit)
{
Expression e2 = (cast(AssignExp)ei.exp).e2;
// function pointer call
if (e2.op == TOKsymoff)
{
auto se = cast(SymOffExp)e2;
fd = se.var.isFuncDeclaration();
if (fd && fd != parent && canInline(fd, false, false, asStatements))
{
expandInline(fd, parent, eret, null, e.arguments, asStatements, eresult, sresult, again);
}
inlineFd();
}
// function literal call
else 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);
}
inlineFd();
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions test/runnable/inline.d
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,36 @@ void test9785_2() {
loop(&func);
}

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

void test9785_3() @nogc
{
int j = 3;

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

loop((x) @nogc {
pragma(inline, true);
//printf("%d\n", x + j * 2);
assert(x == 4);
assert(j == 4);
});

j = 3;
void func(int x) @nogc {
pragma(inline, true);
//printf("%d\n", x + j * 2);
assert(x == 4);
assert(j == 4);
}

loop(&func);
}

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

int main()
Expand Down Expand Up @@ -849,6 +879,7 @@ int main()
test7625();
test9785();
test9785_2();
test9785_3();

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

0 comments on commit 6ad132d

Please sign in to comment.