/** * @covers \Gliph\Traversal\DepthFirst::toposort * @expectedException Gliph\Exception\RuntimeException * Thrown by the visitor after adding a cycle to the graph. */ public function testToposort() { extract($this->v); $this->assertEquals(array($c, $d, $b, $a), DepthFirst::toposort($this->g, $a)); $this->g->addDirectedEdge($d, $a); DepthFirst::toposort($this->g, $a); }
/** * @covers ::process */ public function testExpansionFailure() { $graph = new DirectedAdjacencyList(); $end = new End(); $graph->ensureArc($end, $b = new JitBinaryOp(JitBinaryOp::PLUS, new Constant(1), new Variable(), new Variable())); $rule = new ConstBinaryOp(); $this->assertFalse($rule->process($b, $graph)); }
public static function dump(DirectedAdjacencyList $graph) { $edges = []; foreach ($graph->edges() as $edge) { $edges[] = $edge[0]->getName() . ' ' . $edge[1]->getName(); } return $edges; }
/** * @covers ::process * @covers ::addRule */ public function testOperation() { $graph = new DirectedAdjacencyList(); $func = new Function_([], new Type(0), $graph); $graph->ensureVertex($func); $state = new GraphState($func); $resolver = new Optimizer(); $resolver->addRule($r = $this->getMock(OptimizerRule::class)); $r->expects($this->once())->method('process')->with($this->identicalTo($func))->will($this->returnValue(false)); $resolver->process($state); }
/** * @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()); }
/** * @covers ::generateText * @covers ::convertGraph */ public function testGenerateText() { $a = new DummyVertex('a'); $b = new DummyVertex('b'); $c = new DummyVertex('c'); $graph = new DirectedAdjacencyList(); $graph->ensureArc($a, $b); $graph->ensureArc($b, $c); $graph->ensureArc($c, $b); $printer = new GraphPrinter(); $this->assertContains('node_0', $printer->generateText($graph)); }
/** * @covers ::generateFunction * @covers ::generate */ public function testGenerateFunctionReversedJumpZ() { $generator = new Generator(); $graph = new DirectedAdjacencyList(); $long = new Type(Type::TYPE_LONG); $double = new Type(Type::TYPE_DOUBLE); $func = new Vertex\Function_([$a = new Variable($long), $b = new Variable($double)], $double, $graph); $noOp = new Vertex\NoOp(); $jumpz = new Vertex\JumpZ($noOp, $a); $end = new Vertex\End(); $graph->ensureArc($func, $jumpz); $graph->ensureArc($jumpz, $r1 = new Vertex\Return_(new Constant(1.5))); $graph->ensureArc($jumpz, $noOp); $graph->ensureArc($r1, $end); $graph->ensureArc($noOp, $r2 = new Vertex\Return_($b)); $graph->ensureArc($r2, $end); $expected = <<<'EOF' function test123 double param $1 long param $2 double begin jumpz $1 @1 const $3 double 1.5 return $3 label @1 return $2 end EOF; $this->assertEquals($expected, $generator->generateFunction('test123', $func)); }
/** * @covers ::isLiveVar */ public function testIsLiveVarWithCycleAndLaterValue() { $graph = new DirectedAdjacencyList(); $var = new Variable(); $vertex = $this->getMock(Vertex::class); $graph->ensureVertex($vertex); $vertex->expects($this->once())->method('getVariables')->will($this->returnValue([])); $v1 = $this->getMock(Vertex::class); $v1->expects($this->once())->method('getVariables')->will($this->returnValue([$var])); $graph->ensureArc($vertex, $v1); $this->assertTrue(Helper::isLiveVar($var, $vertex, $graph)); }
/** * @expectedException Gliph\Exception\RuntimeException * @covers Gliph\Visitor\DepthFirstBasicVisitor::onBackEdge * @covers Gliph\Visitor\DepthFirstBasicVisitor::onInitializeVertex */ public function testErrorOnCycle() { $this->g->addDirectedEdge($this->v['d'], $this->v['b']); DepthFirst::traverse($this->g, $this->vis); }
/** * @covers ::process * @covers ::implementSSA */ public function testOperationLoopWithPhi() { $graph = new DirectedAdjacencyList(); $a = new Variable(); $func = new Function_([$a], new Type(0), $graph); $start = new NoOp(); $noOp = new NoOp(); $jumpz = new JumpZ($noOp, $a); $graph->ensureArc($func, $start); $graph->ensureArc($start, $jumpz); $graph->ensureArc($jumpz, $r = new Return_($a)); $graph->ensureArc($r, new End()); $graph->ensureArc($jumpz, $binary = new BinaryOp(BinaryOp::PLUS, $a, new Constant(2), $a)); $graph->ensureArc($binary, $j = new Jump()); $graph->ensureArc($j, $start); $state = new GraphState($func); $compiler = new SSACompiler(); $compiler->process($state); $this->assertSame([$a], $func->getArguments()); $i = 0; foreach ($graph->successorsOf($start) as $v) { $this->assertEquals(0, $i++, 'More then one adjacent node'); $this->assertInstanceOf(Phi::class, $v); $this->assertContains($a, $v->getValues()); $this->assertSame($r->getValue(), $v->getResult()); } }
/** * @covers \Gliph\Algorithm\ConnectedComponent::tarjan_scc() */ public function testTarjanScc() { $a = new TestVertex('a'); $b = new TestVertex('b'); $c = new TestVertex('c'); $d = new TestVertex('d'); $e = new TestVertex('e'); $f = new TestVertex('f'); $g = new TestVertex('g'); $h = new TestVertex('h'); $graph = new DirectedAdjacencyList(); $graph->addDirectedEdge($a, $d); $graph->addDirectedEdge($a, $b); $graph->addDirectedEdge($b, $c); $graph->addDirectedEdge($c, $d); $graph->addDirectedEdge($d, $a); $graph->addDirectedEdge($e, $d); $graph->addDirectedEdge($f, $g); $graph->addDirectedEdge($g, $h); $graph->addDirectedEdge($h, $f); $visitor = ConnectedComponent::tarjan_scc($graph); $expected_full = array(array($c, $b, $d, $a), array($e), array($h, $g, $f)); $this->assertEquals($expected_full, $visitor->getComponents()); $expected_full = array(array($c, $b, $d, $a), array($h, $g, $f)); $this->assertEquals($expected_full, $visitor->getConnectedComponents()); }
public function checkForCircularReference(array $phiNodes, GraphState $state) { $graph = new DirectedAdjacencyList(); foreach ($phiNodes as $phi) { $result = $phi->getResult(); foreach ($phi->getValues() as $value) { $graph->ensureArc($value, $result); } } $cycles = $graph->getCycles(); foreach ($cycles as $cycle) { if ($this->areAllUnknown($cycle)) { // All are unknown, process! $types = array(); foreach ($cycle as $component) { foreach (Helper::getInboundNodes($component, $graph) as $node) { if (in_array($node, $cycle, true)) { continue; } $types[] = $node->getType()->getType(); } } $types = array_unique($types); $newType = 0; switch (count($types)) { case 1: if ($types[0] != Type::TYPE_UNKNOWN) { $newType = $types[0]; } break; case 2: if (in_array(Type::TYPE_NUMERIC, $types) && in_array(Type::TYPE_LONG, $types)) { $newType = Type::TYPE_NUMERIC; } elseif (in_array(Type::TYPE_NUMERIC, $types) && in_array(Type::TYPE_DOUBLE, $types)) { $newType = Type::TYPE_DOUBLE; } break; } if ($newType) { foreach ($cycle as $component) { $component->setType(new Type($newType)); } return true; } } } return false; }