Commit f6bb36ec by Iain Buclaw

d: Merge upstream dmd 8508c4e68.

Fixes a performance bug where 'static foreach' would take an
exponentially long time to expand during CTFE.

In the following example:

    static foreach (i; 0..30000) {}

Compilation time had been reduced from around 40 to 0.08 seconds.
Memory consumption is also reduced from 3.5GB to 55MB.

Reviewed-on: https://github.com/dlang/dmd/pull/11335

gcc/d/ChangeLog:

	* dmd/cond.c (lowerArrayAggregate): Directly use the elements of the
	array for TupleExp creation.
	(lowerNonArrayAggregate): Inline creation of foreach range indexes.

(cherry picked from commit ce56fd949f359a62b86a45aaf975ac2ecc48fa64)
parent c3bf482a
...@@ -92,13 +92,24 @@ static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc) ...@@ -92,13 +92,24 @@ static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc)
el = el->ctfeInterpret(); el = el->ctfeInterpret();
if (el->op == TOKint64) if (el->op == TOKint64)
{ {
dinteger_t length = el->toInteger(); Expressions *es;
Expressions *es = new Expressions(); if (aggr->op == TOKarrayliteral)
for (size_t i = 0; i < length; i++)
{ {
IntegerExp *index = new IntegerExp(sfe->loc, i, Type::tsize_t); // Directly use the elements of the array for the TupleExp creation
Expression *value = new IndexExp(aggr->loc, aggr, index); ArrayLiteralExp *ale = (ArrayLiteralExp *)aggr;
es->push(value); es = ale->elements;
}
else
{
size_t length = (size_t)el->toInteger();
es = new Expressions();
es->setDim(length);
for (size_t i = 0; i < length; i++)
{
IntegerExp *index = new IntegerExp(sfe->loc, i, Type::tsize_t);
Expression *value = new IndexExp(aggr->loc, aggr, index);
(*es)[i] = value;
}
} }
sfe->aggrfe->aggr = new TupleExp(aggr->loc, es); sfe->aggrfe->aggr = new TupleExp(aggr->loc, es);
sfe->aggrfe->aggr = semantic(sfe->aggrfe->aggr, sc); sfe->aggrfe->aggr = semantic(sfe->aggrfe->aggr, sc);
...@@ -307,13 +318,50 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc) ...@@ -307,13 +318,50 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
Expression *catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]); Expression *catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
s2->push(createForeach(sfe, aloc, pparams[1], new ExpStatement(aloc, catass))); s2->push(createForeach(sfe, aloc, pparams[1], new ExpStatement(aloc, catass)));
s2->push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres))); s2->push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
Expression *aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
sc = sc->startCTFE(); Expression *aggr;
aggr = semantic(aggr, sc); Type *indexty;
aggr = resolveProperties(sc, aggr);
sc = sc->endCTFE(); if (sfe->rangefe && (indexty = ety->semantic(aloc, sc))->isintegral())
aggr = aggr->optimize(WANTvalue); {
aggr = aggr->ctfeInterpret(); sfe->rangefe->lwr->type = indexty;
sfe->rangefe->upr->type = indexty;
IntRange lwrRange = getIntRange(sfe->rangefe->lwr);
IntRange uprRange = getIntRange(sfe->rangefe->upr);
const dinteger_t lwr = sfe->rangefe->lwr->toInteger();
dinteger_t upr = sfe->rangefe->upr->toInteger();
size_t length = 0;
if (lwrRange.imin <= uprRange.imax)
length = (size_t)(upr - lwr);
Expressions *exps = new Expressions();
exps->setDim(length);
if (sfe->rangefe->op == TOKforeach)
{
for (size_t i = 0; i < length; i++)
(*exps)[i] = new IntegerExp(aloc, lwr + i, indexty);
}
else
{
--upr;
for (size_t i = 0; i < length; i++)
(*exps)[i] = new IntegerExp(aloc, upr - i, indexty);
}
aggr = new ArrayLiteralExp(aloc, indexty->arrayOf(), exps);
}
else
{
aggr = wrapAndCall(aloc, new CompoundStatement(aloc, s2));
sc = sc->startCTFE();
aggr = semantic(aggr, sc);
aggr = resolveProperties(sc, aggr);
sc = sc->endCTFE();
aggr = aggr->optimize(WANTvalue);
aggr = aggr->ctfeInterpret();
}
assert(!!sfe->aggrfe ^ !!sfe->rangefe); assert(!!sfe->aggrfe ^ !!sfe->rangefe);
sfe->aggrfe = new ForeachStatement(sfe->loc, TOKforeach, pparams[2], aggr, sfe->aggrfe = new ForeachStatement(sfe->loc, TOKforeach, pparams[2], aggr,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment