Skip to content

Commit 982a1df

Browse files
committed
Rework branch handling in inliner
1 parent b59a8fb commit 982a1df

File tree

4 files changed

+230
-136
lines changed

4 files changed

+230
-136
lines changed

compiler/src/dmd/inline.d

Lines changed: 167 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -205,100 +205,153 @@ public:
205205
result = exp;
206206
}
207207

208-
override void visit(CompoundStatement s)
208+
static if (asStatements)
209+
alias StatementsResult = Statements*;
210+
else
211+
alias StatementsResult = Expression;
212+
213+
static StatementsResult statementsDoInline(Statements* stmts, InlineDoState ids)
209214
{
210-
//printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
211215
static if (asStatements)
212216
{
213-
auto as = new Statements();
214-
as.reserve(s.statements.length);
217+
auto result = new Statements();
218+
result.reserve(stmts.length);
219+
}
220+
else
221+
{
222+
Expression result;
215223
}
216224

217-
foreach (i, sx; *s.statements)
225+
foreach (i, sx; *stmts)
218226
{
219227
if (!sx)
220228
continue;
221-
static if (asStatements)
222-
{
223-
as.push(doInlineAs!Statement(sx, ids));
224-
}
225-
else
229+
230+
if (auto ifs = sx.isIfStatement())
226231
{
227-
/* Specifically allow:
228-
* if (condition)
229-
* return exp1;
230-
* return exp2;
231-
*/
232-
IfStatement ifs;
233-
Statement s3;
234-
if ((ifs = sx.isIfStatement()) !is null &&
235-
ifs.ifbody &&
236-
ifs.ifbody.endsWithReturnStatement() &&
237-
!ifs.elsebody &&
238-
i + 1 < s.statements.length &&
239-
(s3 = (*s.statements)[i + 1]) !is null &&
240-
s3.endsWithReturnStatement()
241-
)
232+
assert(!ifs.param);
233+
auto econd = doInlineAs!Expression(ifs.condition, ids);
234+
assert(econd);
235+
236+
ids.foundReturn = false;
237+
auto ifbody = doInlineAs!Result(ifs.ifbody, ids);
238+
bool ifReturned = ids.foundReturn;
239+
240+
ids.foundReturn = false;
241+
auto elsebody = doInlineAs!Result(ifs.elsebody, ids);
242+
bool elseReturned = ids.foundReturn;
243+
244+
if (ifReturned != elseReturned)
242245
{
243-
/* Rewrite as ?:
246+
/* One branch returns, but the other does not.
247+
* Merge the remaining statements in stmts into
248+
* the branch that does not return, and recurse.
244249
*/
245-
auto econd = doInlineAs!Expression(ifs.condition, ids);
246-
assert(econd);
247-
auto e1 = doInlineAs!Expression(ifs.ifbody, ids);
248-
assert(ids.foundReturn);
249-
auto e2 = doInlineAs!Expression(s3, ids);
250-
assert(e2);
251-
Expression e = new CondExp(econd.loc, econd, e1, e2);
252-
e.type = e1.type;
253-
if (e.type.ty == Ttuple)
250+
251+
if (elseReturned)
254252
{
255-
e1.type = Type.tvoid;
256-
e2.type = Type.tvoid;
257-
e.type = Type.tvoid;
253+
/* Rewrite
254+
* if (cond) stmt; else return exp;
255+
* into
256+
* if (!cond) return exp; else stmt;
257+
*/
258+
econd = new NotExp(econd.loc, econd);
259+
econd.type = Type.tbool;
260+
261+
auto tmp = ifbody;
262+
ifbody = elsebody;
263+
elsebody = tmp;
258264
}
259-
result = Expression.combine(result, e);
265+
266+
if (i < stmts.length - 1)
267+
{
268+
ids.foundReturn = false;
269+
scope rem = Statements((*stmts)[i + 1 .. $]);
270+
auto rembody = statementsDoInline(&rem, ids);
271+
272+
static if (asStatements)
273+
{
274+
/* Rewrite
275+
* if (cond) return exp; else stmt1; stmt2;
276+
* into
277+
* if (cond) return exp; else { { stmt1; } stmt2; }
278+
*/
279+
auto ss = new ScopeStatement(ifs.loc, elsebody, ifs.endloc);
280+
auto cs = new CompoundStatement(ifs.loc, ss);
281+
cs.statements.append(rembody);
282+
elsebody = cs;
283+
}
284+
else
285+
{
286+
elsebody = Expression.combine(elsebody, rembody);
287+
}
288+
}
289+
290+
ids.foundReturn = true;
291+
292+
static if (asStatements)
293+
{
294+
auto s = new IfStatement(ifs.loc, ifs.param, econd, ifbody, elsebody, ifs.endloc);
295+
result.push(s);
296+
}
297+
else
298+
{
299+
auto e = buildBranchExp(econd, ifbody, elsebody);
300+
result = Expression.combine(result, e);
301+
}
302+
303+
return result;
304+
}
305+
306+
ids.foundReturn = ifReturned && elseReturned;
307+
308+
static if (asStatements)
309+
{
310+
auto s = new IfStatement(ifs.loc, ifs.param, econd, ifbody, elsebody, ifs.endloc);
311+
result.push(s);
260312
}
261313
else
262314
{
263-
ids.foundReturn = false;
264-
auto e = doInlineAs!Expression(sx, ids);
315+
auto e = buildBranchExp(econd, ifbody, elsebody);
265316
result = Expression.combine(result, e);
266317
}
267318
}
319+
else
320+
{
321+
ids.foundReturn = false;
322+
323+
auto r = doInlineAs!Result(sx, ids);
324+
static if (asStatements)
325+
result.push(r);
326+
else
327+
result = Expression.combine(result, r);
328+
}
268329

269330
if (ids.foundReturn)
270331
break;
271332
}
272333

334+
return result;
335+
}
336+
337+
override void visit(CompoundStatement s)
338+
{
339+
//printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
340+
auto r = statementsDoInline(s.statements, ids);
273341
static if (asStatements)
274-
result = new CompoundStatement(s.loc, as);
342+
result = new CompoundStatement(s.loc, r);
343+
else
344+
result = r;
275345
}
276346

