implements PR-O2.3
This commit is contained in:
parent
804fc27959
commit
7679c5eeeb
@ -1,14 +1,25 @@
|
|||||||
package p.studio.compiler.backend.irvm;
|
package p.studio.compiler.backend.irvm;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
public class OptimizeIRVMService {
|
public class OptimizeIRVMService {
|
||||||
private final IRVMValidator validator;
|
private final IRVMValidator validator;
|
||||||
|
private final List<IRVMPass> passes;
|
||||||
|
|
||||||
public OptimizeIRVMService() {
|
public OptimizeIRVMService() {
|
||||||
this(new IRVMValidator());
|
this(new IRVMValidator(), List.of(new NoOpPass()));
|
||||||
}
|
}
|
||||||
|
|
||||||
OptimizeIRVMService(final IRVMValidator validator) {
|
OptimizeIRVMService(final IRVMValidator validator) {
|
||||||
|
this(validator, List.of(new NoOpPass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
OptimizeIRVMService(
|
||||||
|
final IRVMValidator validator,
|
||||||
|
final List<IRVMPass> passes) {
|
||||||
this.validator = validator;
|
this.validator = validator;
|
||||||
|
this.passes = passes == null ? List.of(new NoOpPass()) : List.copyOf(passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IRVMProgram optimize(final IRVMProgram input) {
|
public IRVMProgram optimize(final IRVMProgram input) {
|
||||||
@ -16,11 +27,41 @@ public class OptimizeIRVMService {
|
|||||||
if (!"core-v1".equals(program.module().vmProfile())) {
|
if (!"core-v1".equals(program.module().vmProfile())) {
|
||||||
throw new IllegalArgumentException("unsupported vm profile: " + program.module().vmProfile());
|
throw new IllegalArgumentException("unsupported vm profile: " + program.module().vmProfile());
|
||||||
}
|
}
|
||||||
validator.validate(program.module(), false);
|
var current = program;
|
||||||
// Baseline pass manager: no-op pass preserving semantic shape.
|
validator.validate(current.module(), false);
|
||||||
final var optimized = program;
|
for (final var pass : passes) {
|
||||||
validator.validate(optimized.module(), false);
|
if (pass == null || !pass.enabled()) {
|
||||||
return optimized;
|
continue;
|
||||||
}
|
}
|
||||||
|
final var beforeProfile = current.module().vmProfile();
|
||||||
|
current = Objects.requireNonNull(pass.apply(current), "pass output");
|
||||||
|
if (!beforeProfile.equals(current.module().vmProfile())) {
|
||||||
|
throw new IllegalArgumentException("pass changed vm profile: " + pass.name());
|
||||||
|
}
|
||||||
|
validator.validate(current.module(), false);
|
||||||
|
}
|
||||||
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface IRVMPass {
|
||||||
|
String name();
|
||||||
|
|
||||||
|
default boolean enabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IRVMProgram apply(IRVMProgram input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class NoOpPass implements IRVMPass {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "NoOpPass";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IRVMProgram apply(final IRVMProgram input) {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -0,0 +1,94 @@
|
|||||||
|
package p.studio.compiler.backend.irvm;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import p.studio.utilities.structures.ReadOnlyList;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
class OptimizeIRVMServiceTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void optimizeMustExecuteEnabledPassesInDeclaredOrder() {
|
||||||
|
final var order = new ArrayList<String>();
|
||||||
|
final var service = new OptimizeIRVMService(new IRVMValidator(), List.of(
|
||||||
|
namedPass("A", order, true),
|
||||||
|
namedPass("B", order, true)));
|
||||||
|
|
||||||
|
final var output = service.optimize(validProgram());
|
||||||
|
|
||||||
|
assertEquals(validProgram(), output);
|
||||||
|
assertEquals(List.of("A", "B"), order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void optimizeMustSkipDisabledPasses() {
|
||||||
|
final var order = new ArrayList<String>();
|
||||||
|
final var service = new OptimizeIRVMService(new IRVMValidator(), List.of(
|
||||||
|
namedPass("A", order, false),
|
||||||
|
namedPass("B", order, true)));
|
||||||
|
|
||||||
|
service.optimize(validProgram());
|
||||||
|
|
||||||
|
assertEquals(List.of("B"), order);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void optimizeMustRejectPassThatMutatesVmProfile() {
|
||||||
|
final var service = new OptimizeIRVMService(new IRVMValidator(), List.of(new OptimizeIRVMService.IRVMPass() {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "MutateProfile";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IRVMProgram apply(final IRVMProgram input) {
|
||||||
|
return new IRVMProgram(new IRVMModule(
|
||||||
|
"experimental",
|
||||||
|
input.module().functions()));
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
final var thrown = assertThrows(IllegalArgumentException.class, () -> service.optimize(validProgram()));
|
||||||
|
assertTrue(thrown.getMessage().contains("vm profile"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private OptimizeIRVMService.IRVMPass namedPass(
|
||||||
|
final String name,
|
||||||
|
final List<String> order,
|
||||||
|
final boolean enabled) {
|
||||||
|
return new OptimizeIRVMService.IRVMPass() {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IRVMProgram apply(final IRVMProgram input) {
|
||||||
|
order.add(name);
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private IRVMProgram validProgram() {
|
||||||
|
return new IRVMProgram(new IRVMModule(
|
||||||
|
"core-v1",
|
||||||
|
ReadOnlyList.from(new IRVMFunction(
|
||||||
|
"main",
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
ReadOnlyList.from(new IRVMInstruction(IRVMOp.HALT, null))))));
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user