Skip to content

Commit 1b8446e

Browse files
committed
Allow one layer of unbalanced if to be inlined
1 parent 05a62c8 commit 1b8446e

3 files changed

Lines changed: 204 additions & 137 deletions

File tree

compiler/src/dmd/inline.d

Lines changed: 149 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ public:
146146

147147
enum asStatements = is(Result == Statement);
148148

149+
static if (asStatements)
150+
alias StatementsResult = Statements;
151+
else
152+
alias StatementsResult = Expression;
153+
149154
extern (D) this(InlineDoState ids) scope
150155
{
151156
this.ids = ids;
@@ -175,100 +180,173 @@ public:
175180
result = exp;
176181
}
177182

178-
override void visit(CompoundStatement s)
183+
static Result buildConditional(Loc loc, Expression econd, Result e1, Result e2, Loc endloc)
179184
{
180-
//printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
181185
static if (asStatements)
182186
{
183-
auto as = Statements();
184-
as.reserve(s.statements.length);
187+
return new IfStatement(loc, null, econd, e1, e2, endloc);
185188
}
186-
187-
foreach (i, sx; s.statements)
189+
else
188190
{
189-
if (!sx)
190-
continue;
191-
static if (asStatements)
192-
{
193-
as.push(doInlineAs!Statement(sx, ids));
194-
}
195-
else
191+
if (e1 && e2)
196192
{
197-
/* Specifically allow:
198-
* if (condition)
199-
* return exp1;
200-
* return exp2;
201-
*/
202-
IfStatement ifs;
203-
Statement s3;
204-
if ((ifs = sx.isIfStatement()) !is null &&
205-
ifs.ifbody &&
206-
ifs.ifbody.endsWithReturnStatement() &&
207-
!ifs.elsebody &&
208-
i + 1 < s.statements.length &&
209-
(s3 = s.statements[i + 1]) !is null &&
210-
s3.endsWithReturnStatement()
211-
)
212-
{
213-
/* Rewrite as ?:
214-
*/
215-
auto econd = doInlineAs!Expression(ifs.condition, ids);
216-
assert(econd);
217-
auto e1 = doInlineAs!Expression(ifs.ifbody, ids);
218-
assert(ids.foundReturn);
219-
auto e2 = doInlineAs!Expression(s3, ids);
220-
assert(e2);
221-
Expression e = new CondExp(econd.loc, econd, e1, e2);
222-
e.type = e1.type;
223-
if (e.type.ty == Ttuple)
224-
{
225-
e1.type = Type.tvoid;
226-
e2.type = Type.tvoid;
227-
e.type = Type.tvoid;
228-
}
229-
result = combineInlineSequence(result, e);
230-
}
193+
auto ce = new CondExp(loc, econd, e1, e2);
194+
195+
if (e1.type.ty == Tvoid || e2.type.ty == Tvoid)
196+
ce.type = Type.tvoid;
197+
else if (e1.type.ty == Tnoreturn)
198+
ce.type = e2.type;
231199
else
200+
ce.type = e1.type;
201+
202+
if (ce.type.ty == Ttuple)
232203
{
233-
ids.foundReturn = false;
234-
auto e = doInlineAs!Expression(sx, ids);
235-
result = combineInlineSequence(result, e);
204+
ce.e1.type = Type.tvoid;
205+
ce.e2.type = Type.tvoid;
206+
ce.type = Type.tvoid;
236207
}
208+
209+
return ce;
210+
}
211+
else if (e1)
212+
{
213+
auto le = new LogicalExp(loc, EXP.andAnd, econd, e1);
214+
le.type = Type.tvoid;
215+
return le;
216+
}
217+
else if (e2)
218+
{
219+
auto le = new LogicalExp(loc, EXP.orOr, econd, e2);
220+
le.type = Type.tvoid;
221+
return le;
237222
}
238223

239-
if (ids.foundReturn)
240-
break;
224+
return econd;
241225
}
242-
243-
static if (asStatements)
244-
result = new CompoundStatement(s.loc, as.move());
245226
}
246227

