mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 04:43:26 +03:00
Rewriting MiniIRPass processing to queue - much easier for profiling each mini pass
This commit is contained in:
parent
c84e8815f1
commit
0964711ba9
@ -1,54 +1,89 @@
|
||||
package org.enso.compiler.pass;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import org.enso.compiler.core.IR;
|
||||
import org.enso.compiler.core.ir.Expression;
|
||||
import org.enso.compiler.core.ir.Module;
|
||||
|
||||
/** Implementation of {@link MiniIRPass#compile}. */
|
||||
final class MiniPassTraverser {
|
||||
private MiniPassTraverser() {}
|
||||
private final MiniIRPass miniPass;
|
||||
private List<IR> in;
|
||||
private final List<IR> out;
|
||||
private int outIndex;
|
||||
|
||||
static IR compileRecursively(IR ir, MiniIRPass miniPass) {
|
||||
var preparedMiniPass =
|
||||
switch (ir) {
|
||||
case Module m -> miniPass.prepareForModule(m);
|
||||
case Expression e -> miniPass.prepare(e);
|
||||
default -> throw new IllegalArgumentException("" + ir);
|
||||
};
|
||||
IR newIr;
|
||||
var childExpressions = new ArrayList<Expression>();
|
||||
private MiniPassTraverser(MiniIRPass miniPass, List<IR> out, int outIndex) {
|
||||
this.miniPass = miniPass;
|
||||
this.out = out;
|
||||
this.outIndex = outIndex;
|
||||
}
|
||||
|
||||
private boolean enqueue(Collection<MiniPassTraverser> queue) {
|
||||
if (in == null) {
|
||||
var ir = out.get(outIndex);
|
||||
in = enqueueSubExpressions(queue, ir, miniPass);
|
||||
return !in.isEmpty();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void convertExpression() {
|
||||
if (outIndex != -1) {
|
||||
var oldIr = out.get(outIndex);
|
||||
var index = new int[1];
|
||||
var newIr = oldIr.mapExpressions((old) -> (Expression) in.get(index[0]++));
|
||||
var transformedIr =
|
||||
switch (newIr) {
|
||||
case Module m -> miniPass.transformModule(m);
|
||||
case Expression e -> miniPass.transformExpression(e);
|
||||
default -> throw new IllegalArgumentException("" + oldIr);
|
||||
};
|
||||
if (oldIr != transformedIr) {
|
||||
out.set(outIndex, transformedIr);
|
||||
}
|
||||
outIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
static IR compileDeep(IR root, MiniIRPass miniPass) {
|
||||
var result = new IR[] {root};
|
||||
var rootTask = new MiniPassTraverser(miniPass, Arrays.asList(result), 0);
|
||||
var stackOfPendingIrs = new LinkedList<MiniPassTraverser>();
|
||||
stackOfPendingIrs.add(rootTask);
|
||||
while (!stackOfPendingIrs.isEmpty()) {
|
||||
if (stackOfPendingIrs.peekLast().enqueue(stackOfPendingIrs)) {
|
||||
// continue descent
|
||||
continue;
|
||||
}
|
||||
var deepestIr = stackOfPendingIrs.removeLast();
|
||||
deepestIr.convertExpression();
|
||||
}
|
||||
assert result[0] != null;
|
||||
return result[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param queue queue to put objects in
|
||||
* @param ir IR to process
|
||||
* @param miniPass process with this mini pass
|
||||
* @return {@code true} if the has been modified with new tries to process first
|
||||
*/
|
||||
private static List<IR> enqueueSubExpressions(
|
||||
Collection<MiniPassTraverser> queue, IR ir, MiniIRPass miniPass) {
|
||||
var childExpressions = new ArrayList<IR>();
|
||||
var i = new int[1];
|
||||
ir.mapExpressions(
|
||||
(ch) -> {
|
||||
var preparedMiniPass = miniPass.prepare(ir, ch);
|
||||
childExpressions.add(ch);
|
||||
queue.add(new MiniPassTraverser(preparedMiniPass, childExpressions, i[0]++));
|
||||
return ch;
|
||||
});
|
||||
if (childExpressions.isEmpty()) {
|
||||
newIr = ir;
|
||||
} else {
|
||||
var changed = false;
|
||||
for (var i = 0; i < childExpressions.size(); i++) {
|
||||
var child = childExpressions.get(i);
|
||||
var newChild = (Expression) compileRecursively(child, preparedMiniPass);
|
||||
if (child == newChild) {
|
||||
continue;
|
||||
}
|
||||
changed = true;
|
||||
childExpressions.set(i, newChild);
|
||||
}
|
||||
if (changed) {
|
||||
var index = new int[1];
|
||||
newIr = ir.mapExpressions((old) -> childExpressions.get(index[0]++));
|
||||
} else {
|
||||
newIr = ir;
|
||||
}
|
||||
}
|
||||
var transformedIr =
|
||||
switch (newIr) {
|
||||
case Module m -> miniPass.transformModule(m);
|
||||
case Expression e -> miniPass.transformExpression(e);
|
||||
default -> throw new IllegalArgumentException("" + newIr);
|
||||
};
|
||||
return transformedIr;
|
||||
return childExpressions;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user