public function process(GraphState $state) { $graph = $state->getGraph(); $vars = Helper::findVariables($graph); $postdominator = $state->getPostDominator(); $dominator = $state->getDominator(); foreach ($vars as $var) { $usages = []; foreach ($graph->vertices() as $vertex) { if (in_array($var, $vertex->getVariables(), true)) { $usages[] = $vertex; } } $dom = $postdominator->immediateDominatorArray($usages); while ($dom) { foreach ($usages as $usage) { if ($dominator->strictlyDominates($usage, $dom)) { $dom = $postdominator->immediateDominator($dom); continue 2; } } break; } if (!$dom) { continue; } if ($dom instanceof Jump || $dom instanceof JumpZ) { Helper::insertBefore($dom, new Free($var), $graph); } else { Helper::insertAfter($dom, new Free($var), $graph); } } }
/** * @covers ::__construct * @covers ::getGraph * @covers ::getFunction * @covers ::getDominator * @covers ::getPostDominator * @covers ::getInverseGraph */ public function testBasicUsage() { $func = new JitFunction([], new Type(0), $graph = new DirectedAdjacencyList()); $graph->ensureArc($func, new End()); $state = new GraphState($func); $this->assertSame($func, $state->getFunction()); $this->assertSame($graph, $state->getGraph()); $this->assertInstanceOf(Dominator::class, $state->getDominator()); $this->assertInstanceOf(Dominator::class, $state->getPostDominator()); $this->assertInstanceOf(DirectedAdjacencyList::class, $state->getInverseGraph()); }
/** * Actually run the optimization rules over the graph. * * This will re-run the optimizers if anything was changed in a run. This * allows for optimizations to happen in any order, and for one optimization * to open the door to another. * * Unfortunately, this also makes this process EXTREMELY expensive. * * This is O(scary). */ public function process(GraphState $state) { $graph = $state->getGraph(); do { $rerun = false; foreach ($graph->vertices() as $vertex) { foreach ($this->rules as $rule) { $rerun = $rerun || $rule->process($vertex, $graph); } } } while ($rerun); }
public function process(GraphState $state) { $graph = $state->getGraph(); $assignments = array_merge(Helper::findVerticesByClass(JitAssignment::class, $graph), [$state->getFunction()]); $vars = Helper::findVariables($graph); $dominator = $state->getDominator(); foreach ($vars as $var) { $hash = spl_object_hash($var); $varAssignments = $this->findAssignmentsByVar($var, $assignments); $phi = $this->findPhiNodes($var, $varAssignments, $dominator, $graph); $this->implementSSA($var, $var, $state->getFunction(), $graph, $phi, $state->getFunction()->getArguments()); $this->stack->removeAll($this->stack); } }
public function removePhi(Phi $vertex, GraphState $state) { $graph = $state->getGraph(); Helper::remove($vertex, $graph); $to = $vertex->getResult(); foreach ($vertex->getValues() as $value) { foreach ($graph->vertices() as $v) { $v->replaceVariable($value, $to); if ($v instanceof Assignment && $v->getResult() === $value) { $v->setResult($to); } } } }