277347
override void visit(UnrolledLoopStatement s)
278348
{
279349
//printf("UnrolledLoopStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
350+
auto r = statementsDoInline(s.statements, ids);
280351
static if (asStatements)
281-
{
282-
auto as = new Statements();
283-
as.reserve(s.statements.length);
284-
}
285-
286-
foreach (sx; *s.statements)
287-
{
288-
if (!sx)
289-
continue;
290-
auto r = doInlineAs!Result(sx, ids);
291-
static if (asStatements)
292-
as.push(r);
293-
else
294-
result = Expression.combine(result, r);
295-
296-
if (ids.foundReturn)
297-
break;
298-
}
299-
300-
static if (asStatements)
301-
result = new UnrolledLoopStatement(s.loc, as);
352+
result = new UnrolledLoopStatement(s.loc, r);
353+
else
354+
result = r;
302355
}
303356

304357
override void visit(ScopeStatement s)
@@ -317,47 +370,23 @@ public:
317370
auto econd = doInlineAs!Expression(s.condition, ids);
318371
assert(econd);
319372

373+
ids.foundReturn = false;
320374
auto ifbody = doInlineAs!Result(s.ifbody, ids);
321-
bool bodyReturn = ids.foundReturn;
375+
bool ifReturned = ids.foundReturn;
322376

323377
ids.foundReturn = false;
324378
auto elsebody = doInlineAs!Result(s.elsebody, ids);
379+
bool elseReturned = ids.foundReturn;
380+
381+
// Top-level if statements should have been handled in statementsDoInline().
382+
// Here we're handling nested if statements, which must be symmetrical.
383+
assert(ifReturned == elseReturned);
384+
ids.foundReturn = ifReturned && elseReturned;
325385

326386
static if (asStatements)
327-
{
328387
result = new IfStatement(s.loc, s.param, econd, ifbody, elsebody, s.endloc);
329-
}
330388
else
331-
{
332-
alias e1 = ifbody;
333-
alias e2 = elsebody;
334-
if (e1 && e2)
335-
{
336-
result = new CondExp(econd.loc, econd, e1, e2);
337-
result.type = e1.type;
338-
if (result.type.ty == Ttuple)
339-
{
340-
e1.type = Type.tvoid;
341-
e2.type = Type.tvoid;
342-
result.type = Type.tvoid;
343-
}
344-
}
345-
else if (e1)
346-
{
347-
result = new LogicalExp(econd.loc, EXP.andAnd, econd, e1);
348-
result.type = Type.tvoid;
349-
}
350-
else if (e2)
351-
{
352-
result = new LogicalExp(econd.loc, EXP.orOr, econd, e2);
353-
result.type = Type.tvoid;
354-
}
355-
else
356-
{
357-
result = econd;
358-
}
359-
}
360-
ids.foundReturn = ids.foundReturn && bodyReturn;
389+
result = buildBranchExp(econd, ifbody, elsebody);
361390
}
362391

363392
override void visit(ReturnStatement s)
@@ -2619,3 +2648,45 @@ private bool expNeedsDtor(Expression exp)
26192648
scope NeedsDtor ct = new NeedsDtor(exp);
26202649
return walkPostorder(exp, ct);
26212650
}
2651+
2652+
/***********************************************************
2653+
* Build an expression with the semantics of
2654+
* if (econd) e1; else e2;
2655+
*/
2656+
Expression buildBranchExp(Expression econd, Expression e1, Expression e2)
2657+
{
2658+
if (e1 && e2)
2659+
{
2660+
auto ce = new CondExp(econd.loc, econd, e1, e2);
2661+
2662+
if (e1.type.ty == Tvoid || e2.type.ty == Tvoid)
2663+
ce.type = Type.tvoid;
2664+
else if (e1.type.ty == Tnoreturn)
2665+
ce.type = e2.type;
2666+
else
2667+
ce.type = e1.type;
2668+
2669+
if (ce.type.ty == Ttuple)
2670+
{
2671+
ce.e1.type = Type.tvoid;
2672+
ce.e2.type = Type.tvoid;
2673+
ce.type = Type.tvoid;
2674+
}
2675+
2676+
return ce;
2677+
}
2678+
else if (e1)
2679+
{
2680+
auto le = new LogicalExp(econd.loc, EXP.andAnd, econd, e1);
2681+
le.type = Type.tvoid;
2682+
return le;
2683+
}
2684+
else if (e2)
2685+
{
2686+
auto le = new LogicalExp(econd.loc, EXP.orOr, econd, e2);
2687+
le.type = Type.tvoid;
2688+
return le;
2689+
}
2690+
2691+
return econd;
2692+
}

0 commit comments

Comments
 (0)