247-
override void visit(UnrolledLoopStatement s)
228+
StatementsResult statementsDoInline(ref scope Statements stmts)
248229
{
249-
//printf("UnrolledLoopStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
250230
static if (asStatements)
251231
{
252-
auto as = Statements();
253-
as.reserve(s.statements.length);
232+
Statements result;
233+
result.reserve(stmts.length);
234+
}
235+
else
236+
{
237+
Expression result;
254238
}
255239

256-
foreach (sx; s.statements)
240+
foreach (i, sx; stmts)
257241
{
258242
if (!sx)
259243
continue;
260-
auto r = doInlineAs!Result(sx, ids);
244+
245+
Result r;
246+
247+
if (auto ifs = sx.isIfStatement())
248+
{
249+
assert(!ifs.param);
250+
auto econd = doInlineAs!Expression(ifs.condition, ids);
251+
assert(econd);
252+
253+
ids.foundReturn = false;
254+
auto ifbody = doInlineAs!Result(ifs.ifbody, ids);
255+
bool ifReturned = ids.foundReturn;
256+
257+
ids.foundReturn = false;
258+
auto elsebody = doInlineAs!Result(ifs.elsebody, ids);
259+
bool elseReturned = ids.foundReturn;
260+
261+
ids.foundReturn = ifReturned && elseReturned;
262+
263+
if (ifReturned != elseReturned)
264+
{
265+
/* One branch returns, but the other does not.
266+
* Merge the remaining statements in stmts into
267+
* the branch that does not return, and recurse.
268+
*/
269+
270+
if (elseReturned)
271+
{
272+
/* Rewrite
273+
* if (cond) stmt; else return exp;
274+
* into
275+
* if (!cond) return exp; else stmt;
276+
*/
277+
econd = new NotExp(econd.loc, econd);
278+
econd.type = Type.tbool;
279+
280+
auto tmp = ifbody;
281+
ifbody = elsebody;
282+
elsebody = tmp;
283+
}
284+
285+
if (i < stmts.length - 1)
286+
{
287+
ids.foundReturn = false;
288+
scope rem = Statements(stmts[i + 1 .. $]);
289+
auto rembody = statementsDoInline(rem);
290+
291+
static if (asStatements)
292+
{
293+
/* Rewrite
294+
* if (cond) return exp; else stmt1; stmt2;
295+
* into
296+
* if (cond) return exp; else { { stmt1; } stmt2; }
297+
*/
298+
auto ss = new ScopeStatement(ifs.loc, elsebody, ifs.endloc);
299+
auto cs = new CompoundStatement(ifs.loc, ss);
300+
cs.statements.append(&rembody);
301+
elsebody = cs;
302+
}
303+
else
304+
{
305+
elsebody = combineInlineSequence(elsebody, rembody);
306+
}
307+
}
308+
309+
ids.foundReturn = true;
310+
}
311+
312+
r = buildConditional(ifs.loc, econd, ifbody, elsebody, ifs.endloc);
313+
}
314+
else
315+
{
316+
ids.foundReturn = false;
317+
r = doInlineAs!Result(sx, ids);
318+
}
319+
261320
static if (asStatements)
262-
as.push(r);
321+
result.push(r);
263322
else
264323
result = combineInlineSequence(result, r);
265324

266325
if (ids.foundReturn)
267326
break;
268327
}
269328

329+
return result;
330+
}
331+
332+
override void visit(CompoundStatement s)
333+
{
334+
//printf("CompoundStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
335+
auto r = statementsDoInline(s.statements);
270336
static if (asStatements)
271-
result = new UnrolledLoopStatement(s.loc, as.move());
337+
result = new CompoundStatement(s.loc, r.move());
338+
else
339+
result = r;
340+
}
341+
342+
override void visit(UnrolledLoopStatement s)
343+
{
344+
//printf("UnrolledLoopStatement.doInlineAs!%s() %d\n", Result.stringof.ptr, s.statements.length);
345+
auto r = statementsDoInline(s.statements);
346+
static if (asStatements)
347+
result = new UnrolledLoopStatement(s.loc, r.move());
348+
else
349+
result = r;
272350
}
273351

274352
override void visit(ScopeStatement s)
@@ -287,47 +365,19 @@ public:
287365
auto econd = doInlineAs!Expression(s.condition, ids);
288366
assert(econd);
289367

368+
ids.foundReturn = false;
290369
auto ifbody = doInlineAs!Result(s.ifbody, ids);
291-
bool bodyReturn = ids.foundReturn;
370+
bool ifReturned = ids.foundReturn;
292371

293372
ids.foundReturn = false;
294373
auto elsebody = doInlineAs!Result(s.elsebody, ids);
374+
bool elseReturned = ids.foundReturn;
295375

296-
static if (asStatements)
297-
{
298-
result = new IfStatement(s.loc, s.param, econd, ifbody, elsebody, s.endloc);
299-
}
300-
else
301-
{
302-
alias e1 = ifbody;
303-
alias e2 = elsebody;
304-
if (e1 && e2)
305-
{
306-
result = new CondExp(econd.loc, econd, e1, e2);
307-
result.type = e1.type;
308-
if (result.type.ty == Ttuple)
309-
{
310-
e1.type = Type.tvoid;
311-
e2.type = Type.tvoid;
312-
result.type = Type.tvoid;
313-
}
314-
}
315-
else if (e1)
316-
{
317-
result = new LogicalExp(econd.loc, EXP.andAnd, econd, e1);
318-
result.type = Type.tvoid;
319-
}
320-
else if (e2)
321-
{
322-
result = new LogicalExp(econd.loc, EXP.orOr, econd, e2);
323-
result.type = Type.tvoid;
324-
}
325-
else
326-
{
327-
result = econd;
328-
}
329-
}
330-
ids.foundReturn = ids.foundReturn && bodyReturn;
376+
// Top-level if statements should have been handled in statementsDoInline().
377+
// Here we're handling nested if statements, which must be symmetrical.
378+
assert(ifReturned == elseReturned);
379+
ids.foundReturn = ifReturned && elseReturned;
380+
result = buildConditional(s.loc, econd, ifbody, elsebody, s.endloc);
331381
}
332382

333383
override void visit(ReturnStatement s)

0 commit comments

Comments
 (0)