Refactor handling of input records.
Introduce HInstruction::GetInputRecords(), a new virtual
function that returns an ArrayRef<> to all input records.
Implement all other functions dealing with input records as
wrappers around GetInputRecords(). Rewrite functions that
previously used multiple virtual calls to deal with input
records, especially in loops, to prefetch the ArrayRef<>
only once for each instruction. Besides avoiding all the
extra calls, this also allows the compiler (clang++) to
perform additional optimizations.
This speeds up the Nexus 5 boot image compilation by ~0.5s
(4% of "Compile Dex File", 2% of dex2oat time) on AOSP ToT.
Change-Id: Id8ebe0fb9405e38d918972a11bd724146e4ca578
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index f96ca32..ed50c69 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -123,8 +123,7 @@
static bool TypePhiFromInputs(HPhi* phi) {
Primitive::Type common_type = phi->GetType();
- for (HInputIterator it(phi); !it.Done(); it.Advance()) {
- HInstruction* input = it.Current();
+ for (HInstruction* input : phi->GetInputs()) {
if (input->IsPhi() && input->AsPhi()->IsDead()) {
// Phis are constructed live so if an input is a dead phi, it must have
// been made dead due to type conflict. Mark this phi conflicting too.
@@ -169,8 +168,7 @@
// or `common_type` is integral and we do not need to retype ambiguous inputs
// because they are always constructed with the integral type candidate.
if (kIsDebugBuild) {
- for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
- HInstruction* input = phi->InputAt(i);
+ for (HInstruction* input : phi->GetInputs()) {
if (common_type == Primitive::kPrimVoid) {
DCHECK(input->IsPhi() && input->GetType() == Primitive::kPrimVoid);
} else {
@@ -183,8 +181,9 @@
return true;
} else {
DCHECK(common_type == Primitive::kPrimNot || Primitive::IsFloatingPointType(common_type));
- for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
- HInstruction* input = phi->InputAt(i);
+ auto&& inputs = phi->GetInputs();
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ HInstruction* input = inputs[i];
if (input->GetType() != common_type) {
// Input type does not match phi's type. Try to retype the input or
// generate a suitably typed equivalent.
@@ -618,11 +617,14 @@
|| (next->AsPhi()->GetRegNumber() != phi->GetRegNumber())
|| (next->GetType() != type)) {
ArenaAllocator* allocator = graph_->GetArena();
- HPhi* new_phi = new (allocator) HPhi(allocator, phi->GetRegNumber(), phi->InputCount(), type);
- for (size_t i = 0, e = phi->InputCount(); i < e; ++i) {
- // Copy the inputs. Note that the graph may not be correctly typed
- // by doing this copy, but the type propagation phase will fix it.
- new_phi->SetRawInputAt(i, phi->InputAt(i));
+ auto&& inputs = phi->GetInputs();
+ HPhi* new_phi =
+ new (allocator) HPhi(allocator, phi->GetRegNumber(), inputs.size(), type);
+ // Copy the inputs. Note that the graph may not be correctly typed
+ // by doing this copy, but the type propagation phase will fix it.
+ ArrayRef<HUserRecord<HInstruction*>> new_input_records = new_phi->GetInputRecords();
+ for (size_t i = 0; i < inputs.size(); ++i) {
+ new_input_records[i] = HUserRecord<HInstruction*>(inputs[i]);
}
phi->GetBlock()->InsertPhiAfter(new_phi, phi);
DCHECK(new_phi->IsLive());