|
| 1 | +# Compilation plan fuzzing |
| 2 | +This page covers the creation and usage of fuzzed compilation plans instead of the usual phase orderings specified by the different `CompilerConfiguration`s. |
| 3 | +## Abstraction design |
| 4 | +The following design can be found in the package `org.graalvm.compiler.core.phases.fuzzing`. |
| 5 | +### Diagram |
| 6 | +``` |
| 7 | + Suites > FuzzedSuites |
| 8 | + | |
| 9 | + AbstractCompilationPlan > MinimalFuzzedCompilationPlan > FullFuzzedCompilationPlan |
| 10 | + / | \ 3x| 3x| |
| 11 | +AbstractTierPlan AbstractTierPlan AbstractTierPlan > MinimalFuzzedTierPlan > FullFuzzedTierPlan |
| 12 | +``` |
| 13 | +`A > B` means A is the superclass of B. |
| 14 | +Vertical lines (`/`, `|` and `\`) means the lower end of the line is a field of the higher end of the line. |
| 15 | + |
| 16 | +### `AbstractCompilationPlan` |
| 17 | +An `AbstractCompilationPlan` represents a specific ordering of phases. |
| 18 | +It is composed of three `AbstractTierPlan`s which represent the phase orderings for high tier, mid tier and low tier. |
| 19 | + |
| 20 | +### `AbstractTierPlan` |
| 21 | +An `AbstractTierPlan` represents the phase ordering for a tier (high, mid or low tier). |
| 22 | +It contains a `PhaseSuite` which specifies the specific phase ordering of the plan. |
| 23 | + |
| 24 | +### `MinimalFuzzedCompilationPlan` |
| 25 | +A `MinimalFuzzedCompilationPlan` is a fuzzed compilation plan that is composed only of phases that apply a mandatory stage or that fulfills a future stage requirement. It is a phase ordering with the least number of phases possible. |
| 26 | + |
| 27 | +A mandatory stage (see `GraphState.MandatoryStages`) is a stage that necessarily needs to be applied to the graph to produce a valid compilation. For example, `StageFlag.HIGH_TIER_LOWERING` is required in high tier to transition to mid tier. |
| 28 | + |
| 29 | +A future stage requirement means the graph requires a stage to be applied. For example, if vector nodes are created, the graph requires a stage that lowers this kind of nodes. |
| 30 | + |
| 31 | +A `MinimalFuzzedCompilationPlan` is composed of three `MinimalFuzzedTierPlan`s which represent the phase orderings for high tier, mid tier and low tier. |
| 32 | + |
| 33 | +### `FullFuzzedCompilationPlan` |
| 34 | +A `FullFuzzedCompilationPlan` represents a compilation plan created by fuzzing. |
| 35 | +It is created by inserting optional phases in a `MinimalFuzzedCompilationPlan`. |
| 36 | +It is composed of three `FullFuzzedTierPlan`s which represent the phase orderings for high tier, mid tier and low tier. |
| 37 | + |
| 38 | +### `FuzzedSuites` |
| 39 | +`FuzzedSuites` is a subclass of `Suites` and represents suites created using a `FullFuzzedCompilationPlan`. |
| 40 | +Since it is a subclass of `Suites`, it can be used instead of `Suites` to provide fuzzed phase orderings. |
| 41 | + |
| 42 | +## Fuzzing strategy |
| 43 | +To create a fuzzed compilation plan, three fuzzed tier plans are constructed: one for high, mid and low tier. |
| 44 | +They are assembled in this order to ensure the graph state resulting from a previous tier is carried to the next tier. This way, future stage requirements can be resolved by phases in later tiers. |
| 45 | + |
| 46 | +### Minimal fuzzed compilation plan |
| 47 | +The `MinimalFuzzedCompilationPlan` is created by constructing three `MinimalFuzzedTierPlan`s. These tier plans are assembled in three steps: |
| 48 | +1. Insert in the fuzzed tier plan all the phases for which `BasePhase.mustApply(GraphState)` returns `true`. |
| 49 | + This resolves graph or stage requirements that were introduced by earlier tiers. |
| 50 | +2. Loop over the phases that apply a mandatory stage and try to insert them in the tier plan. |
| 51 | + If the mandatory stages cannot be reached after a fixed number of attempts, an error is thrown. |
| 52 | +3. Insert the phases which `BasePhase.mustApply(GraphState)` after applying the tier plan resulting from step 2. |
| 53 | + This leaves only future stage requirements remaining that cannot be fulfilled by the tier itself. |
| 54 | + |
| 55 | +### Inserting phases that must apply |
| 56 | +To fulfill future stage requirements, phases for which `BasePhase.mustApply(GraphState)` returns `true` are inserted in the suite. The procedure is as follow: |
| 57 | +``` |
| 58 | +queue = queueContainingAllThePhases(); |
| 59 | +while(queue.contains(phaseThatMustApply)){ |
| 60 | + // Try to insert the phase in the plan, starting from the end. |
| 61 | + for(position=endPosition; position >= startPosition; position--){ |
| 62 | + if(!phaseMustApply(position)){ |
| 63 | + break; |
| 64 | + } |
| 65 | + if(canInsertPhaseAtPosition(phaseThatMustApply, position)){ |
| 66 | + insertPhaseAtPosition(phaseThatMustApply, position); |
| 67 | + break; |
| 68 | + } |
| 69 | + } |
| 70 | + // If the phase cannot be inserted, it means it must happen after another phase. Try again later. |
| 71 | + queue.putAtTheEnd(phaseThatMustApply); |
| 72 | +} |
| 73 | +``` |
| 74 | + |
| 75 | +### Full fuzzed compilation plan |
| 76 | +The `FullFuzzedCompilationPlan` is created by constructing three `FullFuzzedTierPlan`s. These tier plans are assembled with the following steps: |
| 77 | +1. Initialize the plan to given `MinimalFuzzedTierPlan`. |
| 78 | +2. Insert in the fuzzed tier plan all the phases for which `BasePhase.mustApply(GraphState)` returns `true`. |
| 79 | + This resolves graph or stage requirements that were introduced by earlier tiers. |
| 80 | +3. Insert optional phases that can be applied at most once. These phases are the ones that modify the graph state. |
| 81 | + Each phase is inserted by following the logic described by this pseudo-code: |
| 82 | + ``` |
| 83 | + phase = pickRandomPhase() |
| 84 | + for randomPosition in positionsInThePlan { |
| 85 | + if(skipped){ |
| 86 | + continue; |
| 87 | + } |
| 88 | + newPlan = currPlan.insertPhaseAtPosition(randomPosition, phase); |
| 89 | + if(newPlan.respectsOrderingConstraints()){ |
| 90 | + currPlan = newPlan; |
| 91 | + break; |
| 92 | + } |
| 93 | + } |
| 94 | + ``` |
| 95 | + The probability of skipping a phase is determined by a parameter of `FullFuzzedTierPlan`. |
| 96 | + |
| 97 | +4. Insert optional phases that can be applied multiple times since they do not modify the graph state. |
| 98 | + Each phase is inserted by following the logic described by this pseudo-code: |
| 99 | + ``` |
| 100 | + phase = pickRandomPhase() |
| 101 | + for position in positionsInThePlan { |
| 102 | + if(skipped){ |
| 103 | + continue; |
| 104 | + } |
| 105 | + newPlan = currPlan.insertPhaseAtPosition(position, phase); |
| 106 | + if(newPlan.respectsOrderingConstraints()){ |
| 107 | + currPlan = newPlan; |
| 108 | + } |
| 109 | + } |
| 110 | + ``` |
| 111 | + The probability of skipping a phase is determined by a parameter of `FullFuzzedTierPlan`. |
| 112 | + Compared to step 3, we keep on trying to insert the phase in the plan even if the phase was already inserted successfully. Furthermore, we do not insert at a random position but follow the natural positions order. |
| 113 | + |
| 114 | +5. Insert the phases which `BasePhase.mustApply(GraphState)` after applying the tier plan resulting from the previous step. |
| 115 | + This leaves only future stage requirements remaining that cannot be fulfilled by the tier itself. |
| 116 | + |
| 117 | +## Reproducibility |
| 118 | +### JTT tests |
| 119 | +#### Create new fuzzed compilation plans |
| 120 | +You can create fuzzed compilation plans for JTT tests. For this, use one of the following equivalent commands: |
| 121 | +- `mx fuzz-jtt-tests` |
| 122 | +- `mx gate --tags fuzz-jtt-tests` |
| 123 | +- `mx unittest -Dtest.graal.compilationplan.fuzzing=true` |
| 124 | + |
| 125 | +It is possible to fix some parameters of the creation of fuzzed compilation plans: |
| 126 | +- To test only the minimal fuzzed compilation plan: |
| 127 | + * `mx fuzz-jtt-tests --minimal` |
| 128 | + * `mx gate --extra-unittest-argument='--minimal' --tags fuzz-jtt-tests` |
| 129 | + * `mx fuzz-jtt-tests -Dtest.graal.compilationplan.fuzzing.minimal=true` |
| 130 | + * `mx gate --extra-unittest-argument='-Dtest.graal.compilationplan.fuzzing.minimal=true' --tags fuzz-jtt-tests` |
| 131 | + * `mx gate --extra-vm-argument='-Dtest.graal.compilationplan.fuzzing.minimal=true' --tags fuzz-jtt-tests` |
| 132 | +- You can choose the seed to be used to create `Random` instances. The option is `-Dtest.graal.compilationplan.fuzzing.seed=<seed>` and the short version is `--seed=<seed>`. It can be used like the option for the minimal fuzzed compilation plan. |
| 133 | +- To regulate the probability that a phase will be inserted at each position in the suite, you can use: |
| 134 | + * `-Dtest.graal.skip.phase.insertion.odds=<number>` or `--skip-phase-odds=<number>`. |
| 135 | + - When we try to insert the phase, the phase will be inserted with probability `1/<number>` at each position in the current suite but only if the ordering constraints are respected. |
| 136 | + - The creation of the fuzzed compilation plan will use the same odds for each tier. |
| 137 | + * `-Dtest.graal.skip.phase.insertion.odds.high.tier=<number>` or `--high-tier-skip-phase=<number>` |
| 138 | + - This will determine the probability for the insertion in high tier. |
| 139 | + - If the odds for mid tier or low tier are not given, these odds will be used. |
| 140 | + - If the odds for high tier are not defined, the default odds defined in `FullFuzzedCompilationPlan` are used instead. |
| 141 | + * `-Dtest.graal.skip.phase.insertion.odds.mid.tier=<number>` or `--mid-tier-skip-phase=<number>` |
| 142 | + - This will determine the probability for the insertion in mid tier. |
| 143 | + * `-Dtest.graal.skip.phase.insertion.odds.low.tier=<number>` or `--low-tier-skip-phase=<number>` |
| 144 | + - This will determine the probability for the insertion in low tier. |
| 145 | +- You can specify which test you want to run like this: |
| 146 | + * `mx fuzz-jtt-tests HP_life` |
| 147 | + * `mx gate --extra-unittest-argument='HP_life' --tags fuzz-jtt-tests` |
| 148 | +- If you want to use the phases of a specific compiler configuration and respect its requirements, you should use: |
| 149 | + * `-Dgraal.CompilerConfiguration=<config>` |
| 150 | + |
| 151 | +#### Load a phase plan |
| 152 | +You can load a phase plan (one created by a fuzzed compilation plan or any other phase plan serialized using the `PhasePlanSerializer`) using the command: |
| 153 | +``` |
| 154 | +mx unittest -Dtest.graal.phaseplan.file="/path/to/phaseplan" |
| 155 | +``` |
| 156 | + |
| 157 | +### CompileTheWorld |
| 158 | +#### Create new fuzzed compilation plans |
| 159 | +You can use fuzzed plans for `CompileTheWorld`'s compilations by using the following commands: |
| 160 | +``` |
| 161 | +mx gate --tags ctwfuzzing |
| 162 | +``` |
| 163 | +or |
| 164 | +``` |
| 165 | +mx gate --extra-vm-argument='-DCompileTheWorld.FuzzPhasePlan=true' --tags ctw |
| 166 | +``` |
| 167 | + |
| 168 | +These commands will make each thread create a new fuzzed compilation plan for each compilation they have to perform. |
| 169 | + |
| 170 | +#### Load a phase plan |
| 171 | +It is possible to load a phase plan (one created by a fuzzed compilation plan or any other phase plan serialized using the `PhasePlanSerializer`) and use it for the compilation of a method by using the command: |
| 172 | +``` |
| 173 | +mx gate --extra-vm-argument='-DCompileTheWorld.LoadPhasePlan=/path/to/phaseplan' --extra-vm-argument='-DCompileTheWorld.MethodFilter=<methodName>' --extra-vm-argument='-Dgraal.CompilerConfiguration=<config>' --tags ctw |
| 174 | +``` |
0 commit comments