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