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.rop.code.*;
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.Type;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.rop.type.TypeBearer;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport com.android.dx.util.Hex;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.ArrayList;
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.util.List;
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * A Phi instruction (magical post-control-flow-merge) instruction
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * in SSA form. Will be converted to moves in predecessor blocks before
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * conversion back to ROP form.
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic final class PhiInsn extends SsaInsn {
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
3499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * result register. The original result register of the phi insn
3599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * is needed during the renaming process after the new result
3699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * register has already been chosen.
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
3899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private final int ropResultReg;
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
4199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@code non-null;} operands of the instruction; built up by
4299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * {@link #addPhiOperand}
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
4499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private final ArrayList<Operand> operands = new ArrayList<Operand>();
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
4699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@code null-ok;} source registers; constructed lazily */
4799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private RegisterSpecList sources;
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a new phi insn with no operands.
51de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param resultReg the result reg for this phi insn
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param block block containing this insn.
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
5599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn(RegisterSpec resultReg, SsaBasicBlock block) {
5699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        super(resultReg, block);
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ropResultReg = resultReg.getReg();
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Makes a phi insn with a void result type.
62de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param resultReg the result register for this phi insn.
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param block block containing this insn.
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
6699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn(final int resultReg, final SsaBasicBlock block) {
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
6899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * The result type here is bogus: The type depends on the
6999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * operand and will be derived later.
70f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
7199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        super(RegisterSpec.make(resultReg, Type.VOID), block);
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ropResultReg = resultReg;
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
7599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@inheritDoc} */
76b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    @Override
7799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public PhiInsn clone() {
7899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        throw new UnsupportedOperationException("can't clone phi");
7999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
8099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Updates the TypeBearers of all the sources (phi operands) to be
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the current TypeBearer of the register-defining instruction's result.
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This is used during phi-type resolution.<p>
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Note that local association of operands are preserved in this step.
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ssaMeth method that contains this insn
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
9099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public void updateSourcesToDefinitions(SsaMethod ssaMeth) {
9199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
92de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro            RegisterSpec def
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                = ssaMeth.getDefinitionForRegister(
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    o.regSpec.getReg()).getResult();
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            o.regSpec = o.regSpec.withType(def.getType());
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Changes the result type. Used during phi type resolution
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
10599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param type {@code non-null;} new TypeBearer
10699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param local {@code null-ok;} new local info, if available
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
10899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public void changeResultType(TypeBearer type, LocalItem local) {
10999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        setResult(RegisterSpec.makeLocalOptional(
11099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                          getResult().getReg(), type, local));
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
11499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Gets the original rop-form result reg. This is useful during renaming.
115de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
11699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return the original rop-form result reg
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
11899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public int getRopResultReg() {
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ropResultReg;
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
12399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Adds an operand to this phi instruction.
124de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param registerSpec register spec, including type and reg of operand
12699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param predBlock predecessor block to be associated with this operand
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void addPhiOperand(RegisterSpec registerSpec,
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            SsaBasicBlock predBlock) {
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        operands.add(new Operand(registerSpec, predBlock.getIndex(),
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                predBlock.getRopLabel()));
132de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
13399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        // Un-cache sources, in case someone has already called getSources().
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
138b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     * Removes all operand uses of a register from this phi instruction.
139b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     *
140b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     * @param registerSpec register spec, including type and reg of operand
141b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao     */
142b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    public void removePhiRegister(RegisterSpec registerSpec) {
143b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        ArrayList<Operand> operandsToRemove = new ArrayList<Operand>();
144b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        for (Operand o : operands) {
145b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao            if (o.regSpec.getReg() == registerSpec.getReg()) {
146b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao                operandsToRemove.add(o);
147b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao            }
148b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        }
149b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
150b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        operands.removeAll(operandsToRemove);
151b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
152b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        // Un-cache sources, in case someone has already called getSources().
153b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao        sources = null;
154b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    }
155b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao
156b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    /**
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the index of the pred block associated with the RegisterSpec
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * at the particular getSources() index.
159de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
160f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param sourcesIndex index of source in getSources()
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return block index
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public int predBlockIndexForSourcesIndex(int sourcesIndex) {
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return operands.get(sourcesIndex).blockIndex;
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
166f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
17099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns null for {@code PhiInsn}s.
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Rop getOpcode() {
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
178f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
18099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns null for {@code PhiInsn}s.
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn getOriginalRopInsn() {
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@inheritDoc}
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
19099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always returns false for {@code PhiInsn}s.
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
192f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean canThrow() {
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets sources. Constructed lazily from phi operand data structures and
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * then cached.
200de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
20199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return {@code non-null;} sources list
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
203b75d1ca580c6a6c7ebdc813dff2855205063fc46jeffhao    @Override
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public RegisterSpecList getSources() {
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sources != null) {
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return sources;
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (operands.size() == 0) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // How'd this happen? A phi insn with no operand?
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return RegisterSpecList.EMPTY;
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int szSources = operands.size();
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = new RegisterSpecList(szSources);
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        for (int i = 0; i < szSources; i++) {
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Operand o = operands.get(i);
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sources.set(i, o.regSpec);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources.setImmutable();
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sources;
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean isRegASource(int reg) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /*
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         * Avoid creating a sources list in case it has not already been
23299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project         * created.
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project         */
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
23599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (o.regSpec.getReg() == reg) {
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return true;
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return true if all operands use the same register
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public boolean areAllOperandsEqual() {
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (operands.size() == 0 ) {
24999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            // This should never happen.
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return true;
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int firstReg = operands.get(0).regSpec.getReg();
25499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (firstReg != o.regSpec.getReg()) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return false;
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return true;
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final void mapSourceRegisters(RegisterMapper mapper) {
26699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            RegisterSpec old = o.regSpec;
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            o.regSpec = mapper.map(old);
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (old != o.regSpec) {
27099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project                getBlock().getParent().onSourceChanged(this, old, o.regSpec);
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
273f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sources = null;
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
27799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Always throws an exeption, since a phi insn may not be
27899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * converted back to rop form.
279de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return always throws exception
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Insn toRopInsn() {
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new IllegalArgumentException(
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                "Cannot convert phi insns to rop form");
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the list of predecessor blocks associated with all operands
29099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * that have {@code reg} as an operand register.
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param reg register to look up
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param ssaMeth method we're operating on
29499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @return list of predecessor blocks, empty if none
295f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
29699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public List<SsaBasicBlock> predBlocksForReg(int reg, SsaMethod ssaMeth) {
29799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        ArrayList<SsaBasicBlock> ret = new ArrayList<SsaBasicBlock>();
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
29999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        for (Operand o : operands) {
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (o.regSpec.getReg() == reg) {
301f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ret.add(ssaMeth.getBlocks().get(o.blockIndex));
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return ret;
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
31099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public boolean isPhiOrMove() {
311de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        return true;
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
31599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    @Override
31699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public boolean hasSideEffect() {
317f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return Optimizer.getPreserveLocals() && getLocalAssignment() != null;
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /** {@inheritDoc} */
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    @Override
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public void accept(SsaInsn.Visitor v) {
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        v.visitPhiInsn(this);
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /** {@inheritDoc} */
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public String toHuman() {
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return toHumanWithInline(null);
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
33299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Returns human-readable string for listing dumps. This method
33399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * allows sub-classes to specify extra text.
334de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro     *
33599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * @param extra {@code null-ok;} the argument to print after the opcode
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return human-readable string for listing dumps
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected final String toHumanWithInline(String extra) {
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        StringBuffer sb = new StringBuffer(80);
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(SourcePosition.NO_INFO);
342de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro        sb.append(": phi");
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (extra != null) {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append("(");
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(extra);
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(")");
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
35099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        RegisterSpec result = getResult();
351de75089fb7216d19e9c22cce4dc62a49513477d3Carl Shapiro
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result == null) {
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" ");
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(result.toHuman());
357f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
358f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
359f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        sb.append(" <-");
360f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int sz = getSources().size();
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (sz == 0) {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            sb.append(" .");
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            for (int i = 0; i < sz; i++) {
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(" ");
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                sb.append(sources.get(i).toHuman()
368f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + "[b="
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        + Hex.u2(operands.get(i).ropLabel)  + "]");
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return sb.toString();
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
37599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
37699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /**
37799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * A single phi operand, consiting of source register and block index
37899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * for move.
37999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
38099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    private static class Operand {
38199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public RegisterSpec regSpec;
38299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public final int blockIndex;
38399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public final int ropLabel;       // only used for debugging
38499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
3854b4413ab3d8de5805276cfcde3d7f535d9f64e85Dan Bornstein        public Operand(RegisterSpec regSpec, int blockIndex, int ropLabel) {
38699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.regSpec = regSpec;
38799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.blockIndex = blockIndex;
38899409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project            this.ropLabel = ropLabel;
38999409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        }
39099409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
39199409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project
39299409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    /**
39399409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     * Visitor interface for instances of this (outer) class.
39499409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project     */
39599409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    public static interface Visitor {
39699409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project        public void visitPhiInsn(PhiInsn insn);
39799409883d9c4c0ffb49b070ce307bb33a9dfe9f1The Android Open Source Project    }
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
399