001/* 002 * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.compiler.common.cfg; 024 025import java.util.*; 026 027public interface AbstractControlFlowGraph<T extends AbstractBlockBase<T>> { 028 029 int BLOCK_ID_INITIAL = -1; 030 int BLOCK_ID_VISITED = -2; 031 032 /** 033 * Returns the list blocks contained in this control flow graph. 034 * 035 * It is {@linkplain CFGVerifier guaranteed} that the blocks are numbered and ordered according 036 * to a reverse post order traversal of the control flow graph. 037 * 038 * @see CFGVerifier 039 */ 040 List<T> getBlocks(); 041 042 Collection<Loop<T>> getLoops(); 043 044 T getStartBlock(); 045 046 /** 047 * Computes the dominators of control flow graph. 048 */ 049 @SuppressWarnings("unchecked") 050 static <T extends AbstractBlockBase<T>> void computeDominators(AbstractControlFlowGraph<T> cfg) { 051 List<T> reversePostOrder = cfg.getBlocks(); 052 assert reversePostOrder.get(0).getPredecessorCount() == 0 : "start block has no predecessor and therefore no dominator"; 053 for (int i = 1; i < reversePostOrder.size(); i++) { 054 T block = reversePostOrder.get(i); 055 assert block.getPredecessorCount() > 0; 056 T dominator = null; 057 for (T pred : block.getPredecessors()) { 058 if (!pred.isLoopEnd()) { 059 dominator = (T) ((dominator == null) ? pred : commonDominatorRaw(dominator, pred)); 060 } 061 } 062 // set dominator 063 block.setDominator(dominator); 064 if (dominator.getDominated().equals(Collections.emptyList())) { 065 dominator.setDominated(new ArrayList<>()); 066 } 067 dominator.getDominated().add(block); 068 } 069 calcDominatorRanges(cfg.getStartBlock()); 070 } 071 072 static <T extends AbstractBlockBase<T>> void calcDominatorRanges(T block) { 073 final class Frame { 074 int myNumber; 075 int maxNumber; 076 T block; 077 Iterator<T> dominated; 078 Frame parent; 079 080 public Frame(int myNumber, T block, Iterator<T> dominated, Frame parent) { 081 super(); 082 this.myNumber = myNumber; 083 this.maxNumber = myNumber; 084 this.block = block; 085 this.dominated = dominated; 086 this.parent = parent; 087 } 088 } 089 Frame f = new Frame(0, block, block.getDominated().iterator(), null); 090 while (f != null) { 091 if (!f.dominated.hasNext()) { // Retreat 092 f.block.setDominatorNumbers(f.myNumber, f.maxNumber); 093 if (f.parent != null) { 094 f.parent.maxNumber = f.maxNumber; 095 } 096 f = f.parent; 097 } else { 098 T d = f.dominated.next(); 099 List<T> dd = d.getDominated(); 100 f = new Frame(f.maxNumber + 1, d, dd.iterator(), f); 101 } 102 } 103 } 104 105 /** 106 * True if block {@code a} is dominated by block {@code b}. 107 */ 108 static boolean isDominatedBy(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 109 int domNumberA = a.getDominatorNumber(); 110 int domNumberB = b.getDominatorNumber(); 111 return domNumberA >= domNumberB && domNumberA <= b.getMaxChildDominatorNumber(); 112 } 113 114 /** 115 * True if block {@code a} dominates block {@code b} and {@code a} is not identical block to 116 * {@code b}. 117 */ 118 static boolean strictlyDominates(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 119 return a != b && dominates(a, b); 120 } 121 122 /** 123 * True if block {@code a} dominates block {@code b}. 124 */ 125 static boolean dominates(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 126 assert a != null && b != null; 127 return isDominatedBy(b, a); 128 } 129 130 /** 131 * Calculates the common dominator of two blocks. 132 * 133 * Note that this algorithm makes use of special properties regarding the numbering of blocks. 134 * 135 * @see #getBlocks() 136 * @see CFGVerifier 137 */ 138 static AbstractBlockBase<?> commonDominator(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 139 if (a == null) { 140 return b; 141 } else if (b == null) { 142 return a; 143 } else { 144 int aDomDepth = a.getDominatorDepth(); 145 int bDomDepth = b.getDominatorDepth(); 146 AbstractBlockBase<?> aTemp; 147 AbstractBlockBase<?> bTemp; 148 if (aDomDepth > bDomDepth) { 149 aTemp = a; 150 bTemp = b; 151 } else { 152 aTemp = b; 153 bTemp = a; 154 } 155 return commonDominatorHelper(aTemp, bTemp); 156 } 157 } 158 159 static AbstractBlockBase<?> commonDominatorHelper(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 160 int domNumberA = a.getDominatorNumber(); 161 AbstractBlockBase<?> result = b; 162 while (domNumberA < result.getDominatorNumber()) { 163 result = result.getDominator(); 164 } 165 while (domNumberA > result.getMaxChildDominatorNumber()) { 166 result = result.getDominator(); 167 } 168 return result; 169 } 170 171 static AbstractBlockBase<?> commonDominatorRaw(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 172 int aDomDepth = a.getDominatorDepth(); 173 int bDomDepth = b.getDominatorDepth(); 174 if (aDomDepth > bDomDepth) { 175 return commonDominatorRawSameDepth(a.getDominator(aDomDepth - bDomDepth), b); 176 } else { 177 return commonDominatorRawSameDepth(a, b.getDominator(bDomDepth - aDomDepth)); 178 } 179 } 180 181 static AbstractBlockBase<?> commonDominatorRawSameDepth(AbstractBlockBase<?> a, AbstractBlockBase<?> b) { 182 AbstractBlockBase<?> iterA = a; 183 AbstractBlockBase<?> iterB = b; 184 while (iterA != iterB) { 185 iterA = iterA.getDominator(); 186 iterB = iterB.getDominator(); 187 } 188 return iterA; 189 } 190 191 /** 192 * @see AbstractControlFlowGraph#commonDominator(AbstractBlockBase, AbstractBlockBase) 193 */ 194 @SuppressWarnings("unchecked") 195 static <T extends AbstractBlockBase<T>> T commonDominatorTyped(T a, T b) { 196 return (T) commonDominator(a, b); 197 } 198}