1 /*
   2  * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.loop.phases;
  26 
  27 import org.graalvm.compiler.graph.Graph;
  28 import org.graalvm.compiler.loop.LoopEx;
  29 import org.graalvm.compiler.loop.LoopPolicies;
  30 import org.graalvm.compiler.loop.LoopsData;
  31 import org.graalvm.compiler.nodes.StructuredGraph;
  32 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
  33 import org.graalvm.compiler.phases.common.util.HashSetNodeEventListener;
  34 import org.graalvm.compiler.phases.tiers.PhaseContext;
  35 
  36 public class LoopPartialUnrollPhase extends LoopPhase<LoopPolicies> {
  37 
  38     private final CanonicalizerPhase canonicalizer;
  39 
  40     public LoopPartialUnrollPhase(LoopPolicies policies, CanonicalizerPhase canonicalizer) {
  41         super(policies);
  42         this.canonicalizer = canonicalizer;
  43     }
  44 
  45     @Override
  46     @SuppressWarnings("try")
  47     protected void run(StructuredGraph graph, PhaseContext context) {
  48         if (graph.hasLoops()) {
  49             HashSetNodeEventListener listener = new HashSetNodeEventListener();
  50             boolean changed = true;
  51             while (changed) {
  52                 changed = false;
  53                 try (Graph.NodeEventScope nes = graph.trackNodeEvents(listener)) {
  54                     LoopsData dataCounted = new LoopsData(graph);
  55                     dataCounted.detectedCountedLoops();
  56                     Graph.Mark mark = graph.getMark();
  57                     boolean prePostInserted = false;
  58                     for (LoopEx loop : dataCounted.countedLoops()) {
  59                         if (!LoopTransformations.isUnrollableLoop(loop)) {
  60                             continue;
  61                         }
  62                         if (getPolicies().shouldPartiallyUnroll(loop)) {
  63                             if (loop.loopBegin().isSimpleLoop()) {
  64                                 // First perform the pre/post transformation and do the partial
  65                                 // unroll when we come around again.
  66                                 LoopTransformations.insertPrePostLoops(loop);
  67                                 prePostInserted = true;
  68                             } else {
  69                                 LoopTransformations.partialUnroll(loop);
  70                             }
  71                             changed = true;
  72                         }
  73                     }
  74                     dataCounted.deleteUnusedNodes();
  75 
  76                     if (!listener.getNodes().isEmpty()) {
  77                         canonicalizer.applyIncremental(graph, context, listener.getNodes());
  78                         listener.getNodes().clear();
  79                     }
  80 
  81                     assert !prePostInserted || checkCounted(graph, mark);
  82                 }
  83             }
  84         }
  85     }
  86 
  87     private static boolean checkCounted(StructuredGraph graph, Graph.Mark mark) {
  88         LoopsData dataCounted;
  89         dataCounted = new LoopsData(graph);
  90         dataCounted.detectedCountedLoops();
  91         for (LoopEx anyLoop : dataCounted.loops()) {
  92             if (graph.isNew(mark, anyLoop.loopBegin())) {
  93                 assert anyLoop.isCounted() : "pre/post transformation loses counted loop " + anyLoop.loopBegin();
  94             }
  95         }
  96         return true;
  97     }
  98 
  99     @Override
 100     public boolean checkContract() {
 101         return false;
 102     }
 103 }