From b91a3cea342fd4adaca51f9ed4d6abadba30431c Mon Sep 17 00:00:00 2001 From: bQUARKz Date: Mon, 9 Mar 2026 08:44:28 +0000 Subject: [PATCH] implements PR-07.1 --- ...Backend Spec-to-Test Conformance Matrix.md | 2 +- .../backend/irvm/OptimizeIRVMServiceTest.java | 74 +++++++++++++++++++ 2 files changed, 75 insertions(+), 1 deletion(-) diff --git a/docs/general/specs/22. Backend Spec-to-Test Conformance Matrix.md b/docs/general/specs/22. Backend Spec-to-Test Conformance Matrix.md index 7b2af4f4..adfcdf5d 100644 --- a/docs/general/specs/22. Backend Spec-to-Test Conformance Matrix.md +++ b/docs/general/specs/22. Backend Spec-to-Test Conformance Matrix.md @@ -62,7 +62,7 @@ to concrete positive/negative test evidence and current status. | G21-7.2 | Optimization passes MUST be deterministic for same input/profile. | `BackendSafetyGateSUTest#optimizeStageMustBeDeterministicForSameInputProgram` | N/A | pass | | | G21-7.3 | Optimization passes MUST preserve profile compatibility. | `OptimizeIRVMPipelineStageTest#runMustAcceptSupportedNonDefaultVmProfile` | `OptimizeIRVMServiceTest#optimizeMustRejectPassThatMutatesVmProfile` | pass | | | G21-7.4 | Optimization passes MUST preserve host-vs-intrinsic boundary classification. | `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites`; `BackendGateIIntegrationTest#gateI_validIntrinsicPath` | N/A | pass | No pass rewrites operation kind domains. | -| G21-7.5 | Optimization passes MUST preserve diagnostics/source-attribution hooks. | `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites` (spans on emission ops) | N/A | partial | Needs targeted optimizer regression asserting span retention after rewrites. | +| G21-7.5 | Optimization passes MUST preserve diagnostics/source-attribution hooks. | `OptimizeIRVMServiceTest#unreachableInstructionEliminationPassMustPreserveJumpSpanWhenTargetIsRemapped`; `OptimizeIRVMServiceTest#normalizeRedundantJumpTargetsPassMustPreserveJumpSpanAfterRewrite`; `OptimizeIRVMServiceTest#simplifyJumpToNextPcPassMustPreserveSpanOnSurvivingOperation`; `LowerToIRVMServiceTest#lowerMustMapHostAndIntrinsicCallsites` | N/A | pass | Dedicated optimizer regressions now assert span/source-hook preservation for rewrite and elimination paths. | | G21-9.1 | Validation MUST include optimized-vs-non-optimized equivalence fixtures. | `OptimizeIRVMEquivalenceHarnessTest#optimizeOnOffMustPreserveObservableTraceForLoweredHostIntrinsicFixture`; `OptimizeIRVMEquivalenceHarnessTest#optimizeOnOffMustPreserveObservableTraceForConditionalJoinFixture`; `OptimizeIRVMEquivalenceHarnessTest#optimizeOnOffMustPreserveObservableTraceForSimpleLoopFixture`; `OptimizeIRVMEquivalenceHarnessTest#optimizeOnOffMustPreserveObservableTraceForLinearCallFixture` | N/A | pass | Dedicated opt on/off harness with reusable interpreter and deterministic trace assertions is in place. | | G21-9.2 | Validation MUST preserve known negative loader/verifier behavior. | `BackendSafetyGateSUTest#emitStageMustExposeMarshalingLinkageFailureDeterministically`; `BackendGateIIntegrationTest` rejection suite | N/A | pass | | | G21-9.3 | Validation MUST preserve deterministic artifact-level invariants. | `BackendSafetyGateSUTest#fullPipelineMustProduceDeterministicBytecodeForSameInput`; `BytecodeEmitterTest#emitMustRemainDeterministicAfterInterning` | N/A | pass | | diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/backend/irvm/OptimizeIRVMServiceTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/backend/irvm/OptimizeIRVMServiceTest.java index 0b9dad66..32899939 100644 --- a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/backend/irvm/OptimizeIRVMServiceTest.java +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/backend/irvm/OptimizeIRVMServiceTest.java @@ -2,6 +2,7 @@ package p.studio.compiler.backend.irvm; import org.junit.jupiter.api.Test; import p.studio.compiler.backend.bytecode.BytecodeEmitter; +import p.studio.compiler.backend.bytecode.BytecodeModule; import p.studio.compiler.backend.bytecode.BytecodePreloadVerifierService; import p.studio.utilities.structures.ReadOnlyList; @@ -174,6 +175,79 @@ class OptimizeIRVMServiceTest { new BytecodePreloadVerifierService().verify(emitted); } + @Test + void unreachableInstructionEliminationPassMustPreserveJumpSpanWhenTargetIsRemapped() { + final var jumpSpan = new BytecodeModule.SourceSpan(7, 10, 12); + final var removedSpan = new BytecodeModule.SourceSpan(7, 13, 14); + final var retSpan = new BytecodeModule.SourceSpan(7, 15, 16); + final var service = new OptimizeIRVMService(new IRVMValidator(), List.of( + OptimizeIRVMService.unreachableInstructionEliminationPass())); + final var input = singleFunctionProgram( + ReadOnlyList.from( + new IRVMInstruction(IRVMOp.JMP, 8), + new IRVMInstruction(IRVMOp.HALT, null), + new IRVMInstruction(IRVMOp.RET, null)), + ReadOnlyList.from( + BytecodeEmitter.Operation.jmp(8, jumpSpan), + BytecodeEmitter.Operation.halt(removedSpan), + BytecodeEmitter.Operation.ret(retSpan))); + + final var optimized = service.optimize(input); + final var firstOperation = optimized.coherentEmissionPlan().functions().getFirst().operations().getFirst(); + final var secondOperation = optimized.coherentEmissionPlan().functions().getFirst().operations().get(1); + + assertEquals(2, optimized.module().functions().getFirst().instructions().size()); + assertEquals(BytecodeEmitter.OperationKind.JMP, firstOperation.kind()); + assertEquals(6, firstOperation.immediate()); + assertEquals(jumpSpan, firstOperation.span()); + assertEquals(retSpan, secondOperation.span()); + } + + @Test + void normalizeRedundantJumpTargetsPassMustPreserveJumpSpanAfterRewrite() { + final var firstJumpSpan = new BytecodeModule.SourceSpan(9, 20, 24); + final var secondJumpSpan = new BytecodeModule.SourceSpan(9, 25, 28); + final var service = new OptimizeIRVMService(new IRVMValidator(), List.of( + OptimizeIRVMService.normalizeRedundantJumpTargetsPass())); + final var input = singleFunctionProgram( + ReadOnlyList.from( + new IRVMInstruction(IRVMOp.JMP, 6), + new IRVMInstruction(IRVMOp.JMP, 12), + new IRVMInstruction(IRVMOp.RET, null)), + ReadOnlyList.from( + BytecodeEmitter.Operation.jmp(6, firstJumpSpan), + BytecodeEmitter.Operation.jmp(12, secondJumpSpan), + BytecodeEmitter.Operation.ret())); + + final var optimized = service.optimize(input); + final var firstOperation = optimized.coherentEmissionPlan().functions().getFirst().operations().getFirst(); + + assertEquals(BytecodeEmitter.OperationKind.JMP, firstOperation.kind()); + assertEquals(12, firstOperation.immediate()); + assertEquals(firstJumpSpan, firstOperation.span()); + } + + @Test + void simplifyJumpToNextPcPassMustPreserveSpanOnSurvivingOperation() { + final var retSpan = new BytecodeModule.SourceSpan(11, 40, 41); + final var service = new OptimizeIRVMService(new IRVMValidator(), List.of( + OptimizeIRVMService.simplifyJumpToNextPcPass())); + final var input = singleFunctionProgram( + ReadOnlyList.from( + new IRVMInstruction(IRVMOp.JMP, 6), + new IRVMInstruction(IRVMOp.RET, null)), + ReadOnlyList.from( + BytecodeEmitter.Operation.jmp(6, new BytecodeModule.SourceSpan(11, 35, 39)), + BytecodeEmitter.Operation.ret(retSpan))); + + final var optimized = service.optimize(input); + final var onlyOperation = optimized.coherentEmissionPlan().functions().getFirst().operations().getFirst(); + + assertEquals(1, optimized.module().functions().getFirst().instructions().size()); + assertEquals(BytecodeEmitter.OperationKind.RET, onlyOperation.kind()); + assertEquals(retSpan, onlyOperation.span()); + } + private OptimizeIRVMService.IRVMPass namedPass( final String name, final List order,