Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions de.peeeq.wurstscript/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,8 @@ dependencies {
implementation "org.antlr:antlr4-runtime:4.13.1"

// abstractsyntaxgen (available to IDE via compileOnly; used at runtime via astgen)
compileOnly 'com.github.peterzeller:abstractsyntaxgen:623da1c60f'
astgen 'com.github.peterzeller:abstractsyntaxgen:623da1c60f'
compileOnly 'com.github.peterzeller:abstractsyntaxgen:2b3d742e8a'
astgen 'com.github.peterzeller:abstractsyntaxgen:2b3d742e8a'


// Tests
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,21 @@ public int optimize(ImTranslator trans, LocalPlayerContextAnalyzer analyzer) {
ImProg prog = trans.getImProg();
localPlayerContextAnalyzer = analyzer;
totalLocalsMerged = 0;
for (ImFunction func : de.peeeq.wurstscript.translation.imtranslation.ImHelper.calculateFunctionsOfProg(prog)) {
optimizeFunctions(prog.getFunctions());
List<ImClass> classes = prog.getClasses();
for (int i = 0; i < classes.size(); i++) {
optimizeFunctions(classes.get(i).getFunctions());
}
return totalLocalsMerged;
}

private void optimizeFunctions(List<ImFunction> functions) {
for (int i = 0; i < functions.size(); i++) {
ImFunction func = functions.get(i);
if (!func.isNative() && !func.isBj()) {
optimizeFunc(func);
}
}
return totalLocalsMerged;
}

@Override
Expand All @@ -54,21 +63,23 @@ private void mergeLocals(Map<ImStmt, Set<ImVar>> livenessInfo, ImFunction func)
);
queue.addAll(interference.keySet());

List<ImVar> params = new ArrayList<>(func.getParameters());
if (func.hasFlag(de.peeeq.wurstscript.translation.imtranslation.FunctionFlagEnum.IS_VARARG) && !params.isEmpty()) {
params.remove(params.size() - 1);
List<ImVar> colors = new ArrayList<>(func.getParameters());
if (func.hasFlag(de.peeeq.wurstscript.translation.imtranslation.FunctionFlagEnum.IS_VARARG) && !colors.isEmpty()) {
colors.remove(colors.size() - 1);
}
queue.removeAll(func.getParameters());

List<ImVar> colors = new ArrayList<>(params);
Map<ImVar, ImVar> merges = new LinkedHashMap<>();

while (!queue.isEmpty()) {
ImVar v = queue.poll();
boolean merged = false;

for (ImVar color : colors) {
if (!canMerge(color.getType(), v.getType())) continue;
for (int colorIndex = 0; colorIndex < colors.size(); colorIndex++) {
ImVar color = colors.get(colorIndex);
if (!canMerge(color.getType(), v.getType())) {
continue;
}
if (localPlayerContextAnalyzer != null
&& (localPlayerContextAnalyzer.isLocalPlayerDependent(v)
|| localPlayerContextAnalyzer.isLocalPlayerDependent(color))) {
Expand Down Expand Up @@ -110,7 +121,9 @@ private static void applyMerges(ImFunction func, Map<ImVar, ImVar> merges) {
}
@Override public void visit(ImVarargLoop varargLoop) {
super.visit(varargLoop);
for (ImVarargLoopVar loopVar : varargLoop.getLoopVars()) {
List<ImVarargLoopVar> loopVars = varargLoop.getLoopVars();
for (int i = 0; i < loopVars.size(); i++) {
ImVarargLoopVar loopVar = loopVars.get(i);
ImVar m = merges.get(loopVar.getVar());
if (m != null) loopVar.setVar(m);
}
Expand All @@ -127,13 +140,20 @@ private static int removeUnusedLocals(ImFunction f) {
@Override public void visit(ImVarArrayAccess vaa) { super.visit(vaa); used.add(vaa.getVar()); }
@Override public void visit(ImVarargLoop loop) {
super.visit(loop);
loop.getLoopVars().forEach(v -> used.add(v.getVar()));
for (int i = 0; i < loop.getLoopVars().size(); i++) {
used.add(loop.getLoopVars().get(i).getVar());
}
}
});
List<ImVar> locals = new ArrayList<>(f.getLocals());
List<ImVar> locals = f.getLocals();
int before = locals.size();
List<ImVar> kept = new ArrayList<>(locals.size());
for (ImVar v : locals) if (used.contains(v)) kept.add(v);
for (int i = 0; i < locals.size(); i++) {
ImVar v = locals.get(i);
if (used.contains(v)) {
kept.add(v);
}
}
if (kept.size() != locals.size()) { f.getLocals().clear(); f.getLocals().addAll(kept); }
return before - kept.size();
}
Expand Down Expand Up @@ -183,7 +203,8 @@ private void eliminateDeadCode(Map<ImStmt, Set<ImVar>> livenessInfo) {
AstEdits.deleteStmt(s); // remove the dead assignment entirely
} else {
ImStmts block = JassIm.ImStmts();
for (ImExpr e : raw) {
for (int i = 0; i < raw.size(); i++) {
ImExpr e = raw.get(i);
// wrap expression as a statement; add a *copy* to avoid re-parenting conflicts
block.add(ImHelper.statementExprVoid(e.copy()));
}
Expand All @@ -195,10 +216,22 @@ private void eliminateDeadCode(Map<ImStmt, Set<ImVar>> livenessInfo) {

private static void collectLhsSideEffects(ImLExpr lhs, List<ImExpr> out) {
if (lhs instanceof ImVarArrayAccess a) {
for (ImExpr idx : a.getIndexes()) if (hasSideEffects(idx)) out.add(idx);
ImExprs indexes = a.getIndexes();
for (int i = 0; i < indexes.size(); i++) {
ImExpr idx = indexes.get(i);
if (hasSideEffects(idx)) {
out.add(idx);
}
}
} else if (lhs instanceof ImMemberAccess m) {
if (hasSideEffects(m.getReceiver())) out.add(m.getReceiver());
for (ImExpr idx : m.getIndexes()) if (hasSideEffects(idx)) out.add(idx);
ImExprs indexes = m.getIndexes();
for (int i = 0; i < indexes.size(); i++) {
ImExpr idx = indexes.get(i);
if (hasSideEffects(idx)) {
out.add(idx);
}
}
} else if (lhs instanceof ImTupleSelection ts) {
Element t = ts.getTupleExpr();
if (hasSideEffects(t)) out.add((ImExpr) t);
Expand Down Expand Up @@ -255,7 +288,12 @@ public Map<ImStmt, Set<ImVar>> calculateLiveness(ImFunction func) {
@Override public void case_ImVarArrayAccess(ImVarArrayAccess e) { e.getIndexes().accept(me); }
@Override public void case_ImMemberAccess(ImMemberAccess e) { e.getReceiver().accept(me); e.getIndexes().accept(me); }
@Override public void case_ImStatementExpr(ImStatementExpr e) { e.getStatements().accept(me); ((ImLExpr) e.getExpr()).match(this); }
@Override public void case_ImTupleExpr(ImTupleExpr e) { for (ImExpr ex : e.getExprs()) ((ImLExpr) ex).match(this); }
@Override public void case_ImTupleExpr(ImTupleExpr e) {
ImExprs exprs = e.getExprs();
for (int i = 0; i < exprs.size(); i++) {
((ImLExpr) exprs.get(i)).match(this);
}
}
});
}
});
Expand Down Expand Up @@ -291,14 +329,16 @@ protected Collection<Node> getIncidentNodes(Node t) {
for (int i = 0; i < N; i++) { in[i] = new ObjectOpenHashSet<>(); out[i] = new ObjectOpenHashSet<>(); }

// 5. Iterate over SCCs in reverse topological order
for (List<Node> scc : sccs) {
for (int sccIndex = 0; sccIndex < sccs.size(); sccIndex++) {
List<Node> scc = sccs.get(sccIndex);
if (scc.isEmpty()) continue;

// Iterate within this SCC until a fixed point is reached for all its nodes.
boolean changedInScc = true;
while (changedInScc) {
changedInScc = false;
for (Node u_node : scc) {
for (int uIndex = 0; uIndex < scc.size(); uIndex++) {
Node u_node = scc.get(uIndex);
int u_idx = idx.getInt(u_node);

// Recalculate OUT[u] from the IN sets of its successors.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.peeeq.wurstscript.intermediatelang.optimizer;

import de.peeeq.wurstscript.jassIm.*;
import de.peeeq.wurstscript.translation.imtranslation.ImHelper;

import java.util.ArrayDeque;
import java.util.ArrayList;
Expand Down Expand Up @@ -161,7 +160,17 @@ public boolean isLocalPlayerSource(ImFunction function) {

private void analyze(ImProg prog) {
sourceFacts.add(unknownDispatchSource);
for (ImFunction function : ImHelper.calculateFunctionsOfProg(prog)) {
analyzeFunctions(prog.getFunctions());
List<ImClass> classes = prog.getClasses();
for (int i = 0; i < classes.size(); i++) {
analyzeFunctions(classes.get(i).getFunctions());
}
propagateFacts();
}

private void analyzeFunctions(List<ImFunction> functions) {
for (int i = 0; i < functions.size(); i++) {
ImFunction function = functions.get(i);
returnFact(function);
useFact(function);
if (isClientLocalValueSource(function)) {
Expand All @@ -171,7 +180,6 @@ private void analyze(ImProg prog) {
addDependency(function.getBody(), useFact(function));
}
}
propagateFacts();
}

private boolean methodReturnsLocalPlayerDependentValue(ImMethod method) {
Expand All @@ -181,8 +189,9 @@ private boolean methodReturnsLocalPlayerDependentValue(ImMethod method) {
if (localPlayerDependentReturns.contains(method.getImplementation())) {
return true;
}
for (ImMethod subMethod : method.getSubMethods()) {
if (methodReturnsLocalPlayerDependentValue(subMethod)) {
List<ImMethod> subMethods = method.getSubMethods();
for (int i = 0; i < subMethods.size(); i++) {
if (methodReturnsLocalPlayerDependentValue(subMethods.get(i))) {
return true;
}
}
Expand Down Expand Up @@ -259,9 +268,12 @@ private void indexElementAfterChildren(Element element, ImFunction owner, Object
} else if (element instanceof ImMemberAccess) {
addDependency(variableFact(((ImMemberAccess) element).getVar()), element);
} else if (element instanceof ImVarargLoop) {
ImVarargLoop loop = (ImVarargLoop) element;
ImVar varargParameter = varargParameter(owner);
if (varargParameter != null) {
for (ImVarargLoopVar loopVar : ((ImVarargLoop) element).getLoopVars()) {
List<ImVarargLoopVar> loopVars = loop.getLoopVars();
for (int i = 0; i < loopVars.size(); i++) {
ImVarargLoopVar loopVar = loopVars.get(i);
addDependency(variableFact(varargParameter), variableFact(loopVar.getVar()));
}
}
Expand Down Expand Up @@ -292,7 +304,8 @@ private void scheduleStatementSequence(ImStmts statements,
Deque<IndexTask> work) {
List<IndexTask> tasks = new ArrayList<>(statements.size());
Object continuationControl = controlContext;
for (ImStmt statement : statements) {
for (int i = 0; i < statements.size(); i++) {
ImStmt statement = statements.get(i);
addDependency(statement, statements);
tasks.add(new IndexTask(statement, continuationControl, false));

Expand Down Expand Up @@ -380,6 +393,8 @@ private void indexFunctionCall(ImFunctionCall call, ImFunction owner, Object con
ImFunction called = call.getFunc();
addDependency(returnFact(called), call);
addDependency(useFact(called), useFact(owner));
List<ImExpr> arguments = call.getArguments();
List<ImVar> calledParameters = called.getParameters();
if (!called.isNative()) {
addEnclosingControlDependency(controlContext, entryControlFact(called));
}
Expand All @@ -388,19 +403,20 @@ private void indexFunctionCall(ImFunctionCall call, ImFunction owner, Object con
addLocalPlayerSource(called);
}

int fixedParameterCount = called.getParameters().size();
int fixedParameterCount = calledParameters.size();
if (called.hasFlag(IS_VARARG) && fixedParameterCount > 0) {
fixedParameterCount--;
}
int positionalCount = Math.min(call.getArguments().size(), fixedParameterCount);
int argumentCount = arguments.size();
int positionalCount = Math.min(argumentCount, fixedParameterCount);
for (int i = 0; i < positionalCount; i++) {
addDependency(call.getArguments().get(i),
variableFact(called.getParameters().get(i)));
addDependency(arguments.get(i),
variableFact(calledParameters.get(i)));
}
ImVar varargParameter = varargParameter(called);
if (varargParameter != null) {
for (int i = fixedParameterCount; i < call.getArguments().size(); i++) {
addDependency(call.getArguments().get(i),
for (int i = fixedParameterCount; i < argumentCount; i++) {
addDependency(arguments.get(i),
variableFact(varargParameter));
}
}
Expand All @@ -425,14 +441,18 @@ private void indexMethodCall(ImMethodCall call, ImFunction owner, Object control
addDependency(unknownDispatchSource, useFact(owner));
}

List<ImExpr> arguments = call.getArguments();
for (ImFunction implementation : implementations) {
addDependency(returnFact(implementation), call);
addDependency(useFact(implementation), useFact(owner));
addEnclosingControlDependency(controlContext, entryControlFact(implementation));
for (ImVar parameter : implementation.getParameters()) {
addDependency(call.getReceiver(), variableFact(parameter));
for (ImExpr argument : call.getArguments()) {
addDependency(argument, variableFact(parameter));
Element receiver = call.getReceiver();
List<ImVar> parameters = implementation.getParameters();
for (int i = 0; i < parameters.size(); i++) {
ImVar parameter = parameters.get(i);
addDependency(receiver, variableFact(parameter));
for (int j = 0; j < arguments.size(); j++) {
addDependency(arguments.get(j), variableFact(parameter));
}
}
}
Expand Down Expand Up @@ -487,8 +507,9 @@ private boolean collectMethodImplementations(ImMethod method,
return method != null && method.getImplementation() != null;
}
implementations.add(method.getImplementation());
for (ImMethod subMethod : method.getSubMethods()) {
if (!collectMethodImplementations(subMethod, implementations, visited)) {
List<ImMethod> subMethods = method.getSubMethods();
for (int i = 0; i < subMethods.size(); i++) {
if (!collectMethodImplementations(subMethods.get(i), implementations, visited)) {
return false;
}
}
Expand All @@ -508,9 +529,11 @@ private void forEachAssignedVariable(ImLExpr left, Consumer<ImVar> consumer) {
forEachAssignedVariable((ImLExpr) tupleExpr, consumer);
}
} else if (left instanceof ImTupleExpr) {
for (ImExpr expr : ((ImTupleExpr) left).getExprs()) {
if (expr instanceof ImLExpr) {
forEachAssignedVariable((ImLExpr) expr, consumer);
ImExprs exprs = ((ImTupleExpr) left).getExprs();
for (int i = 0; i < exprs.size(); i++) {
ImExpr expr = exprs.get(i);
if (expr instanceof ImLExpr lExpr) {
forEachAssignedVariable(lExpr, consumer);
}
}
} else if (left instanceof ImStatementExpr) {
Expand Down Expand Up @@ -539,8 +562,11 @@ private void propagateFacts() {
}
while (!worklist.isEmpty()) {
Object fact = worklist.removeFirst();
for (Object dependent : dependents.getOrDefault(fact, Collections.emptyList())) {
activateFact(dependent, worklist);
List<Object> factDependents = dependents.get(fact);
if (factDependents != null) {
for (int i = 0; i < factDependents.size(); i++) {
activateFact(factDependents.get(i), worklist);
}
}
}
}
Expand Down
Loading
Loading