1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/* 2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License. 6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at 7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and 14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License. 15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage com.android.dx.ssa; 18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.IntSet; 20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.BitIntSet; 21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.ListIntSet; 22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList; 24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.Arrays; 25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.BitSet; 26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/** 28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calculates the dominance-frontiers of a methot's basic blocks. 29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Algorithm from "A Simple, Fast Dominance Algorithm" by Cooper, 30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Harvey, and Kennedy; transliterated to Java. 31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic class DomFront { 3399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** local debug flag */ 34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private static boolean DEBUG = false; 35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code non-null;} method being processed */ 37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final SsaMethod meth; 3899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final ArrayList<SsaBasicBlock> nodes; 40de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private final DomInfo[] domInfos; 42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Dominance-frontier information for a single basic block. 45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public static class DomInfo { 4799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** 4899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * {@code null-ok;} the dominance frontier set indexed by 4999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * block index 5099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */ 5199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project public IntSet dominanceFrontiers; 5299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 5399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /** {@code >= 0 after run();} the index of the immediate dominator */ 5499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project public int idom = -1; 55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 58de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * Constructs instance. Call {@link DomFront#run} to process. 59de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro * 6099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @param meth {@code non-null;} method to process 61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DomFront(SsaMethod meth) { 63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project this.meth = meth; 64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project nodes = meth.getBlocks(); 65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int szNodes = nodes.size(); 67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project domInfos = new DomInfo[szNodes]; 68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project domInfos[i] = new DomInfo(); 71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 75f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calculates the dominance frontier information for the method. 76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * 7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * @return {@code non-null;} an array of DomInfo structures 78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 79f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project public DomInfo[] run() { 80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int szNodes = nodes.size(); 81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SsaBasicBlock node = nodes.get(i); 85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("pred[" + i + "]: " 86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + node.getPredecessors()); 87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project Dominators methDom = Dominators.make(meth, domInfos, false); 91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DomInfo info = domInfos[i]; 95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("idom[" + i + "]: " 96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + info.idom); 97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project buildDomTree(); 101de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro 102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project debugPrintDomChildren(); 104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project domInfos[i].dominanceFrontiers 108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project = SetFactory.makeDomFrontSet(szNodes); 109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project calcDomFronts(); 112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (DEBUG) { 114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("df[" + i + "]: " 116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + domInfos[i].dominanceFrontiers); 117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project return domInfos; 121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void debugPrintDomChildren() { 124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int szNodes = nodes.size(); 125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SsaBasicBlock node = nodes.get(i); 128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project StringBuffer sb = new StringBuffer(); 129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('{'); 131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project boolean comma = false; 13241aecd0a6bfea1e9a6713014b2b3d56fec8c552cDan Bornstein for (SsaBasicBlock child : node.getDomChildren()) { 133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (comma) { 134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(','); 135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append(child); 137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project comma = true; 138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project sb.append('}'); 140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project System.out.println("domChildren[" + node + "]: " 142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project + sb); 143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 147f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * The dominators algorithm leaves us knowing who the immediate dominator 148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * is for each node. This sweeps the node list and builds the proper 149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * dominance tree. 150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void buildDomTree() { 152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int szNodes = nodes.size(); 153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = 0; i < szNodes; i++) { 155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DomInfo info = domInfos[i]; 156e31ed7e916d212840dd5639afa01938bea58b2b8jeffhao 157e31ed7e916d212840dd5639afa01938bea58b2b8jeffhao if (info.idom == -1) continue; 158e31ed7e916d212840dd5639afa01938bea58b2b8jeffhao 159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SsaBasicBlock domParent = nodes.get(info.idom); 160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project domParent.addDomChild(nodes.get(i)); 161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project /** 165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Calculates the dominance-frontier set. 166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * from "A Simple, Fast Dominance Algorithm" by Cooper, 167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Harvey, and Kennedy; transliterated to Java. 168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */ 169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project private void calcDomFronts() { 170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project int szNodes = nodes.size(); 171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int b = 0; b < szNodes; b++) { 173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project SsaBasicBlock nb = nodes.get(b); 174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DomInfo nbInfo = domInfos[b]; 175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project BitSet pred = nb.getPredecessors(); 17699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project if (pred.cardinality() > 1) { 178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project for (int i = pred.nextSetBit(0); i >= 0; 179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project i = pred.nextSetBit(i + 1)) { 180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project 18199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project for (int runnerIndex = i; 18299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project runnerIndex != nbInfo.idom; /* empty */) { 18399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project /* 18499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * We can stop if we hit a block we already 18599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * added label to, since we must be at a part 18699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project * of the dom tree we have seen before. 18799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project */ 188e31ed7e916d212840dd5639afa01938bea58b2b8jeffhao if (runnerIndex == -1) break; 189e31ed7e916d212840dd5639afa01938bea58b2b8jeffhao 190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project DomInfo runnerInfo = domInfos[runnerIndex]; 19199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 19299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project if (runnerInfo.dominanceFrontiers.has(b)) { 193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project break; 19499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project } 19599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project 19699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project // Add b to runner's dominance frontier set. 197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project runnerInfo.dominanceFrontiers.add(b); 198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project runnerIndex = runnerInfo.idom; 199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project } 204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project} 205