001    /*
002     *  This file is part of the Jikes RVM project (http://jikesrvm.org).
003     *
004     *  This file is licensed to You under the Eclipse Public License (EPL);
005     *  You may not use this file except in compliance with the License. You
006     *  may obtain a copy of the License at
007     *
008     *      http://www.opensource.org/licenses/eclipse-1.0.php
009     *
010     *  See the COPYRIGHT.txt file distributed with this work for information
011     *  regarding copyright ownership.
012     */
013    package org.jikesrvm.compilers.opt.controlflow;
014    
015    import java.util.Enumeration;
016    
017    import org.jikesrvm.compilers.opt.OperationNotImplementedException;
018    import org.jikesrvm.compilers.opt.dfsolver.DF_LatticeCell;
019    import org.jikesrvm.compilers.opt.dfsolver.DF_Solution;
020    import org.jikesrvm.compilers.opt.ir.BasicBlock;
021    import org.jikesrvm.compilers.opt.ir.IR;
022    
023    /**
024     * Calculate dominators for basic blocks.
025     * <p> Uses the algorithm contained in Dragon book, pg. 670-1.
026     * <pre>
027     *       D(n0) := { n0 }
028     *       for n in N - { n0 } do D(n) := N;
029     *       while changes to any D(n) occur do
030     *         for n in N - {n0} do
031     *             D(n) := {n} U (intersect of D(p) over all predecessors p of n)
032     * </pre>
033     * <p> TODO: we do not support IRs with exception handlers!!
034     */
035    public class Dominators {
036      /**
037       * Control for debug output
038       */
039      static final boolean DEBUG = false;
040      /**
041       * Should we compute post-dominators instead of dominators? This is
042       * false by default.
043       */
044      static boolean COMPUTE_POST_DOMINATORS = false;
045    
046      /**
047       * Calculate the dominators for an IR.
048       * <p> After this pass, each basic block's scrach field points to
049       * an <code> DominatorInfo </code> object, which holds the dominators
050       * of the basic block.
051       *
052       * @param ir the IR in question
053       */
054      public static void perform(IR ir) {
055        if (ir.hasReachableExceptionHandlers()) {
056          throw new OperationNotImplementedException("IR with exception handlers");
057        }
058        DominatorSystem system = new DominatorSystem(ir);
059        if (DEBUG) {
060          System.out.print("Solving...");
061        }
062        if (DEBUG) {
063          System.out.println(system);
064        }
065        system.solve();
066        if (DEBUG) {
067          System.out.println("done");
068        }
069        DF_Solution solution = system.getSolution();
070        if (DEBUG) {
071          System.out.println("Dominator Solution :" + solution);
072        }
073        if (DEBUG) {
074          System.out.print("Updating blocks ...");
075        }
076        updateBlocks(solution);
077        if (DEBUG) {
078          System.out.println("done.");
079        }
080        if (ir.options.PRINT_DOMINATORS) {
081          printDominators(ir);
082        }
083      }
084    
085      /**
086       * Calculate the "approximate" dominators for an IR i.e., the
087       * dominators in the factored CFG rather than the normal CFG.
088       * <p> (No exception is thrown if the input IR has handler blocks.)
089       *
090       * <p> After this pass, each basic block's scratch field points to
091       * an DominatorInfo object, which holds the dominators
092       * of the basic block.
093       *
094       * @param ir the IR in question
095       */
096      public static void computeApproxDominators(IR ir) {
097        DominatorSystem system = new DominatorSystem(ir);
098        if (DEBUG) {
099          System.out.print("Solving...");
100        }
101        if (DEBUG) {
102          System.out.println(system);
103        }
104        system.solve();
105        if (DEBUG) {
106          System.out.println("done");
107        }
108        DF_Solution solution = system.getSolution();
109        if (DEBUG) {
110          System.out.println("Dominator Solution :" + solution);
111        }
112        if (DEBUG) {
113          System.out.print("Updating blocks ...");
114        }
115        updateBlocks(solution);
116        if (DEBUG) {
117          System.out.println("done.");
118        }
119        if (ir.options.PRINT_DOMINATORS) {
120          printDominators(ir);
121        }
122      }
123    
124      /**
125       * Calculate the postdominators for an IR.
126       * <p> After this pass, each basic block's scrach field points to
127       * an DominatorInfo object, which holds the postdominators
128       * of the basic block.
129       *
130       * @param ir the IR in question
131       */
132      public static void computeApproxPostdominators(IR ir) {
133        Dominators.COMPUTE_POST_DOMINATORS = true;
134        DominatorSystem system = new DominatorSystem(ir);
135        if (DEBUG) {
136          System.out.print("Solving...");
137        }
138        if (DEBUG) {
139          System.out.println(system);
140        }
141        system.solve();
142        if (DEBUG) {
143          System.out.println("done");
144        }
145        DF_Solution solution = system.getSolution();
146        if (DEBUG) {
147          System.out.println("Postdominator Solution :" + solution);
148        }
149        if (DEBUG) {
150          System.out.print("Updating blocks ...");
151        }
152        updateBlocks(solution);
153        if (DEBUG) {
154          System.out.println("done.");
155        }
156        if (ir.options.PRINT_DOMINATORS) {
157          printDominators(ir);
158        }
159        Dominators.COMPUTE_POST_DOMINATORS = false;
160      }
161    
162      /**
163       * For each basic block in the data flow system solution,
164       * create an <code> DominatorInfo </code> and store it in the basic
165       * blocks scratchObject
166       *
167       * @param solution the solution to the Dominators equations
168       */
169      public static void updateBlocks(DF_Solution solution) {
170        for (final DF_LatticeCell latticeCell : solution.values()) {
171          DominatorCell cell = (DominatorCell) latticeCell;
172          BasicBlock b = cell.block;
173          b.scratchObject = new DominatorInfo(cell.dominators);
174          if (DEBUG) {
175            System.out.println("Dominators of " + b + ":" + cell.dominators);
176          }
177        }
178      }
179    
180      /**
181       * Print the (already calculated) dominators.
182       * @param ir the IR
183       */
184      public static void printDominators(IR ir) {
185        for (Enumeration<BasicBlock> e = ir.getBasicBlocks(); e.hasMoreElements();) {
186          BasicBlock b = e.nextElement();
187          DominatorInfo i = (DominatorInfo) b.scratchObject;
188          System.out.println("Dominators of " + b + ":" + i.dominators);
189        }
190      }
191    }