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.*; 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.Type; 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.rop.type.TypeBearer; 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport com.android.dx.util.Hex; 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.ArrayList; 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonimport java.util.List; 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson/** 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A Phi instruction (magical post-control-flow-merge) instruction 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * in SSA form. Will be converted to moves in predecessor blocks before 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * conversion back to ROP form. 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonpublic final class PhiInsn extends SsaInsn { 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * result register. The original result register of the phi insn 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * is needed during the renaming process after the new result 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * register has already been chosen. 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final int ropResultReg; 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@code non-null;} operands of the instruction; built up by 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@link #addPhiOperand} 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private final ArrayList<Operand> operands = new ArrayList<Operand>(); 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@code null-ok;} source registers; constructed lazily */ 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private RegisterSpecList sources; 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Constructs a new phi insn with no operands. 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param resultReg the result reg for this phi insn 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param block block containing this insn. 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public PhiInsn(RegisterSpec resultReg, SsaBasicBlock block) { 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super(resultReg, block); 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ropResultReg = resultReg.getReg(); 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Makes a phi insn with a void result type. 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param resultReg the result register for this phi insn. 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param block block containing this insn. 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public PhiInsn(final int resultReg, final SsaBasicBlock block) { 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * The result type here is bogus: The type depends on the 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * operand and will be derived later. 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson super(RegisterSpec.make(resultReg, Type.VOID), block); 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ropResultReg = resultReg; 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public PhiInsn clone() { 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new UnsupportedOperationException("can't clone phi"); 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Updates the TypeBearers of all the sources (phi operands) to be 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * the current TypeBearer of the register-defining instruction's result. 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * This is used during phi-type resolution.<p> 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Note that local association of operands are preserved in this step. 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param ssaMeth method that contains this insn 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void updateSourcesToDefinitions(SsaMethod ssaMeth) { 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec def 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson = ssaMeth.getDefinitionForRegister( 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson o.regSpec.getReg()).getResult(); 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson o.regSpec = o.regSpec.withType(def.getType()); 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources = null; 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Changes the result type. Used during phi type resolution 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param type {@code non-null;} new TypeBearer 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param local {@code null-ok;} new local info, if available 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void changeResultType(TypeBearer type, LocalItem local) { 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson setResult(RegisterSpec.makeLocalOptional( 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getResult().getReg(), type, local)); 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the original rop-form result reg. This is useful during renaming. 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return the original rop-form result reg 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int getRopResultReg() { 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ropResultReg; 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Adds an operand to this phi instruction. 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param registerSpec register spec, including type and reg of operand 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param predBlock predecessor block to be associated with this operand 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void addPhiOperand(RegisterSpec registerSpec, 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson SsaBasicBlock predBlock) { 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson operands.add(new Operand(registerSpec, predBlock.getIndex(), 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson predBlock.getRopLabel())); 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Un-cache sources, in case someone has already called getSources(). 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources = null; 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Removes all operand uses of a register from this phi instruction. 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param registerSpec register spec, including type and reg of operand 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void removePhiRegister(RegisterSpec registerSpec) { 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ArrayList<Operand> operandsToRemove = new ArrayList<Operand>(); 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (o.regSpec.getReg() == registerSpec.getReg()) { 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson operandsToRemove.add(o); 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson operands.removeAll(operandsToRemove); 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Un-cache sources, in case someone has already called getSources(). 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources = null; 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets the index of the pred block associated with the RegisterSpec 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * at the particular getSources() index. 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param sourcesIndex index of source in getSources() 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return block index 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public int predBlockIndexForSourcesIndex(int sourcesIndex) { 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return operands.get(sourcesIndex).blockIndex; 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@inheritDoc} 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Always returns null for {@code PhiInsn}s. 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Rop getOpcode() { 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@inheritDoc} 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Always returns null for {@code PhiInsn}s. 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Insn getOriginalRopInsn() { 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return null; 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * {@inheritDoc} 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Always returns false for {@code PhiInsn}s. 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean canThrow() { 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Gets sources. Constructed lazily from phi operand data structures and 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * then cached. 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return {@code non-null;} sources list 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpecList getSources() { 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (sources != null) { 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sources; 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (operands.size() == 0) { 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // How'd this happen? A phi insn with no operand? 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return RegisterSpecList.EMPTY; 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int szSources = operands.size(); 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources = new RegisterSpecList(szSources); 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < szSources; i++) { 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson Operand o = operands.get(i); 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources.set(i, o.regSpec); 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources.setImmutable(); 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sources; 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean isRegASource(int reg) { 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /* 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Avoid creating a sources list in case it has not already been 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * created. 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (o.regSpec.getReg() == reg) { 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return true if all operands use the same register 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean areAllOperandsEqual() { 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (operands.size() == 0 ) { 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // This should never happen. 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int firstReg = operands.get(0).regSpec.getReg(); 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (firstReg != o.regSpec.getReg()) { 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final void mapSourceRegisters(RegisterMapper mapper) { 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec old = o.regSpec; 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson o.regSpec = mapper.map(old); 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (old != o.regSpec) { 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson getBlock().getParent().onSourceChanged(this, old, o.regSpec); 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sources = null; 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Always throws an exeption, since a phi insn may not be 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * converted back to rop form. 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return always throws exception 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Insn toRopInsn() { 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson throw new IllegalArgumentException( 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson "Cannot convert phi insns to rop form"); 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns the list of predecessor blocks associated with all operands 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * that have {@code reg} as an operand register. 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param reg register to look up 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param ssaMeth method we're operating on 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return list of predecessor blocks, empty if none 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public List<SsaBasicBlock> predBlocksForReg(int reg, SsaMethod ssaMeth) { 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ArrayList<SsaBasicBlock> ret = new ArrayList<SsaBasicBlock>(); 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (Operand o : operands) { 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (o.regSpec.getReg() == reg) { 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ret.add(ssaMeth.getBlocks().get(o.blockIndex)); 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ret; 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean isPhiOrMove() { 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public boolean hasSideEffect() { 317579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return Optimizer.getPreserveLocals() && getLocalAssignment() != null; 318579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 319579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 320579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 321579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson @Override 322579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void accept(SsaInsn.Visitor v) { 323579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson v.visitPhiInsn(this); 324579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 325579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 326579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** {@inheritDoc} */ 327579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public String toHuman() { 328579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return toHumanWithInline(null); 329579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 330579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 331579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 332579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Returns human-readable string for listing dumps. This method 333579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * allows sub-classes to specify extra text. 334579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * 335579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @param extra {@code null-ok;} the argument to print after the opcode 336579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * @return human-readable string for listing dumps 337579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 338579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson protected final String toHumanWithInline(String extra) { 339579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson StringBuffer sb = new StringBuffer(80); 340579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 341579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(SourcePosition.NO_INFO); 342579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(": phi"); 343579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 344579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (extra != null) { 345579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append("("); 346579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(extra); 347579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(")"); 348579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 349579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 350579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RegisterSpec result = getResult(); 351579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 352579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (result == null) { 353579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" ."); 354579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 355579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" "); 356579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(result.toHuman()); 357579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 358579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 359579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" <-"); 360579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 361579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int sz = getSources().size(); 362579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (sz == 0) { 363579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" ."); 364579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } else { 365579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (int i = 0; i < sz; i++) { 366579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(" "); 367579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sb.append(sources.get(i).toHuman() 368579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson + "[b=" 369579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson + Hex.u2(operands.get(i).ropLabel) + "]"); 370579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 371579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 372579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 373579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return sb.toString(); 374579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 375579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 376579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 377579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * A single phi operand, consiting of source register and block index 378579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * for move. 379579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 380579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private static class Operand { 381579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public RegisterSpec regSpec; 382579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final int blockIndex; 383579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public final int ropLabel; // only used for debugging 384579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 385579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public Operand(RegisterSpec regSpec, int blockIndex, int ropLabel) { 386579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.regSpec = regSpec; 387579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.blockIndex = blockIndex; 388579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson this.ropLabel = ropLabel; 389579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 390579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 391579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 392579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson /** 393579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson * Visitor interface for instances of this (outer) class. 394579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson */ 395579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public static interface Visitor { 396579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public void visitPhiInsn(PhiInsn insn); 397579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 398579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 399