blob: 20a8bdb0161b046603ff10c1179716f6bdc06baf [file] [log] [blame]
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +01001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "ssa_builder.h"
Nicolas Geoffray184d6402014-06-09 14:06:02 +010018
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010019#include "nodes.h"
Calin Juravle10e244f2015-01-26 18:54:32 +000020#include "primitive_type_propagation.h"
Nicolas Geoffray31596742014-11-24 15:28:45 +000021#include "ssa_phi_elimination.h"
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +010022
23namespace art {
24
David Brazdil1749e2c2015-09-28 13:49:59 +010025void SsaBuilder::SetLoopPhiInputs() {
26 for (HBasicBlock* block : loop_headers_) {
27 for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
28 HPhi* phi = it.Current()->AsPhi();
29 for (HBasicBlock* predecessor : block->GetPredecessors()) {
30 HInstruction* input = ValueOfLocal(predecessor, phi->GetRegNumber());
31 phi->AddInput(input);
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +000032 }
33 }
34 }
35}
36
Calin Juravlea4f88312015-04-16 12:57:19 +010037void SsaBuilder::FixNullConstantType() {
38 // The order doesn't matter here.
39 for (HReversePostOrderIterator itb(*GetGraph()); !itb.Done(); itb.Advance()) {
40 for (HInstructionIterator it(itb.Current()->GetInstructions()); !it.Done(); it.Advance()) {
41 HInstruction* equality_instr = it.Current();
42 if (!equality_instr->IsEqual() && !equality_instr->IsNotEqual()) {
43 continue;
44 }
45 HInstruction* left = equality_instr->InputAt(0);
46 HInstruction* right = equality_instr->InputAt(1);
Nicolas Geoffray51d400d2015-06-15 09:01:08 +010047 HInstruction* int_operand = nullptr;
Calin Juravlea4f88312015-04-16 12:57:19 +010048
Nicolas Geoffray51d400d2015-06-15 09:01:08 +010049 if ((left->GetType() == Primitive::kPrimNot) && (right->GetType() == Primitive::kPrimInt)) {
50 int_operand = right;
51 } else if ((right->GetType() == Primitive::kPrimNot)
52 && (left->GetType() == Primitive::kPrimInt)) {
53 int_operand = left;
Calin Juravlea4f88312015-04-16 12:57:19 +010054 } else {
55 continue;
56 }
57
58 // If we got here, we are comparing against a reference and the int constant
59 // should be replaced with a null constant.
Nicolas Geoffray51d400d2015-06-15 09:01:08 +010060 // Both type propagation and redundant phi elimination ensure `int_operand`
61 // can only be the 0 constant.
62 DCHECK(int_operand->IsIntConstant());
63 DCHECK_EQ(0, int_operand->AsIntConstant()->GetValue());
64 equality_instr->ReplaceInput(GetGraph()->GetNullConstant(), int_operand == right ? 1 : 0);
Calin Juravlea4f88312015-04-16 12:57:19 +010065 }
66 }
67}
68
69void SsaBuilder::EquivalentPhisCleanup() {
70 // The order doesn't matter here.
71 for (HReversePostOrderIterator itb(*GetGraph()); !itb.Done(); itb.Advance()) {
72 for (HInstructionIterator it(itb.Current()->GetPhis()); !it.Done(); it.Advance()) {
73 HPhi* phi = it.Current()->AsPhi();
74 HPhi* next = phi->GetNextEquivalentPhiWithSameType();
75 if (next != nullptr) {
David Brazdil1749e2c2015-09-28 13:49:59 +010076 // Make sure we do not replace a live phi with a dead phi. A live phi
77 // has been handled by the type propagation phase, unlike a dead phi.
Nicolas Geoffray4230e182015-06-29 14:34:46 +010078 if (next->IsLive()) {
79 phi->ReplaceWith(next);
David Brazdil1749e2c2015-09-28 13:49:59 +010080 phi->SetDead();
Nicolas Geoffray4230e182015-06-29 14:34:46 +010081 } else {
82 next->ReplaceWith(phi);
83 }
Calin Juravlea4f88312015-04-16 12:57:19 +010084 DCHECK(next->GetNextEquivalentPhiWithSameType() == nullptr)
85 << "More then one phi equivalent with type " << phi->GetType()
86 << " found for phi" << phi->GetId();
87 }
88 }
89 }
90}
91
David Brazdil1749e2c2015-09-28 13:49:59 +010092void SsaBuilder::FixEnvironmentPhis() {
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +000093 for (HReversePostOrderIterator it(*GetGraph()); !it.Done(); it.Advance()) {
94 HBasicBlock* block = it.Current();
95 for (HInstructionIterator it_phis(block->GetPhis()); !it_phis.Done(); it_phis.Advance()) {
96 HPhi* phi = it_phis.Current()->AsPhi();
97 // If the phi is not dead, or has no environment uses, there is nothing to do.
98 if (!phi->IsDead() || !phi->HasEnvironmentUses()) continue;
99 HInstruction* next = phi->GetNext();
David Brazdild0180f92015-09-22 14:39:58 +0100100 if (!phi->IsVRegEquivalentOf(next)) continue;
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000101 if (next->AsPhi()->IsDead()) {
102 // If the phi equivalent is dead, check if there is another one.
103 next = next->GetNext();
David Brazdild0180f92015-09-22 14:39:58 +0100104 if (!phi->IsVRegEquivalentOf(next)) continue;
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000105 // There can be at most two phi equivalents.
David Brazdild0180f92015-09-22 14:39:58 +0100106 DCHECK(!phi->IsVRegEquivalentOf(next->GetNext()));
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000107 if (next->AsPhi()->IsDead()) continue;
108 }
109 // We found a live phi equivalent. Update the environment uses of `phi` with it.
110 phi->ReplaceWith(next);
111 }
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000112 }
David Brazdil1749e2c2015-09-28 13:49:59 +0100113}
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000114
David Brazdil1749e2c2015-09-28 13:49:59 +0100115void SsaBuilder::BuildSsa() {
116 // 1) Visit in reverse post order. We need to have all predecessors of a block visited
117 // (with the exception of loops) in order to create the right environment for that
118 // block. For loops, we create phis whose inputs will be set in 2).
119 for (HReversePostOrderIterator it(*GetGraph()); !it.Done(); it.Advance()) {
120 VisitBasicBlock(it.Current());
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000121 }
122
David Brazdil1749e2c2015-09-28 13:49:59 +0100123 // 2) Set inputs of loop phis.
124 SetLoopPhiInputs();
125
126 // 3) Propagate types of phis. At this point, phis are typed void in the general
127 // case, or float/double/reference if we created an equivalent phi. So we need
128 // to propagate the types across phis to give them a correct type. If a type
129 // conflict is detected in this stage, the phi is marked dead.
130 PrimitiveTypePropagation(GetGraph()).Run();
131
132 // 4) When creating equivalent phis we copy the inputs of the original phi which
133 // may be improperly typed. This was fixed during the type propagation in 4) but
134 // as a result we may end up with two equivalent phis with the same type for
135 // the same dex register. This pass cleans them up.
136 EquivalentPhisCleanup();
137
138 // 5) Mark dead phis. This will mark phis which are not used by instructions or
139 // other live phis. If compiling as debuggable code, phis will also be kept live
140 // if they have an environment use.
141 SsaDeadPhiElimination dead_phis(GetGraph());
142 dead_phis.MarkDeadPhis();
143
144 // 6) Make sure environments use the right phi equivalent: a phi marked dead
145 // can have a phi equivalent that is not dead. In that case we have to replace
146 // it with the live equivalent because deoptimization and try/catch rely on
147 // environments containing values of all live vregs at that point. Note that
148 // there can be multiple phis for the same Dex register that are live
149 // (for example when merging constants), in which case it is okay for the
150 // environments to just reference one.
151 FixEnvironmentPhis();
152
153 // 7) Now that the right phis are used for the environments, we can eliminate
154 // phis we do not need. Regardless of the debuggable status, this phase is
155 /// necessary for statement (b) of the SsaBuilder (see ssa_builder.h), as well
156 // as for the code generation, which does not deal with phis of conflicting
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000157 // input types.
158 dead_phis.EliminateDeadPhis();
159
David Brazdil1749e2c2015-09-28 13:49:59 +0100160 // 8) Now that the graph is correctly typed, we can get rid of redundant phis.
161 // Note that we cannot do this phase before type propagation, otherwise
162 // we could get rid of phi equivalents, whose presence is a requirement for the
163 // type propagation phase. Note that this is to satisfy statement (a) of the
164 // SsaBuilder (see ssa_builder.h).
165 SsaRedundantPhiElimination(GetGraph()).Run();
166
167 // 9) Fix the type for null constants which are part of an equality comparison.
168 // We need to do this after redundant phi elimination, to ensure the only cases
169 // that we can see are reference comparison against 0. The redundant phi
170 // elimination ensures we do not see a phi taking two 0 constants in a HEqual
171 // or HNotEqual.
172 FixNullConstantType();
173
174 // 10) Clear locals.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100175 for (HInstructionIterator it(GetGraph()->GetEntryBlock()->GetInstructions());
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100176 !it.Done();
177 it.Advance()) {
178 HInstruction* current = it.Current();
Roland Levillain476df552014-10-09 17:51:36 +0100179 if (current->IsLocal()) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100180 current->GetBlock()->RemoveInstruction(current);
181 }
182 }
183}
184
David Brazdileead0712015-09-18 14:58:57 +0100185ArenaVector<HInstruction*>* SsaBuilder::GetLocalsFor(HBasicBlock* block) {
David Brazdileead0712015-09-18 14:58:57 +0100186 ArenaVector<HInstruction*>* locals = &locals_for_[block->GetBlockId()];
187 const size_t vregs = GetGraph()->GetNumberOfVRegs();
188 if (locals->empty() && vregs != 0u) {
189 locals->resize(vregs, nullptr);
190
191 if (block->IsCatchBlock()) {
192 ArenaAllocator* arena = GetGraph()->GetArena();
193 // We record incoming inputs of catch phis at throwing instructions and
194 // must therefore eagerly create the phis. Phis for undefined vregs will
195 // be deleted when the first throwing instruction with the vreg undefined
196 // is encountered. Unused phis will be removed by dead phi analysis.
197 for (size_t i = 0; i < vregs; ++i) {
198 // No point in creating the catch phi if it is already undefined at
199 // the first throwing instruction.
200 if ((*current_locals_)[i] != nullptr) {
201 HPhi* phi = new (arena) HPhi(arena, i, 0, Primitive::kPrimVoid);
202 block->AddPhi(phi);
203 (*locals)[i] = phi;
204 }
205 }
206 }
207 }
208 return locals;
209}
210
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100211HInstruction* SsaBuilder::ValueOfLocal(HBasicBlock* block, size_t local) {
Vladimir Marko71bf8092015-09-15 15:33:14 +0100212 ArenaVector<HInstruction*>* locals = GetLocalsFor(block);
Vladimir Marko71bf8092015-09-15 15:33:14 +0100213 return (*locals)[local];
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100214}
215
216void SsaBuilder::VisitBasicBlock(HBasicBlock* block) {
217 current_locals_ = GetLocalsFor(block);
218
David Brazdilffee3d32015-07-06 11:48:53 +0100219 if (block->IsCatchBlock()) {
220 // Catch phis were already created and inputs collected from throwing sites.
David Brazdild0180f92015-09-22 14:39:58 +0100221 if (kIsDebugBuild) {
222 // Make sure there was at least one throwing instruction which initialized
223 // locals (guaranteed by HGraphBuilder) and that all try blocks have been
224 // visited already (from HTryBoundary scoping and reverse post order).
225 bool throwing_instruction_found = false;
226 bool catch_block_visited = false;
227 for (HReversePostOrderIterator it(*GetGraph()); !it.Done(); it.Advance()) {
228 HBasicBlock* current = it.Current();
229 if (current == block) {
230 catch_block_visited = true;
231 } else if (current->IsTryBlock() &&
232 current->GetTryCatchInformation()->GetTryEntry().HasExceptionHandler(*block)) {
233 DCHECK(!catch_block_visited) << "Catch block visited before its try block.";
234 throwing_instruction_found |= current->HasThrowingInstructions();
235 }
236 }
237 DCHECK(throwing_instruction_found) << "No instructions throwing into a live catch block.";
238 }
David Brazdilffee3d32015-07-06 11:48:53 +0100239 } else if (block->IsLoopHeader()) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100240 // If the block is a loop header, we know we only have visited the pre header
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100241 // because we are visiting in reverse post order. We create phis for all initialized
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100242 // locals from the pre header. Their inputs will be populated at the end of
243 // the analysis.
Vladimir Marko71bf8092015-09-15 15:33:14 +0100244 for (size_t local = 0; local < current_locals_->size(); ++local) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100245 HInstruction* incoming = ValueOfLocal(block->GetLoopInformation()->GetPreHeader(), local);
246 if (incoming != nullptr) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100247 HPhi* phi = new (GetGraph()->GetArena()) HPhi(
248 GetGraph()->GetArena(), local, 0, Primitive::kPrimVoid);
249 block->AddPhi(phi);
Vladimir Marko71bf8092015-09-15 15:33:14 +0100250 (*current_locals_)[local] = phi;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100251 }
252 }
253 // Save the loop header so that the last phase of the analysis knows which
254 // blocks need to be updated.
Vladimir Marko71bf8092015-09-15 15:33:14 +0100255 loop_headers_.push_back(block);
Vladimir Marko60584552015-09-03 13:35:12 +0000256 } else if (block->GetPredecessors().size() > 0) {
Nicolas Geoffray804d0932014-05-02 08:46:00 +0100257 // All predecessors have already been visited because we are visiting in reverse post order.
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100258 // We merge the values of all locals, creating phis if those values differ.
Vladimir Marko71bf8092015-09-15 15:33:14 +0100259 for (size_t local = 0; local < current_locals_->size(); ++local) {
Nicolas Geoffray7c3560f2014-06-04 12:12:08 +0100260 bool one_predecessor_has_no_value = false;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100261 bool is_different = false;
Vladimir Markoec7802a2015-10-01 20:57:57 +0100262 HInstruction* value = ValueOfLocal(block->GetPredecessors()[0], local);
Nicolas Geoffray7c3560f2014-06-04 12:12:08 +0100263
Vladimir Marko60584552015-09-03 13:35:12 +0000264 for (HBasicBlock* predecessor : block->GetPredecessors()) {
265 HInstruction* current = ValueOfLocal(predecessor, local);
Nicolas Geoffray7c3560f2014-06-04 12:12:08 +0100266 if (current == nullptr) {
Nicolas Geoffrayec7e4722014-06-06 11:24:33 +0100267 one_predecessor_has_no_value = true;
268 break;
Nicolas Geoffray7c3560f2014-06-04 12:12:08 +0100269 } else if (current != value) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100270 is_different = true;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100271 }
272 }
Nicolas Geoffray7c3560f2014-06-04 12:12:08 +0100273
274 if (one_predecessor_has_no_value) {
275 // If one predecessor has no value for this local, we trust the verifier has
276 // successfully checked that there is a store dominating any read after this block.
277 continue;
278 }
279
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100280 if (is_different) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100281 HPhi* phi = new (GetGraph()->GetArena()) HPhi(
Vladimir Marko60584552015-09-03 13:35:12 +0000282 GetGraph()->GetArena(), local, block->GetPredecessors().size(), Primitive::kPrimVoid);
283 for (size_t i = 0; i < block->GetPredecessors().size(); i++) {
Vladimir Markoec7802a2015-10-01 20:57:57 +0100284 HInstruction* pred_value = ValueOfLocal(block->GetPredecessors()[i], local);
Andreas Gampe277ccbd2014-11-03 21:36:10 -0800285 phi->SetRawInputAt(i, pred_value);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100286 }
287 block->AddPhi(phi);
288 value = phi;
289 }
Vladimir Marko71bf8092015-09-15 15:33:14 +0100290 (*current_locals_)[local] = value;
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100291 }
292 }
293
294 // Visit all instructions. The instructions of interest are:
295 // - HLoadLocal: replace them with the current value of the local.
296 // - HStoreLocal: update current value of the local and remove the instruction.
297 // - Instructions that require an environment: populate their environment
298 // with the current values of the locals.
Nicolas Geoffrayf635e632014-05-14 09:43:38 +0100299 for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100300 it.Current()->Accept(this);
301 }
302}
303
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100304/**
305 * Constants in the Dex format are not typed. So the builder types them as
306 * integers, but when doing the SSA form, we might realize the constant
307 * is used for floating point operations. We create a floating-point equivalent
308 * constant to make the operations correctly typed.
309 */
David Brazdil8d5b8b22015-03-24 10:51:52 +0000310HFloatConstant* SsaBuilder::GetFloatEquivalent(HIntConstant* constant) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100311 // We place the floating point constant next to this constant.
312 HFloatConstant* result = constant->GetNext()->AsFloatConstant();
313 if (result == nullptr) {
314 HGraph* graph = constant->GetBlock()->GetGraph();
315 ArenaAllocator* allocator = graph->GetArena();
Roland Levillainda4d79b2015-03-24 14:36:11 +0000316 result = new (allocator) HFloatConstant(bit_cast<float, int32_t>(constant->GetValue()));
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100317 constant->GetBlock()->InsertInstructionBefore(result, constant->GetNext());
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000318 graph->CacheFloatConstant(result);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100319 } else {
320 // If there is already a constant with the expected type, we know it is
321 // the floating point equivalent of this constant.
Roland Levillainda4d79b2015-03-24 14:36:11 +0000322 DCHECK_EQ((bit_cast<int32_t, float>(result->GetValue())), constant->GetValue());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100323 }
324 return result;
325}
326
327/**
328 * Wide constants in the Dex format are not typed. So the builder types them as
329 * longs, but when doing the SSA form, we might realize the constant
330 * is used for floating point operations. We create a floating-point equivalent
331 * constant to make the operations correctly typed.
332 */
David Brazdil8d5b8b22015-03-24 10:51:52 +0000333HDoubleConstant* SsaBuilder::GetDoubleEquivalent(HLongConstant* constant) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100334 // We place the floating point constant next to this constant.
335 HDoubleConstant* result = constant->GetNext()->AsDoubleConstant();
336 if (result == nullptr) {
337 HGraph* graph = constant->GetBlock()->GetGraph();
338 ArenaAllocator* allocator = graph->GetArena();
Roland Levillainda4d79b2015-03-24 14:36:11 +0000339 result = new (allocator) HDoubleConstant(bit_cast<double, int64_t>(constant->GetValue()));
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100340 constant->GetBlock()->InsertInstructionBefore(result, constant->GetNext());
Nicolas Geoffrayf213e052015-04-27 08:53:46 +0000341 graph->CacheDoubleConstant(result);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100342 } else {
343 // If there is already a constant with the expected type, we know it is
344 // the floating point equivalent of this constant.
Roland Levillainda4d79b2015-03-24 14:36:11 +0000345 DCHECK_EQ((bit_cast<int64_t, double>(result->GetValue())), constant->GetValue());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100346 }
347 return result;
348}
349
350/**
351 * Because of Dex format, we might end up having the same phi being
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000352 * used for non floating point operations and floating point / reference operations.
353 * Because we want the graph to be correctly typed (and thereafter avoid moves between
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100354 * floating point registers and core registers), we need to create a copy of the
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000355 * phi with a floating point / reference type.
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100356 */
David Brazdil8d5b8b22015-03-24 10:51:52 +0000357HPhi* SsaBuilder::GetFloatDoubleOrReferenceEquivalentOfPhi(HPhi* phi, Primitive::Type type) {
David Brazdil1749e2c2015-09-28 13:49:59 +0100358 DCHECK(phi->IsLive()) << "Cannot get equivalent of a dead phi since it would create a live one.";
359
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000360 // We place the floating point /reference phi next to this phi.
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100361 HInstruction* next = phi->GetNext();
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000362 if (next != nullptr
363 && next->AsPhi()->GetRegNumber() == phi->GetRegNumber()
364 && next->GetType() != type) {
365 // Move to the next phi to see if it is the one we are looking for.
366 next = next->GetNext();
367 }
368
369 if (next == nullptr
370 || (next->AsPhi()->GetRegNumber() != phi->GetRegNumber())
371 || (next->GetType() != type)) {
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100372 ArenaAllocator* allocator = phi->GetBlock()->GetGraph()->GetArena();
373 HPhi* new_phi = new (allocator) HPhi(allocator, phi->GetRegNumber(), phi->InputCount(), type);
374 for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
David Brazdil1749e2c2015-09-28 13:49:59 +0100375 // Copy the inputs. Note that the graph may not be correctly typed
376 // by doing this copy, but the type propagation phase will fix it.
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100377 new_phi->SetRawInputAt(i, phi->InputAt(i));
378 }
379 phi->GetBlock()->InsertPhiAfter(new_phi, phi);
David Brazdil1749e2c2015-09-28 13:49:59 +0100380 DCHECK(new_phi->IsLive());
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100381 return new_phi;
382 } else {
Nicolas Geoffray21cc7982014-11-17 17:50:33 +0000383 DCHECK_EQ(next->GetType(), type);
David Brazdil1749e2c2015-09-28 13:49:59 +0100384 // An existing equivalent was found. If it is dead, conflict was previously
385 // identified and we return nullptr instead.
386 return next->AsPhi()->IsLive() ? next->AsPhi() : nullptr;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100387 }
388}
389
390HInstruction* SsaBuilder::GetFloatOrDoubleEquivalent(HInstruction* user,
391 HInstruction* value,
392 Primitive::Type type) {
393 if (value->IsArrayGet()) {
David Brazdil1749e2c2015-09-28 13:49:59 +0100394 HArrayGet* aget = value->AsArrayGet();
395 if (aget->GetType() != type && aget->IsTypeFixed()) {
396 // Requested a float/double equivalent of ArrayGet with int/long uses.
397 // Must be a phi with type conflict.
398 DCHECK(user->IsPhi());
399 return nullptr;
400 }
401 aget->SetType(type);
402 return aget;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100403 } else if (value->IsLongConstant()) {
404 return GetDoubleEquivalent(value->AsLongConstant());
405 } else if (value->IsIntConstant()) {
406 return GetFloatEquivalent(value->AsIntConstant());
407 } else if (value->IsPhi()) {
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000408 return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), type);
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100409 } else {
David Brazdil1749e2c2015-09-28 13:49:59 +0100410 return nullptr;
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100411 }
412}
413
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000414HInstruction* SsaBuilder::GetReferenceTypeEquivalent(HInstruction* value) {
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000415 if (value->IsIntConstant() && value->AsIntConstant()->GetValue() == 0) {
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000416 return value->GetBlock()->GetGraph()->GetNullConstant();
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000417 } else if (value->IsPhi()) {
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000418 return GetFloatDoubleOrReferenceEquivalentOfPhi(value->AsPhi(), Primitive::kPrimNot);
Nicolas Geoffraye0fe7ae2015-03-09 10:02:49 +0000419 } else {
420 return nullptr;
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000421 }
422}
423
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100424void SsaBuilder::VisitLoadLocal(HLoadLocal* load) {
Vladimir Marko71bf8092015-09-15 15:33:14 +0100425 HInstruction* value = (*current_locals_)[load->GetLocal()->GetRegNumber()];
Nicolas Geoffrayd6138ef2015-02-18 14:48:53 +0000426 // If the operation requests a specific type, we make sure its input is of that type.
427 if (load->GetType() != value->GetType()) {
428 if (load->GetType() == Primitive::kPrimFloat || load->GetType() == Primitive::kPrimDouble) {
429 value = GetFloatOrDoubleEquivalent(load, value, load->GetType());
430 } else if (load->GetType() == Primitive::kPrimNot) {
431 value = GetReferenceTypeEquivalent(value);
432 }
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100433 }
David Brazdil1749e2c2015-09-28 13:49:59 +0100434
435 // If value is HArrayGet, check if uses of the HLoadLocal disambiguate its
436 // type between int/long and float/double.
437 if (value->IsArrayGet() && !value->AsArrayGet()->IsTypeFixed()) {
438 for (HUseIterator<HInstruction*> use_it(load->GetUses()); !use_it.Done(); use_it.Advance()) {
439 HInstruction* user = use_it.Current()->GetUser();
440 if (!user->IsStoreLocal() &&
441 !user->IsPhi() &&
442 (!user->IsArraySet() || user->AsArraySet()->GetIndex() == value)) {
443 value->AsArrayGet()->FixType();
444 break;
445 }
446 }
447 }
448
Nicolas Geoffray102cbed2014-10-15 18:31:05 +0100449 load->ReplaceWith(value);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100450 load->GetBlock()->RemoveInstruction(load);
451}
452
453void SsaBuilder::VisitStoreLocal(HStoreLocal* store) {
Vladimir Marko71bf8092015-09-15 15:33:14 +0100454 (*current_locals_)[store->GetLocal()->GetRegNumber()] = store->InputAt(1);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100455 store->GetBlock()->RemoveInstruction(store);
456}
457
458void SsaBuilder::VisitInstruction(HInstruction* instruction) {
David Brazdilffee3d32015-07-06 11:48:53 +0100459 if (instruction->NeedsEnvironment()) {
460 HEnvironment* environment = new (GetGraph()->GetArena()) HEnvironment(
461 GetGraph()->GetArena(),
Vladimir Marko71bf8092015-09-15 15:33:14 +0100462 current_locals_->size(),
David Brazdilffee3d32015-07-06 11:48:53 +0100463 GetGraph()->GetDexFile(),
464 GetGraph()->GetMethodIdx(),
465 instruction->GetDexPc(),
466 GetGraph()->GetInvokeType(),
467 instruction);
468 environment->CopyFrom(*current_locals_);
469 instruction->SetRawEnvironment(environment);
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100470 }
David Brazdilffee3d32015-07-06 11:48:53 +0100471
472 // If in a try block, propagate values of locals into catch blocks.
David Brazdilec16f792015-08-19 15:04:01 +0100473 if (instruction->CanThrowIntoCatchBlock()) {
474 const HTryBoundary& try_entry =
475 instruction->GetBlock()->GetTryCatchInformation()->GetTryEntry();
476 for (HExceptionHandlerIterator it(try_entry); !it.Done(); it.Advance()) {
David Brazdil3eaa32f2015-09-18 10:58:32 +0100477 HBasicBlock* catch_block = it.Current();
478 ArenaVector<HInstruction*>* handler_locals = GetLocalsFor(catch_block);
Vladimir Marko71bf8092015-09-15 15:33:14 +0100479 DCHECK_EQ(handler_locals->size(), current_locals_->size());
David Brazdil3eaa32f2015-09-18 10:58:32 +0100480 for (size_t vreg = 0, e = current_locals_->size(); vreg < e; ++vreg) {
481 HInstruction* handler_value = (*handler_locals)[vreg];
482 if (handler_value == nullptr) {
483 // Vreg was undefined at a previously encountered throwing instruction
484 // and the catch phi was deleted. Do not record the local value.
485 continue;
486 }
487 DCHECK(handler_value->IsPhi());
488
489 HInstruction* local_value = (*current_locals_)[vreg];
490 if (local_value == nullptr) {
491 // This is the first instruction throwing into `catch_block` where
492 // `vreg` is undefined. Delete the catch phi.
493 catch_block->RemovePhi(handler_value->AsPhi());
494 (*handler_locals)[vreg] = nullptr;
495 } else {
496 // Vreg has been defined at all instructions throwing into `catch_block`
497 // encountered so far. Record the local value in the catch phi.
498 handler_value->AsPhi()->AddInput(local_value);
David Brazdilffee3d32015-07-06 11:48:53 +0100499 }
500 }
501 }
502 }
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100503}
504
Nicolas Geoffray421e9f92014-11-11 18:21:53 +0000505void SsaBuilder::VisitTemporary(HTemporary* temp) {
506 // Temporaries are only used by the baseline register allocator.
507 temp->GetBlock()->RemoveInstruction(temp);
508}
509
Nicolas Geoffrayc32e7702014-04-24 12:43:16 +0100510} // namespace art