Пример #1
0
 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);
         }
     }
 }
Пример #2
0
 /**
  * Build the dominator tree, and initialize it
  *
  * @param DirectedAdjacencyList $graph The graph to build the tree for
  * @param Vertex                $start The start node of the dominator
  */
 public function __construct(Digraph $graph, Vertex $start)
 {
     $this->dominator = new \SplObjectStorage();
     $this->graph = $graph;
     $this->predecessors = Helper::computePredecessors($this->graph);
     $this->iPredecessors = Helper::computeImmediatePredecessors($this->graph);
     $this->build($start);
 }
Пример #3
0
 public function process(Vertex $vertex, Digraph $graph)
 {
     if ($vertex instanceof Assignment && $vertex->isIdempotent() && 1 >= $this->countUsages($vertex->getResult(), $graph)) {
         Helper::remove($vertex, $graph);
         return true;
     }
     return false;
 }
Пример #4
0
 public function process(Vertex $vertex, Digraph $graph)
 {
     if ($graph->inDegreeOf($vertex) === 0 && !$vertex instanceof Vertex\Function_) {
         Helper::remove($vertex, $graph);
         return true;
     }
     return false;
 }
Пример #5
0
 public function process(Vertex $vertex, Digraph $graph)
 {
     if ($vertex instanceof Vertex\Phi) {
         $types = [];
         foreach ($vertex->getValues() as $value) {
             $types[] = (string) $value->getType();
         }
         $types = array_unique($types);
         if ($vertex->getResult()->getType()->isUnknown()) {
             $type = null;
             $setAll = false;
             if (count($types) === 1 && $types[0] !== 'unknown') {
                 $type = Type::normalizeType($types[0]);
             } elseif (count($types) === 2 && in_array('long', $types) && in_array('numeric', $types)) {
                 $type = new Type(Type::TYPE_LONG);
                 $setAll = true;
             } elseif (count($types) === 2 && in_array('double', $types) && in_array('numeric', $types)) {
                 $type = new Type(Type::TYPE_DOUBLE);
                 $setAll = true;
             } elseif (count($types) === 2 && in_array('bool', $types) && in_array('numeric', $types)) {
                 $type = new Type(Type::TYPE_BOOLEAN);
             }
             if ($type) {
                 $vertex->getResult()->setType($type);
                 if ($setAll) {
                     foreach ($vertex->getValues() as $value) {
                         $value->setType($type);
                     }
                 }
                 return true;
             }
         }
         if (count($vertex->getValues()) === 1) {
             // remove phi node
             list($val) = iterator_to_array($vertex->getValues());
             $result = $vertex->getResult();
             foreach ($graph->vertices() as $vtx) {
                 $vtx->replaceVariable($result, $val);
                 if ($vtx instanceof Assignment && $vtx->getResult() === $result) {
                     $vtx->setResult($val);
                 }
             }
             Helper::remove($vertex, $graph);
             return true;
         }
     }
     return false;
 }
Пример #6
0
 /**
  * @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));
 }
Пример #7
0
 public function process(Vertex $vertex, Digraph $graph)
 {
     if ($vertex instanceof JitBinaryOp && $vertex->getA() instanceof Constant && $vertex->getB() instanceof Constant) {
         $ret = null;
         switch ($vertex->getKind()) {
             case JitBinaryOp::CONCAT:
                 $ret = $vertex->getA()->getValue() . $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::PLUS:
                 $ret = $vertex->getA()->getValue() + $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::MINUS:
                 $ret = $vertex->getA()->getValue() - $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::MUL:
                 $ret = $vertex->getA()->getValue() * $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::DIV:
                 $ret = $vertex->getA()->getValue() / $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::MOD:
                 $ret = $vertex->getA()->getValue() % $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::EQUAL:
                 $ret = $vertex->getA()->getValue() == $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::NOT_EQUAL:
                 $ret = $vertex->getA()->getValue() != $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::IDENTICAL:
                 $ret = $vertex->getA()->getValue() == $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::NOT_IDENTICAL:
                 $ret = $vertex->getA()->getValue() !== $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::GREATER:
                 $ret = $vertex->getA()->getValue() > $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::GREATER_EQUAL:
                 $ret = $vertex->getA()->getValue() >= $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::SMALLER:
                 $ret = $vertex->getA()->getValue() < $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::SMALLER_EQUAL:
                 $ret = $vertex->getA()->getValue() <= $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::BITWISE_AND:
                 $ret = $vertex->getA()->getValue() & $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::BITWISE_OR:
                 $ret = $vertex->getA()->getValue() | $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::BITWISE_XOR:
                 $ret = $vertex->getA()->getValue() ^ $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::SHIFT_LEFT:
                 $ret = $vertex->getA()->getValue() << $vertex->getB()->getValue();
                 break;
             case JitBinaryOp::SHIFT_RIGHT:
                 $ret = $vertex->getA()->getValue() >> $vertex->getB()->getValue();
                 break;
         }
         // replace binary op with assign op
         Helper::replace($vertex, new JitAssign(new Constant($ret), $vertex->getResult()), $graph);
         return true;
     }
     return false;
 }
Пример #8
0
 public function getPostDominator()
 {
     return new Dominator($this->getInverseGraph(), Helper::findVerticesByClass(End::class, $this->graph)[0]);
 }
Пример #9
0
 public function findPhiNodes(Variable $var, array $assignments, Dominator $dominator, Digraph $graph)
 {
     $allDf = new \SplObjectStorage();
     $new = $assignments;
     do {
         $runAgain = false;
         $new = $this->findFrontier($new, $dominator);
         foreach ($new as $obj) {
             if (!$allDf->contains($obj)) {
                 $allDf->attach($obj);
                 // found a new one!!!
                 $runAgain = true;
             }
         }
     } while ($runAgain);
     $phiNodes = new \SplObjectStorage();
     foreach ($allDf as $node) {
         if ($node instanceof JitNoOp) {
             if (Helper::isLiveVar($var, $node, $graph)) {
                 // only add the phi node if the variable is live afterwards
                 $phiNodes[$node] = true;
             }
         } elseif (!$node instanceof End) {
             throw new \RuntimeException('A non-NoOp Phi Node was found, possible corrupted graph');
         }
     }
     return $phiNodes;
 }
Пример #10
0
 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;
 }