1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/*
2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Copyright (C) 2007 The Android Open Source Project
3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Licensed under the Apache License, Version 2.0 (the "License");
5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * you may not use this file except in compliance with the License.
6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * You may obtain a copy of the License at
7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *      http://www.apache.org/licenses/LICENSE-2.0
9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *
10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Unless required by applicable law or agreed to in writing, software
11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * distributed under the License is distributed on an "AS IS" BASIS,
12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * See the License for the specific language governing permissions and
14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * limitations under the License.
15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpackage com.android.dx.ssa;
18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.CstInsn;
20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.Insn;
21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.PlainInsn;
22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegOps;
23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpecList;
24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.Rop;
25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.RegisterSpec;
26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.code.Rops;
27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.Constant;
28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.CstInteger;
29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.cst.TypedConstant;
30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.TypeBearer;
31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type;
32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.ArrayList;
34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.BitSet;
35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/**
37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A small variant of Wegman and Zadeck's Sparse Conditional Constant
38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Propagation algorithm.
39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */
40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic class SCCP {
41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Lattice values  */
42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int TOP = 0;
43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int CONSTANT = 1;
44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static final int VARYING = 2;
45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** method we're processing */
46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private SsaMethod ssaMeth;
47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** ssaMeth.getRegCount() */
48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private int regCount;
49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Lattice values for each SSA register */
50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private int[] latticeValues;
51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** For those registers that are constant, this is the constant value */
52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Constant[] latticeConstants;
53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Worklist of basic blocks to be processed */
54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<SsaBasicBlock> cfgWorklist;
55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Worklist of executed basic blocks with phis to be processed */
56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<SsaBasicBlock> cfgPhiWorklist;
57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Bitset containing bits for each block that has been found executable */
58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private BitSet executableBlocks;
59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Worklist for SSA edges.  This is a list of registers to process */
60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<SsaInsn> ssaWorklist;
61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Worklist for SSA edges that represent varying values.  It makes the
63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * algorithm much faster if you move all values to VARYING as fast as
64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * possible.
65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<SsaInsn> varyingWorklist;
67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /** Worklist of potential branches to convert to gotos */
68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private ArrayList<SsaInsn> branchWorklist;
69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private SCCP(SsaMethod ssaMeth) {
71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.ssaMeth = ssaMeth;
72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.regCount = ssaMeth.getRegCount();
73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.latticeValues = new int[this.regCount];
74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.latticeConstants = new Constant[this.regCount];
75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.cfgWorklist = new ArrayList<SsaBasicBlock>();
76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.cfgPhiWorklist = new ArrayList<SsaBasicBlock>();
77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.executableBlocks = new BitSet(ssaMeth.getBlocks().size());
78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.ssaWorklist = new ArrayList<SsaInsn>();
79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.varyingWorklist = new ArrayList<SsaInsn>();
80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        this.branchWorklist = new ArrayList<SsaInsn>();
81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < this.regCount; i++) {
82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            latticeValues[i] = TOP;
83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            latticeConstants[i] = null;
84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Performs sparse conditional constant propagation on a method.
89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param ssaMethod Method to process
90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    public static void process (SsaMethod ssaMethod) {
92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        new SCCP(ssaMethod).run();
93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Adds a SSA basic block to the CFG worklist if it's unexecuted, or
97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * to the CFG phi worklist if it's already executed.
98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param ssaBlock Block to add
99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void addBlockToWorklist(SsaBasicBlock ssaBlock) {
101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (!executableBlocks.get(ssaBlock.getIndex())) {
102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            cfgWorklist.add(ssaBlock);
103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            executableBlocks.set(ssaBlock.getIndex());
104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            cfgPhiWorklist.add(ssaBlock);
106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Adds an SSA register's uses to the SSA worklist.
111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param reg SSA register
112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param latticeValue new lattice value for @param reg.
113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void addUsersToWorklist(int reg, int latticeValue) {
115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (latticeValue == VARYING) {
116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                varyingWorklist.add(insn);
118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                ssaWorklist.add(insn);
122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Sets a lattice value for a register to value.
128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param reg SSA register
129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param value Lattice value
130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param cst Constant value (may be null)
131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return true if the lattice value changed.
132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private boolean setLatticeValueTo(int reg, int value, Constant cst) {
134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (value != CONSTANT) {
135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (latticeValues[reg] != value) {
136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                latticeValues[reg] = value;
137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (latticeValues[reg] != value
142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    || !latticeConstants[reg].equals(cst)) {
143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                latticeValues[reg] = value;
144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                latticeConstants[reg] = cst;
145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return true;
146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return false;
148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulates a PHI node and set the lattice for the result
153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * to the appropriate value.
154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Meet values:
155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * TOP x anything = TOP
156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * VARYING x anything = VARYING
157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * CONSTANT x CONSTANT = CONSTANT if equal constants, VARYING otherwise
158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param insn PHI to simulate.
159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void simulatePhi(PhiInsn insn) {
161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int phiResultReg = insn.getResult().getReg();
162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (latticeValues[phiResultReg] == VARYING) {
164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return;
165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        RegisterSpecList sources = insn.getSources();
168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int phiResultValue = TOP;
169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Constant phiConstant = null;
170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int sourceSize = sources.size();
171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int i = 0; i < sourceSize; i++) {
173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int predBlockIndex = insn.predBlockIndexForSourcesIndex(i);
174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int sourceReg = sources.get(i).getReg();
175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int sourceRegValue = latticeValues[sourceReg];
176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (!executableBlocks.get(predBlockIndex)) {
178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                continue;
179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (sourceRegValue == CONSTANT) {
182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (phiConstant == null) {
183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    phiConstant = latticeConstants[sourceReg];
184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    phiResultValue = CONSTANT;
185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 } else if (!latticeConstants[sourceReg].equals(phiConstant)){
186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    phiResultValue = VARYING;
187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    break;
188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                phiResultValue = sourceRegValue;
191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                break;
192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (setLatticeValueTo(phiResultReg, phiResultValue, phiConstant)) {
195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            addUsersToWorklist(phiResultReg, phiResultValue);
196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulate a block and note the results in the lattice.
201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param block Block to visit
202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void simulateBlock(SsaBasicBlock block) {
204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (SsaInsn insn : block.getInsns()) {
205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (insn instanceof PhiInsn) {
206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                simulatePhi((PhiInsn) insn);
207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                simulateStmt(insn);
209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulate the phis in a block and note the results in the lattice.
215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param block Block to visit
216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void simulatePhiBlock(SsaBasicBlock block) {
218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (SsaInsn insn : block.getInsns()) {
219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (insn instanceof PhiInsn) {
220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                simulatePhi((PhiInsn) insn);
221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return;
223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private static String latticeValName(int latticeVal) {
228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (latticeVal) {
229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case TOP: return "TOP";
230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case CONSTANT: return "CONSTANT";
231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case VARYING: return "VARYING";
232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            default: return "UNKNOWN";
233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulates branch insns, if possible. Adds reachable successor blocks
238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * to the CFG worklists.
239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param insn branch to simulate
240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void simulateBranch(SsaInsn insn) {
242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Rop opcode = insn.getOpcode();
243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        RegisterSpecList sources = insn.getSources();
244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        boolean constantBranch = false;
246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        boolean constantSuccessor = false;
247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        // Check if the insn is a branch with a constant condition
249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (opcode.getBranchingness() == Rop.BRANCH_IF) {
250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Constant cA = null;
251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Constant cB = null;
252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            RegisterSpec specA = sources.get(0);
254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int regA = specA.getReg();
255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (!ssaMeth.isRegALocal(specA) &&
256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    latticeValues[regA] == CONSTANT) {
257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                cA = latticeConstants[regA];
258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (sources.size() == 2) {
261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                RegisterSpec specB = sources.get(1);
262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int regB = specB.getReg();
263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (!ssaMeth.isRegALocal(specB) &&
264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        latticeValues[regB] == CONSTANT) {
265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    cB = latticeConstants[regB];
266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Calculate the result of the condition
270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (cA != null && sources.size() == 1) {
271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                switch (((TypedConstant) cA).getBasicType()) {
272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case Type.BT_INT:
273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        constantBranch = true;
274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        int vA = ((CstInteger) cA).getValue();
275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        switch (opcode.getOpcode()) {
276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_EQ:
277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA == 0);
278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_NE:
280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA != 0);
281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_LT:
283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA < 0);
284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_GE:
286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA >= 0);
287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_LE:
289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA <= 0);
290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_GT:
292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA > 0);
293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            default:
295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                throw new RuntimeException("Unexpected op");
296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        }
297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    default:
299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        // not yet supported
300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else if (cA != null && cB != null) {
302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                switch (((TypedConstant) cA).getBasicType()) {
303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case Type.BT_INT:
304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        constantBranch = true;
305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        int vA = ((CstInteger) cA).getValue();
306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        int vB = ((CstInteger) cB).getValue();
307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        switch (opcode.getOpcode()) {
308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_EQ:
309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA == vB);
310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_NE:
312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA != vB);
313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_LT:
315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA < vB);
316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_GE:
318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA >= vB);
319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_LE:
321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA <= vB);
322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            case RegOps.IF_GT:
324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                constantSuccessor = (vA > vB);
325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                break;
326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            default:
327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                                throw new RuntimeException("Unexpected op");
328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        }
329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    default:
331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        // not yet supported
332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /*
337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * If condition is constant, add only the target block to the
338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         * worklist. Otherwise, add all successors to the worklist.
339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson         */
340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        SsaBasicBlock block = insn.getBlock();
341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (constantBranch) {
343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int successorBlock;
344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (constantSuccessor) {
345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                successorBlock = block.getSuccessorList().get(1);
346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                successorBlock = block.getSuccessorList().get(0);
348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            branchWorklist.add(insn);
351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (int i = 0; i < block.getSuccessorList().size(); i++) {
353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int successorBlock = block.getSuccessorList().get(i);
354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulates math insns, if possible.
361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     *
362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param insn non-null insn to simulate
363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param resultType basic type of the result
364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @return constant result or null if not simulatable.
365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private Constant simulateMath(SsaInsn insn, int resultType) {
367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Insn ropInsn = insn.getOriginalRopInsn();
368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int opcode = insn.getOpcode().getOpcode();
369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        RegisterSpecList sources = insn.getSources();
370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int regA = sources.get(0).getReg();
371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Constant cA;
372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Constant cB;
373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (latticeValues[regA] != CONSTANT) {
375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            cA = null;
376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else {
377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            cA = latticeConstants[regA];
378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (sources.size() == 1) {
381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            CstInsn cstInsn = (CstInsn) ropInsn;
382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            cB = cstInsn.getConstant();
383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        } else { /* sources.size() == 2 */
384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int regB = sources.get(1).getReg();
385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (latticeValues[regB] != CONSTANT) {
386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                cB = null;
387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                cB = latticeConstants[regB];
389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (cA == null || cB == null) {
393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            //TODO handle a constant of 0 with MUL or AND
394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            return null;
395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (resultType) {
398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case Type.BT_INT:
399579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int vR;
400579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                boolean skip=false;
401579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
402579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int vA = ((CstInteger) cA).getValue();
403579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int vB = ((CstInteger) cB).getValue();
404579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
405579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                switch (opcode) {
406579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.ADD:
407579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA + vB;
408579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
409579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.SUB:
410579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        // 1 source for reverse sub, 2 sources for regular sub
411579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        if (sources.size() == 1) {
412579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = vB - vA;
413579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        } else {
414579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = vA - vB;
415579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        }
416579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
417579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.MUL:
418579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA * vB;
419579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
420579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.DIV:
421579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        if (vB == 0) {
422579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            skip = true;
423579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = 0; // just to hide a warning
424579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        } else {
425579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = vA / vB;
426579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        }
427579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
428579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.AND:
429579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA & vB;
430579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
431579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.OR:
432579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA | vB;
433579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
434579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.XOR:
435579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA ^ vB;
436579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
437579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.SHL:
438579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA << vB;
439579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
440579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.SHR:
441579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA >> vB;
442579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
443579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.USHR:
444579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        vR = vA >>> vB;
445579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
446579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    case RegOps.REM:
447579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        if (vB == 0) {
448579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            skip = true;
449579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = 0; // just to hide a warning
450579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        } else {
451579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                            vR = vA % vB;
452579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        }
453579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        break;
454579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    default:
455579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        throw new RuntimeException("Unexpected op");
456579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
457579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
458579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return skip ? null : CstInteger.make(vR);
459579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
460579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            default:
461579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                // not yet supported
462579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return null;
463579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
464579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
465579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
466579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
467579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Simulates a statement and set the result lattice value.
468579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * @param insn instruction to simulate
469579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
470579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void simulateStmt(SsaInsn insn) {
471579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Insn ropInsn = insn.getOriginalRopInsn();
472579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (ropInsn.getOpcode().getBranchingness() != Rop.BRANCH_NONE
473579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                || ropInsn.getOpcode().isCallLike()) {
474579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            simulateBranch(insn);
475579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
476579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
477579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int opcode = insn.getOpcode().getOpcode();
478579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        RegisterSpec result = insn.getResult();
479579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
480579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (result == null) {
481579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Find move-result-pseudo result for int div and int rem
482579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (opcode == RegOps.DIV || opcode == RegOps.REM) {
483579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                SsaBasicBlock succ = insn.getBlock().getPrimarySuccessor();
484579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                result = succ.getInsns().get(0).getResult();
485579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            } else {
486579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                return;
487579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
488579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
489579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
490579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int resultReg = result.getReg();
491579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        int resultValue = VARYING;
492579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        Constant resultConstant = null;
493579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
494579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        switch (opcode) {
495579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.CONST: {
496579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                CstInsn cstInsn = (CstInsn)ropInsn;
497579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                resultValue = CONSTANT;
498579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                resultConstant = cstInsn.getConstant();
499579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                break;
500579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
501579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.MOVE: {
502579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (insn.getSources().size() == 1) {
503579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    int sourceReg = insn.getSources().get(0).getReg();
504579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    resultValue = latticeValues[sourceReg];
505579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    resultConstant = latticeConstants[sourceReg];
506579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
507579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                break;
508579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
509579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.ADD:
510579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.SUB:
511579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.MUL:
512579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.DIV:
513579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.AND:
514579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.OR:
515579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.XOR:
516579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.SHL:
517579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.SHR:
518579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.USHR:
519579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.REM: {
520579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                resultConstant = simulateMath(insn, result.getBasicType());
521579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (resultConstant != null) {
522579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    resultValue = CONSTANT;
523579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
524579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                break;
525579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
526579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            case RegOps.MOVE_RESULT_PSEUDO: {
527579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (latticeValues[resultReg] == CONSTANT) {
528579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    resultValue = latticeValues[resultReg];
529579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    resultConstant = latticeConstants[resultReg];
530579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
531579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                break;
532579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
533579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // TODO: Handle non-int arithmetic.
534579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // TODO: Eliminate check casts that we can prove the type of.
535579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            default: {}
536579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
537579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        if (setLatticeValueTo(resultReg, resultValue, resultConstant)) {
538579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            addUsersToWorklist(resultReg, resultValue);
539579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
540579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
541579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
542579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void run() {
543579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        SsaBasicBlock firstBlock = ssaMeth.getEntryBlock();
544579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        addBlockToWorklist(firstBlock);
545579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
546579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        /* Empty all the worklists by propagating our values */
547579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        while (!cfgWorklist.isEmpty()
548579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                || !cfgPhiWorklist.isEmpty()
549579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                || !ssaWorklist.isEmpty()
550579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                || !varyingWorklist.isEmpty()) {
551579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            while (!cfgWorklist.isEmpty()) {
552579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int listSize = cfgWorklist.size() - 1;
553579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                SsaBasicBlock block = cfgWorklist.remove(listSize);
554579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                simulateBlock(block);
555579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
556579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
557579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            while (!cfgPhiWorklist.isEmpty()) {
558579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int listSize = cfgPhiWorklist.size() - 1;
559579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                SsaBasicBlock block = cfgPhiWorklist.remove(listSize);
560579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                simulatePhiBlock(block);
561579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
562579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
563579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            while (!varyingWorklist.isEmpty()) {
564579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int listSize = varyingWorklist.size() - 1;
565579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                SsaInsn insn = varyingWorklist.remove(listSize);
566579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
567579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (!executableBlocks.get(insn.getBlock().getIndex())) {
568579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    continue;
569579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
570579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
571579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (insn instanceof PhiInsn) {
572579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    simulatePhi((PhiInsn)insn);
573579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                } else {
574579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    simulateStmt(insn);
575579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
576579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
577579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            while (!ssaWorklist.isEmpty()) {
578579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int listSize = ssaWorklist.size() - 1;
579579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                SsaInsn insn = ssaWorklist.remove(listSize);
580579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
581579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (!executableBlocks.get(insn.getBlock().getIndex())) {
582579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    continue;
583579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
584579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
585579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (insn instanceof PhiInsn) {
586579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    simulatePhi((PhiInsn)insn);
587579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                } else {
588579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    simulateStmt(insn);
589579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
590579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
591579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
592579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
593579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        replaceConstants();
594579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        replaceBranches();
595579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
596579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
597579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
598579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Replaces TypeBearers in source register specs with constant type
599579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * bearers if possible. These are then referenced in later optimization
600579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * steps.
601579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
602579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void replaceConstants() {
603579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (int reg = 0; reg < regCount; reg++) {
604579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (latticeValues[reg] != CONSTANT) {
605579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                continue;
606579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
607579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (!(latticeConstants[reg] instanceof TypedConstant)) {
608579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                // We can't do much with these
609579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                continue;
610579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
611579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
612579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            SsaInsn defn = ssaMeth.getDefinitionForRegister(reg);
613579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            TypeBearer typeBearer = defn.getResult().getTypeBearer();
614579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
615579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (typeBearer.isConstant()) {
616579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                /*
617579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 * The definition was a constant already.
618579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 * The uses should be as well.
619579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                 */
620579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                continue;
621579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
622579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
623579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Update the destination RegisterSpec with the constant value
624579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            RegisterSpec dest = defn.getResult();
625579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            RegisterSpec newDest
626579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    = dest.withType((TypedConstant)latticeConstants[reg]);
627579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            defn.setResult(newDest);
628579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
629579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
630579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Update the sources RegisterSpec's of all non-move uses.
631579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * These will be used in later steps.
632579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
633579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
634579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (insn.isPhiOrMove()) {
635579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    continue;
636579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
637579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
638579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                NormalSsaInsn nInsn = (NormalSsaInsn) insn;
639579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                RegisterSpecList sources = insn.getSources();
640579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
641579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int index = sources.indexOfRegister(reg);
642579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
643579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                RegisterSpec spec = sources.get(index);
644579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                RegisterSpec newSpec
645579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                        = spec.withType((TypedConstant)latticeConstants[reg]);
646579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
647579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                nInsn.changeOneSource(index, newSpec);
648579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
649579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
650579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
651579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
652579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    /**
653579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     * Replaces branches that have constant conditions with gotos
654579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson     */
655579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    private void replaceBranches() {
656579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        for (SsaInsn insn : branchWorklist) {
657579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Find if a successor block is never executed
658579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int oldSuccessor = -1;
659579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            SsaBasicBlock block = insn.getBlock();
660579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            int successorSize = block.getSuccessorList().size();
661579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            for (int i = 0; i < successorSize; i++) {
662579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                int successorBlock = block.getSuccessorList().get(i);
663579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                if (!executableBlocks.get(successorBlock)) {
664579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                    oldSuccessor = successorBlock;
665579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                }
666579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            }
667579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
668579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            /*
669579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * Prune branches that have already been handled and ones that no
670579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             * longer have constant conditions (no nonexecutable successors)
671579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson             */
672579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            if (successorSize != 2 || oldSuccessor == -1) continue;
673579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson
674579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            // Replace branch with goto
675579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            Insn originalRopInsn = insn.getOriginalRopInsn();
676579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            block.replaceLastInsn(new PlainInsn(Rops.GOTO,
677579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson                originalRopInsn.getPosition(), null, RegisterSpecList.EMPTY));
678579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson            block.removeSuccessor(oldSuccessor);
679579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson        }
680579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson    }
681579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}
682