[vm, compiler] Allocate only one SSA index to definitions, even those with pair representation.

Change the mapping between SSA indices and virtual registers from 1:1 to 1:2.

This shrinks the size of bit vectors used during optimizations, and leaves the size of bit vectors used during register allocation the same.

TEST=ci
Change-Id: I0c82ca7972f7efb30559f7e4869396f1eed757c5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/250982
Reviewed-by: Slava Egorov <vegorov@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
Ryan Macnak 2022-07-13 23:27:33 +00:00 committed by Commit Bot
parent 05e5664ad6
commit c2058b0f40
14 changed files with 151 additions and 216 deletions

View file

@ -126,10 +126,7 @@ bool AotCallSpecializer::TryCreateICDataForUniqueTarget(
const intptr_t receiver_index = call->FirstArgIndex();
RedefinitionInstr* redefinition = new (Z)
RedefinitionInstr(new (Z) Value(call->ArgumentAt(receiver_index)));
redefinition->set_ssa_temp_index(flow_graph()->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(redefinition->representation())) {
flow_graph()->alloc_ssa_temp_index();
}
flow_graph()->AllocateSSAIndex(redefinition);
redefinition->InsertAfter(call);
// Replace all uses of the receiver dominated by this call.
FlowGraph::RenameDominatedUses(call->ArgumentAt(receiver_index),

View file

@ -31,10 +31,7 @@ class BlockBuilder : public ValueObject {
}
Definition* AddToInitialDefinitions(Definition* def) {
def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(def->representation())) {
flow_graph_->alloc_ssa_temp_index();
}
flow_graph_->AllocateSSAIndex(def);
auto normal_entry = flow_graph_->graph_entry()->normal_entry();
flow_graph_->AddToInitialDefinitions(normal_entry, def);
return def;
@ -42,7 +39,7 @@ class BlockBuilder : public ValueObject {
template <typename T>
T* AddDefinition(T* def) {
flow_graph_->AllocateSSAIndexes(def);
flow_graph_->AllocateSSAIndex(def);
AddInstruction(def);
return def;
}
@ -134,10 +131,7 @@ class BlockBuilder : public ValueObject {
}
void AddPhi(PhiInstr* phi) {
phi->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(phi->representation())) {
flow_graph_->alloc_ssa_temp_index();
}
flow_graph_->AllocateSSAIndex(phi);
phi->mark_alive();
entry_->AsJoinEntry()->InsertPhi(phi);
}

View file

@ -35,9 +35,8 @@ ConstantPropagator::ConstantPropagator(
unknown_(Object::unknown_constant()),
non_constant_(Object::non_constant()),
constant_value_(Object::Handle(Z)),
reachable_(new (Z) BitVector(Z, graph->preorder().length())),
unwrapped_phis_(new (Z)
BitVector(Z, graph->max_virtual_register_number())),
reachable_(new(Z) BitVector(Z, graph->preorder().length())),
unwrapped_phis_(new(Z) BitVector(Z, graph->current_ssa_temp_index())),
block_worklist_(),
definition_worklist_(graph, 10) {}

View file

@ -67,7 +67,7 @@ FlowGraph::FlowGraph(const ParsedFunction& parsed_function,
void FlowGraph::EnsureSSATempIndex(Definition* defn, Definition* replacement) {
if ((replacement->ssa_temp_index() == -1) && (defn->ssa_temp_index() != -1)) {
AllocateSSAIndexes(replacement);
AllocateSSAIndex(replacement);
}
}
@ -191,10 +191,7 @@ ConstantInstr* FlowGraph::GetConstant(const Object& object,
} else {
constant = new (zone()) UnboxedConstantInstr(zone_object, representation);
}
constant->set_ssa_temp_index(alloc_ssa_temp_index());
if (NeedsPairLocation(constant->representation())) {
alloc_ssa_temp_index();
}
AllocateSSAIndex(constant);
AddToGraphInitialDefinitions(constant);
constant_instr_pool_.Insert(constant);
}
@ -271,7 +268,7 @@ void FlowGraph::InsertAfter(Instruction* prev,
UseKind use_kind) {
if (use_kind == kValue) {
ASSERT(instr->IsDefinition());
AllocateSSAIndexes(instr->AsDefinition());
AllocateSSAIndex(instr->AsDefinition());
}
instr->InsertAfter(prev);
ASSERT(instr->env() == NULL);
@ -296,7 +293,7 @@ Instruction* FlowGraph::AppendTo(Instruction* prev,
UseKind use_kind) {
if (use_kind == kValue) {
ASSERT(instr->IsDefinition());
AllocateSSAIndexes(instr->AsDefinition());
AllocateSSAIndex(instr->AsDefinition());
}
ASSERT(instr->env() == NULL);
if (env != NULL) {
@ -1215,8 +1212,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
new (zone()) ParameterInstr(i, param_offset, function_entry, kTagged);
param_offset++;
}
param->set_ssa_temp_index(alloc_ssa_temp_index());
if (NeedsPairLocation(param->representation())) alloc_ssa_temp_index();
AllocateSSAIndex(param);
AddToInitialDefinitions(function_entry, param);
(*env)[i] = param;
}
@ -1228,7 +1224,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
if (inlining_parameters != NULL) {
for (intptr_t i = 0; i < function().NumParameters(); ++i) {
Definition* defn = (*inlining_parameters)[inlined_type_args_param + i];
AllocateSSAIndexes(defn);
AllocateSSAIndex(defn);
AddToInitialDefinitions(function_entry, defn);
intptr_t index = EnvIndex(parsed_function_.RawParameterVariable(i));
@ -1250,7 +1246,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
} else {
defn = (*inlining_parameters)[0];
}
AllocateSSAIndexes(defn);
AllocateSSAIndex(defn);
AddToInitialDefinitions(function_entry, defn);
(*env)[RawTypeArgumentEnvIndex()] = defn;
}
@ -1260,7 +1256,7 @@ void FlowGraph::PopulateEnvironmentFromFunctionEntry(
Definition* defn =
new (Z) SpecialParameterInstr(SpecialParameterInstr::kArgDescriptor,
DeoptId::kNone, function_entry);
AllocateSSAIndexes(defn);
AllocateSSAIndex(defn);
AddToInitialDefinitions(function_entry, defn);
(*env)[ArgumentDescriptorEnvIndex()] = defn;
}
@ -1279,7 +1275,7 @@ void FlowGraph::PopulateEnvironmentFromOsrEntry(
for (intptr_t i = 0; i < parameter_count; i++) {
ParameterInstr* param =
new (zone()) ParameterInstr(i, i, osr_entry, kTagged);
param->set_ssa_temp_index(alloc_ssa_temp_index());
AllocateSSAIndex(param);
AddToInitialDefinitions(osr_entry, param);
(*env)[i] = param;
}
@ -1313,7 +1309,7 @@ void FlowGraph::PopulateEnvironmentFromCatchEntry(
param = new (Z) ParameterInstr(i, i, catch_entry, kTagged);
}
param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
AllocateSSAIndex(param); // New SSA temp.
(*env)[i] = param;
AddToInitialDefinitions(catch_entry, param);
}
@ -1346,7 +1342,7 @@ void FlowGraph::RenameRecursive(
PhiInstr* phi = (*join->phis())[i];
if (phi != nullptr) {
(*env)[i] = phi;
AllocateSSAIndexes(phi); // New SSA temp.
AllocateSSAIndex(phi); // New SSA temp.
if (block_entry->InsideTryBlock() && !phi->is_alive()) {
// This is a safe approximation. Inside try{} all locals are
// used at every call implicitly, so we mark all phis as live
@ -1549,7 +1545,7 @@ void FlowGraph::RenameRecursive(
if (Definition* definition = current->AsDefinition()) {
if (definition->HasTemp()) {
// Assign fresh SSA temporary and update expression stack.
AllocateSSAIndexes(definition);
AllocateSSAIndex(definition);
env->Add(definition);
}
}
@ -2573,7 +2569,7 @@ void FlowGraph::RenameUsesDominatedByRedefinitions() {
Value* redefined = definition->RedefinedValue();
if (redefined != nullptr) {
if (!definition->HasSSATemp()) {
AllocateSSAIndexes(definition);
AllocateSSAIndex(definition);
}
Definition* original = redefined->definition();
RenameDominatedUses(original, definition, definition);
@ -2821,7 +2817,7 @@ JoinEntryInstr* FlowGraph::NewDiamond(Instruction* instruction,
// Short-circuit second comparison and connect through phi.
condition.oper2->InsertAfter(bt);
AllocateSSAIndexes(condition.oper2);
AllocateSSAIndex(condition.oper2);
condition.oper2->InheritDeoptTarget(zone(), inherit); // must inherit
PhiInstr* phi =
AddPhi(mid_point, condition.oper2, GetConstant(Bool::False()));
@ -2841,7 +2837,7 @@ PhiInstr* FlowGraph::AddPhi(JoinEntryInstr* join,
Value* v1 = new (zone()) Value(d1);
Value* v2 = new (zone()) Value(d2);
AllocateSSAIndexes(phi);
AllocateSSAIndex(phi);
phi->mark_alive();
phi->SetInputAt(0, v1);

View file

@ -200,11 +200,6 @@ class FlowGraph : public ZoneAllocated {
env_index == SuspendStateEnvIndex());
}
static bool NeedsPairLocation(Representation representation) {
return representation == kUnboxedInt64 &&
compiler::target::kIntSpillFactor == 2;
}
// Flow graph orders.
const GrowableArray<BlockEntryInstr*>& preorder() const { return preorder_; }
const GrowableArray<BlockEntryInstr*>& postorder() const {
@ -246,8 +241,8 @@ class FlowGraph : public ZoneAllocated {
current_ssa_temp_index_ = index;
}
intptr_t max_virtual_register_number() const {
return current_ssa_temp_index();
intptr_t max_vreg() const {
return current_ssa_temp_index() * kMaxLocationCount;
}
enum class ToCheck { kNoCheck, kCheckNull, kCheckCid };
@ -272,14 +267,9 @@ class FlowGraph : public ZoneAllocated {
ConstantInstr* constant_dead() const { return constant_dead_; }
intptr_t alloc_ssa_temp_index() { return current_ssa_temp_index_++; }
void AllocateSSAIndexes(Definition* def) {
ASSERT(def);
def->set_ssa_temp_index(alloc_ssa_temp_index());
// Always allocate a second index. This index is unused except
// for Definitions with register pair outputs.
alloc_ssa_temp_index();
void AllocateSSAIndex(Definition* def) {
def->set_ssa_temp_index(current_ssa_temp_index_);
current_ssa_temp_index_++;
}
intptr_t InstructionCount() const;

View file

@ -2321,14 +2321,14 @@ class Definition : public Instruction {
}
bool HasSSATemp() const { return ssa_temp_index_ >= 0; }
void ClearSSATempIndex() { ssa_temp_index_ = -1; }
bool HasPairRepresentation() const {
if (compiler::target::kWordSize == 8) {
return representation() == kPairOfTagged;
} else {
return (representation() == kPairOfTagged) ||
(representation() == kUnboxedInt64);
}
intptr_t vreg(intptr_t index) const {
ASSERT((index >= 0) && (index < location_count()));
if (ssa_temp_index_ == -1) return -1;
return ssa_temp_index_ * kMaxLocationCount + index;
}
intptr_t location_count() const { return LocationCount(representation()); }
bool HasPairRepresentation() const { return location_count() == 2; }
// Compile time type of the definition, which may be requested before type
// propagation during graph building.

View file

@ -439,12 +439,7 @@ void FlowGraphPrinter::PrintCidRangeData(const CallTargets& targets,
static void PrintUse(BaseTextBuffer* f, const Definition& definition) {
if (definition.HasSSATemp()) {
if (definition.HasPairRepresentation()) {
f->Printf("(v%" Pd ", v%" Pd ")", definition.ssa_temp_index(),
definition.ssa_temp_index() + 1);
} else {
f->Printf("v%" Pd "", definition.ssa_temp_index());
}
f->Printf("v%" Pd "", definition.ssa_temp_index());
} else if (definition.HasTemp()) {
f->Printf("t%" Pd "", definition.temp_index());
}
@ -1142,12 +1137,7 @@ const char* RepresentationToCString(Representation rep) {
}
void PhiInstr::PrintTo(BaseTextBuffer* f) const {
if (HasPairRepresentation()) {
f->Printf("(v%" Pd ", v%" Pd ") <- phi(", ssa_temp_index(),
ssa_temp_index() + 1);
} else {
f->Printf("v%" Pd " <- phi(", ssa_temp_index());
}
f->Printf("v%" Pd " <- phi(", ssa_temp_index());
for (intptr_t i = 0; i < inputs_.length(); ++i) {
if (inputs_[i] != NULL) inputs_[i]->PrintTo(f);
if (i < inputs_.length() - 1) f->AddString(", ");

View file

@ -782,10 +782,7 @@ static void ReplaceParameterStubs(Zone* zone,
callee_signature, first_arg_index, i)) {
RedefinitionInstr* redefinition =
new (zone) RedefinitionInstr(actual->Copy(zone));
redefinition->set_ssa_temp_index(caller_graph->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(redefinition->representation())) {
caller_graph->alloc_ssa_temp_index();
}
caller_graph->AllocateSSAIndex(redefinition);
if (is_polymorphic_receiver && target_info->IsSingleCid()) {
redefinition->UpdateType(CompileType::FromCid(target_info->cid_start));
}
@ -831,11 +828,7 @@ static void ReplaceParameterStubs(Zone* zone,
LoadFieldInstr* context_load = new (zone) LoadFieldInstr(
new Value((*arguments)[first_arg_index]->definition()),
Slot::Closure_context(), call_data->call->source());
context_load->set_ssa_temp_index(
caller_graph->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(context_load->representation())) {
caller_graph->alloc_ssa_temp_index();
}
caller_graph->AllocateSSAIndex(context_load);
context_load->InsertBefore(callee_entry->next());
param->ReplaceUsesWith(context_load);
break;
@ -1290,7 +1283,7 @@ class CallSiteInliner : public ValueObject {
{
// Compute SSA on the callee graph, catching bailouts.
COMPILER_TIMINGS_TIMER_SCOPE(thread(), ComputeSSA);
callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
callee_graph->ComputeSSA(caller_graph_->current_ssa_temp_index(),
param_stubs);
#if defined(DEBUG)
// The inlining IDs of instructions in the callee graph are unset
@ -1977,11 +1970,7 @@ bool PolymorphicInliner::TryInlineRecognizedMethod(intptr_t receiver_cid,
Definition* receiver = call_->Receiver()->definition();
RedefinitionInstr* redefinition =
new (Z) RedefinitionInstr(new (Z) Value(receiver));
redefinition->set_ssa_temp_index(
owner_->caller_graph()->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(redefinition->representation())) {
owner_->caller_graph()->alloc_ssa_temp_index();
}
owner_->caller_graph()->AllocateSSAIndex(redefinition);
if (FlowGraphInliner::TryInlineRecognizedMethod(
owner_->caller_graph(), receiver_cid, target, call_, redefinition,
call_->source(), call_->ic_data(), graph_entry, &entry, &last,
@ -2038,7 +2027,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
// at least one branch on the class id.
LoadClassIdInstr* load_cid =
new (Z) LoadClassIdInstr(new (Z) Value(receiver));
load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index());
owner_->caller_graph()->AllocateSSAIndex(load_cid);
cursor = AppendInstruction(cursor, load_cid);
for (intptr_t i = 0; i < inlined_variants_.length(); ++i) {
const CidRange& variant = inlined_variants_[i];
@ -2054,8 +2043,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
if (!call_->complete()) {
RedefinitionInstr* cid_redefinition =
new RedefinitionInstr(new (Z) Value(load_cid));
cid_redefinition->set_ssa_temp_index(
owner_->caller_graph()->alloc_ssa_temp_index());
owner_->caller_graph()->AllocateSSAIndex(cid_redefinition);
cursor = AppendInstruction(cursor, cid_redefinition);
CheckClassIdInstr* check_class_id = new (Z) CheckClassIdInstr(
new (Z) Value(cid_redefinition), variant, call_->deopt_id());
@ -2242,11 +2230,7 @@ TargetEntryInstr* PolymorphicInliner::BuildDecisionGraph() {
PolymorphicInstanceCallInstr* fallback_call =
PolymorphicInstanceCallInstr::FromCall(Z, call_, *non_inlined_variants_,
call_->complete());
fallback_call->set_ssa_temp_index(
owner_->caller_graph()->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(fallback_call->representation())) {
owner_->caller_graph()->alloc_ssa_temp_index();
}
owner_->caller_graph()->AllocateSSAIndex(fallback_call);
fallback_call->InheritDeoptTarget(zone(), call_);
fallback_call->set_total_call_count(call_->CallCount());
ReturnInstr* fallback_return = new ReturnInstr(

View file

@ -33,19 +33,6 @@ static const intptr_t kNoVirtualRegister = -1;
static const intptr_t kTempVirtualRegister = -2;
static const intptr_t kIllegalPosition = -1;
static const intptr_t kMaxPosition = 0x7FFFFFFF;
static const intptr_t kPairVirtualRegisterOffset = 1;
// Definitions which have pair representations
// (kPairOfTagged) use two virtual register names.
// At SSA index allocation time each definition reserves two SSA indexes,
// the second index is only used for pairs. This function maps from the first
// SSA index to the second.
static intptr_t ToSecondPairVreg(intptr_t vreg) {
// Map vreg to its pair vreg.
ASSERT((vreg == kNoVirtualRegister) || vreg >= 0);
return (vreg == kNoVirtualRegister) ? kNoVirtualRegister
: (vreg + kPairVirtualRegisterOffset);
}
static intptr_t MinPosition(intptr_t a, intptr_t b) {
return (a < b) ? a : b;
@ -93,15 +80,15 @@ FlowGraphAllocator::FlowGraphAllocator(const FlowGraph& flow_graph,
bool intrinsic_mode)
: flow_graph_(flow_graph),
reaching_defs_(flow_graph),
value_representations_(flow_graph.max_virtual_register_number()),
value_representations_(flow_graph.max_vreg()),
block_order_(flow_graph.reverse_postorder()),
postorder_(flow_graph.postorder()),
instructions_(),
block_entries_(),
extra_loop_info_(),
liveness_(flow_graph),
vreg_count_(flow_graph.max_virtual_register_number()),
live_ranges_(flow_graph.max_virtual_register_number()),
vreg_count_(flow_graph.max_vreg()),
live_ranges_(flow_graph.max_vreg()),
unallocated_cpu_(),
unallocated_fpu_(),
cpu_regs_(),
@ -165,7 +152,7 @@ static void DeepLiveness(MaterializeObjectInstr* mat, BitVector* live_in) {
if (inner_mat != NULL) {
DeepLiveness(inner_mat, live_in);
} else {
intptr_t idx = defn->ssa_temp_index();
intptr_t idx = defn->vreg(0);
live_in->Add(idx);
}
}
@ -195,11 +182,11 @@ void SSALivenessAnalysis::ComputeInitialSets() {
// Handle definitions.
Definition* current_def = current->AsDefinition();
if ((current_def != NULL) && current_def->HasSSATemp()) {
kill->Add(current_def->ssa_temp_index());
live_in->Remove(current_def->ssa_temp_index());
kill->Add(current_def->vreg(0));
live_in->Remove(current_def->vreg(0));
if (current_def->HasPairRepresentation()) {
kill->Add(ToSecondPairVreg(current_def->ssa_temp_index()));
live_in->Remove(ToSecondPairVreg(current_def->ssa_temp_index()));
kill->Add(current_def->vreg(1));
live_in->Remove(current_def->vreg(1));
}
}
@ -211,9 +198,9 @@ void SSALivenessAnalysis::ComputeInitialSets() {
ASSERT(!locs->in(j).IsConstant() || input->BindsToConstant());
if (locs->in(j).IsConstant()) continue;
live_in->Add(input->definition()->ssa_temp_index());
live_in->Add(input->definition()->vreg(0));
if (input->definition()->HasPairRepresentation()) {
live_in->Add(ToSecondPairVreg(input->definition()->ssa_temp_index()));
live_in->Add(input->definition()->vreg(1));
}
}
@ -228,9 +215,9 @@ void SSALivenessAnalysis::ComputeInitialSets() {
// Treat its inputs as part of the environment.
DeepLiveness(defn->AsMaterializeObject(), live_in);
} else if (!defn->IsPushArgument() && !defn->IsConstant()) {
live_in->Add(defn->ssa_temp_index());
live_in->Add(defn->vreg(0));
if (defn->HasPairRepresentation()) {
live_in->Add(ToSecondPairVreg(defn->ssa_temp_index()));
live_in->Add(defn->vreg(1));
}
}
}
@ -243,11 +230,11 @@ void SSALivenessAnalysis::ComputeInitialSets() {
for (PhiIterator it(join); !it.Done(); it.Advance()) {
PhiInstr* phi = it.Current();
ASSERT(phi != NULL);
kill->Add(phi->ssa_temp_index());
live_in->Remove(phi->ssa_temp_index());
kill->Add(phi->vreg(0));
live_in->Remove(phi->vreg(0));
if (phi->HasPairRepresentation()) {
kill->Add(ToSecondPairVreg(phi->ssa_temp_index()));
live_in->Remove(ToSecondPairVreg(phi->ssa_temp_index()));
kill->Add(phi->vreg(1));
live_in->Remove(phi->vreg(1));
}
// If a phi input is not defined by the corresponding predecessor it
@ -257,12 +244,12 @@ void SSALivenessAnalysis::ComputeInitialSets() {
if (val->BindsToConstant()) continue;
BlockEntryInstr* pred = block->PredecessorAt(k);
const intptr_t use = val->definition()->ssa_temp_index();
const intptr_t use = val->definition()->vreg(0);
if (!kill_[pred->postorder_number()]->Contains(use)) {
live_in_[pred->postorder_number()]->Add(use);
}
if (phi->HasPairRepresentation()) {
const intptr_t second_use = ToSecondPairVreg(use);
const intptr_t second_use = val->definition()->vreg(1);
if (!kill_[pred->postorder_number()]->Contains(second_use)) {
live_in_[pred->postorder_number()]->Add(second_use);
}
@ -273,12 +260,12 @@ void SSALivenessAnalysis::ComputeInitialSets() {
// Process initial definitions, i.e. parameters and special parameters.
for (intptr_t i = 0; i < entry->initial_definitions()->length(); i++) {
Definition* def = (*entry->initial_definitions())[i];
const intptr_t vreg = def->ssa_temp_index();
const intptr_t vreg = def->vreg(0);
kill_[entry->postorder_number()]->Add(vreg);
live_in_[entry->postorder_number()]->Remove(vreg);
if (def->HasPairRepresentation()) {
kill_[entry->postorder_number()]->Add(ToSecondPairVreg((vreg)));
live_in_[entry->postorder_number()]->Remove(ToSecondPairVreg(vreg));
kill_[entry->postorder_number()]->Add(def->vreg(1));
live_in_[entry->postorder_number()]->Remove(def->vreg(1));
}
}
}
@ -598,8 +585,8 @@ void FlowGraphAllocator::BuildLiveRanges() {
} else {
// All values flowing into the loop header are live at the
// back edge and can interfere with phi moves.
current_interference_set = new (zone)
BitVector(zone, flow_graph_.max_virtual_register_number());
current_interference_set =
new (zone) BitVector(zone, flow_graph_.max_vreg());
current_interference_set->AddAll(
liveness_.GetLiveInSet(loop_info->header()));
extra_loop_info_[loop_info->id()]->backedge_interference =
@ -643,7 +630,7 @@ void FlowGraphAllocator::BuildLiveRanges() {
for (intptr_t i = 0; i < catch_entry->initial_definitions()->length();
i++) {
Definition* defn = (*catch_entry->initial_definitions())[i];
LiveRange* range = GetLiveRange(defn->ssa_temp_index());
LiveRange* range = GetLiveRange(defn->vreg(0));
range->DefineAt(catch_entry->start_pos()); // Defined at block entry.
ProcessInitialDefinition(defn, range, catch_entry, i);
}
@ -654,14 +641,13 @@ void FlowGraphAllocator::BuildLiveRanges() {
Definition* defn = initial_definitions[i];
if (defn->HasPairRepresentation()) {
// The lower bits are pushed after the higher bits
LiveRange* range =
GetLiveRange(ToSecondPairVreg(defn->ssa_temp_index()));
LiveRange* range = GetLiveRange(defn->vreg(1));
range->AddUseInterval(entry->start_pos(), entry->start_pos() + 2);
range->DefineAt(entry->start_pos());
ProcessInitialDefinition(defn, range, entry, i,
/*second_location_for_definition=*/true);
}
LiveRange* range = GetLiveRange(defn->ssa_temp_index());
LiveRange* range = GetLiveRange(defn->vreg(0));
range->AddUseInterval(entry->start_pos(), entry->start_pos() + 2);
range->DefineAt(entry->start_pos());
ProcessInitialDefinition(defn, range, entry, i);
@ -676,13 +662,13 @@ void FlowGraphAllocator::BuildLiveRanges() {
Definition* defn = (*graph_entry->initial_definitions())[i];
if (defn->HasPairRepresentation()) {
// The lower bits are pushed after the higher bits
LiveRange* range = GetLiveRange(ToSecondPairVreg(defn->ssa_temp_index()));
LiveRange* range = GetLiveRange(defn->vreg(1));
range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
range->DefineAt(graph_entry->start_pos());
ProcessInitialDefinition(defn, range, graph_entry, i,
/*second_location_for_definition=*/true);
}
LiveRange* range = GetLiveRange(defn->ssa_temp_index());
LiveRange* range = GetLiveRange(defn->vreg(0));
range->AddUseInterval(graph_entry->start_pos(), graph_entry->end_pos());
range->DefineAt(graph_entry->start_pos());
ProcessInitialDefinition(defn, range, graph_entry, i);
@ -920,27 +906,25 @@ Instruction* FlowGraphAllocator::ConnectOutgoingPhiMoves(
// g g'
// value --*
//
intptr_t vreg = val->definition()->ssa_temp_index();
intptr_t vreg = val->definition()->vreg(0);
LiveRange* range = GetLiveRange(vreg);
if (interfere_at_backedge != NULL) interfere_at_backedge->Add(vreg);
range->AddUseInterval(block->start_pos(), pos);
range->AddHintedUse(
pos, move->src_slot(),
GetLiveRange(phi->ssa_temp_index())->assigned_location_slot());
range->AddHintedUse(pos, move->src_slot(),
GetLiveRange(phi->vreg(0))->assigned_location_slot());
move->set_src(Location::PrefersRegister());
if (val->definition()->HasPairRepresentation()) {
move = parallel_move->MoveOperandsAt(move_index++);
vreg = ToSecondPairVreg(vreg);
vreg = val->definition()->vreg(1);
range = GetLiveRange(vreg);
if (interfere_at_backedge != NULL) {
interfere_at_backedge->Add(vreg);
}
range->AddUseInterval(block->start_pos(), pos);
range->AddHintedUse(pos, move->src_slot(),
GetLiveRange(ToSecondPairVreg(phi->ssa_temp_index()))
->assigned_location_slot());
GetLiveRange(phi->vreg(1))->assigned_location_slot());
move->set_src(Location::PrefersRegister());
}
}
@ -962,7 +946,7 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
for (PhiIterator it(join); !it.Done(); it.Advance()) {
PhiInstr* phi = it.Current();
ASSERT(phi != NULL);
const intptr_t vreg = phi->ssa_temp_index();
const intptr_t vreg = phi->vreg(0);
ASSERT(vreg >= 0);
const bool is_pair_phi = phi->HasPairRepresentation();
@ -976,7 +960,7 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
if (is_loop_header) range->mark_loop_phi();
if (is_pair_phi) {
LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
LiveRange* second_range = GetLiveRange(phi->vreg(1));
second_range->DefineAt(pos); // Shorten live range.
if (is_loop_header) second_range->mark_loop_phi();
}
@ -990,7 +974,7 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
move->set_dest(Location::PrefersRegister());
range->AddUse(pos, move->dest_slot());
if (is_pair_phi) {
LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
LiveRange* second_range = GetLiveRange(phi->vreg(1));
MoveOperands* second_move =
goto_instr->parallel_move()->MoveOperandsAt(move_idx + 1);
second_move->set_dest(Location::PrefersRegister());
@ -1003,7 +987,7 @@ void FlowGraphAllocator::ConnectIncomingPhiMoves(JoinEntryInstr* join) {
AssignSafepoints(phi, range);
CompleteRange(range, phi->RegisterKindForResult());
if (is_pair_phi) {
LiveRange* second_range = GetLiveRange(ToSecondPairVreg(vreg));
LiveRange* second_range = GetLiveRange(phi->vreg(1));
AssignSafepoints(phi, second_range);
CompleteRange(second_range, phi->RegisterKindForResult());
}
@ -1059,7 +1043,7 @@ void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
// they are still used when resolving control flow.
ASSERT(def->IsParameter() || def->IsPhi());
ASSERT(!def->HasPairRepresentation());
LiveRange* range = GetLiveRange(def->ssa_temp_index());
LiveRange* range = GetLiveRange(def->vreg(0));
range->AddUseInterval(block_start_pos, use_pos);
}
continue;
@ -1089,19 +1073,18 @@ void FlowGraphAllocator::ProcessEnvironmentUses(BlockEntryInstr* block,
PairLocation* location_pair = locations[i].AsPairLocation();
{
// First live range.
LiveRange* range = GetLiveRange(def->ssa_temp_index());
LiveRange* range = GetLiveRange(def->vreg(0));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, location_pair->SlotAt(0));
}
{
// Second live range.
LiveRange* range =
GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
LiveRange* range = GetLiveRange(def->vreg(1));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, location_pair->SlotAt(1));
}
} else {
LiveRange* range = GetLiveRange(def->ssa_temp_index());
LiveRange* range = GetLiveRange(def->vreg(0));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, &locations[i]);
}
@ -1141,14 +1124,13 @@ void FlowGraphAllocator::ProcessMaterializationUses(
PairLocation* location_pair = locations[i].AsPairLocation();
{
// First live range.
LiveRange* range = GetLiveRange(def->ssa_temp_index());
LiveRange* range = GetLiveRange(def->vreg(0));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, location_pair->SlotAt(0));
}
{
// Second live range.
LiveRange* range =
GetLiveRange(ToSecondPairVreg(def->ssa_temp_index()));
LiveRange* range = GetLiveRange(def->vreg(1));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, location_pair->SlotAt(1));
}
@ -1158,7 +1140,7 @@ void FlowGraphAllocator::ProcessMaterializationUses(
def->AsMaterializeObject());
} else {
locations[i] = Location::Any();
LiveRange* range = GetLiveRange(def->ssa_temp_index());
LiveRange* range = GetLiveRange(def->vreg(0));
range->AddUseInterval(block_start_pos, use_pos);
range->AddUse(use_pos, &locations[i]);
}
@ -1323,7 +1305,7 @@ void FlowGraphAllocator::ProcessOneOutput(BlockEntryInstr* block,
if ((interference_set != NULL) && (range->vreg() >= 0) &&
interference_set->Contains(range->vreg())) {
interference_set->Add(input->ssa_temp_index());
interference_set->Add(input->vreg(0));
}
} else {
// Normal unallocated location that requires a register. Expected shape of
@ -1355,9 +1337,7 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
Definition* def = current->AsDefinition();
if ((def != NULL) && (def->AsConstant() != NULL)) {
ASSERT(!def->HasPairRepresentation());
LiveRange* range = (def->ssa_temp_index() != -1)
? GetLiveRange(def->ssa_temp_index())
: NULL;
LiveRange* range = (def->vreg(0) != -1) ? GetLiveRange(def->vreg(0)) : NULL;
// Drop definitions of constants that have no uses.
if ((range == NULL) || (range->first_use() == NULL)) {
@ -1435,16 +1415,15 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
if (in_ref->IsPairLocation()) {
ASSERT(input->definition()->HasPairRepresentation());
PairLocation* pair = in_ref->AsPairLocation();
const intptr_t vreg = input->definition()->ssa_temp_index();
// Each element of the pair is assigned it's own virtual register number
// and is allocated its own LiveRange.
ProcessOneInput(block, pos, pair->SlotAt(0), input, vreg,
live_registers);
ProcessOneInput(block, pos, pair->SlotAt(0), input,
input->definition()->vreg(0), live_registers);
ProcessOneInput(block, pos, pair->SlotAt(1), input,
ToSecondPairVreg(vreg), live_registers);
input->definition()->vreg(1), live_registers);
} else {
ProcessOneInput(block, pos, in_ref, input,
input->definition()->ssa_temp_index(), live_registers);
ProcessOneInput(block, pos, in_ref, input, input->definition()->vreg(0),
live_registers);
}
}
}
@ -1543,7 +1522,7 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
}
if (locs->out(0).IsInvalid()) {
ASSERT(def->ssa_temp_index() < 0);
ASSERT(def->vreg(0) < 0);
return;
}
@ -1559,42 +1538,40 @@ void FlowGraphAllocator::ProcessOneInstruction(BlockEntryInstr* block,
ASSERT(input->HasPairRepresentation());
// Each element of the pair is assigned it's own virtual register number
// and is allocated its own LiveRange.
ProcessOneOutput(block, pos, // BlockEntry, seq.
pair->SlotAt(0), def, // (output) Location, Definition.
def->ssa_temp_index(), // (output) virtual register.
true, // output mapped to first input.
ProcessOneOutput(block, pos, // BlockEntry, seq.
pair->SlotAt(0), def, // (output) Location, Definition.
def->vreg(0), // (output) virtual register.
true, // output mapped to first input.
in_pair->SlotAt(0), input, // (input) Location, Def.
input->ssa_temp_index(), // (input) virtual register.
input->vreg(0), // (input) virtual register.
interference_set);
ProcessOneOutput(block, pos, pair->SlotAt(1), def, def->vreg(1), true,
in_pair->SlotAt(1), input, input->vreg(1),
interference_set);
ProcessOneOutput(
block, pos, pair->SlotAt(1), def,
ToSecondPairVreg(def->ssa_temp_index()), true, in_pair->SlotAt(1),
input, ToSecondPairVreg(input->ssa_temp_index()), interference_set);
} else {
// Each element of the pair is assigned it's own virtual register number
// and is allocated its own LiveRange.
ProcessOneOutput(block, pos, pair->SlotAt(0), def, def->ssa_temp_index(),
ProcessOneOutput(block, pos, pair->SlotAt(0), def, def->vreg(0),
false, // output is not mapped to first input.
NULL, NULL, -1, // First input not needed.
interference_set);
ProcessOneOutput(block, pos, pair->SlotAt(1), def,
ToSecondPairVreg(def->ssa_temp_index()), false, NULL,
NULL, -1, interference_set);
ProcessOneOutput(block, pos, pair->SlotAt(1), def, def->vreg(1), false,
NULL, NULL, -1, interference_set);
}
} else {
if (output_same_as_first_input) {
Location* in_ref = locs->in_slot(0);
Definition* input = current->InputAt(0)->definition();
ASSERT(!in_ref->IsPairLocation());
ProcessOneOutput(block, pos, // BlockEntry, Instruction, seq.
out, def, // (output) Location, Definition.
def->ssa_temp_index(), // (output) virtual register.
true, // output mapped to first input.
in_ref, input, // (input) Location, Def.
input->ssa_temp_index(), // (input) virtual register.
ProcessOneOutput(block, pos, // BlockEntry, Instruction, seq.
out, def, // (output) Location, Definition.
def->vreg(0), // (output) virtual register.
true, // output mapped to first input.
in_ref, input, // (input) Location, Def.
input->vreg(0), // (input) virtual register.
interference_set);
} else {
ProcessOneOutput(block, pos, out, def, def->ssa_temp_index(),
ProcessOneOutput(block, pos, out, def, def->vreg(0),
false, // output is not mapped to first input.
NULL, NULL, -1, // First input not needed.
interference_set);
@ -2202,8 +2179,7 @@ intptr_t FlowGraphAllocator::FirstIntersectionWithAllocated(
void ReachingDefs::AddPhi(PhiInstr* phi) {
if (phi->reaching_defs() == NULL) {
Zone* zone = flow_graph_.zone();
phi->set_reaching_defs(
new (zone) BitVector(zone, flow_graph_.max_virtual_register_number()));
phi->set_reaching_defs(new (zone) BitVector(zone, flow_graph_.max_vreg()));
// Compute initial set reaching defs set.
bool depends_on_phi = false;
@ -2212,9 +2188,9 @@ void ReachingDefs::AddPhi(PhiInstr* phi) {
if (input->IsPhi()) {
depends_on_phi = true;
}
phi->reaching_defs()->Add(input->ssa_temp_index());
phi->reaching_defs()->Add(input->vreg(0));
if (phi->HasPairRepresentation()) {
phi->reaching_defs()->Add(ToSecondPairVreg(input->ssa_temp_index()));
phi->reaching_defs()->Add(input->vreg(1));
}
}
@ -2329,7 +2305,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
it.Advance()) {
PhiInstr* phi = it.Current();
ASSERT(phi->is_alive());
const intptr_t phi_vreg = phi->ssa_temp_index();
const intptr_t phi_vreg = phi->vreg(0);
LiveRange* range = GetLiveRange(phi_vreg);
if (range->assigned_location().kind() == register_kind_) {
const intptr_t reg = range->assigned_location().register_code();
@ -2338,7 +2314,7 @@ bool FlowGraphAllocator::AllocateFreeRegister(LiveRange* unallocated) {
}
}
if (phi->HasPairRepresentation()) {
const intptr_t second_phi_vreg = ToSecondPairVreg(phi_vreg);
const intptr_t second_phi_vreg = phi->vreg(1);
LiveRange* second_range = GetLiveRange(second_phi_vreg);
if (second_range->assigned_location().kind() == register_kind_) {
const intptr_t reg =
@ -3091,10 +3067,10 @@ void FlowGraphAllocator::CollectRepresentations() {
auto initial_definitions = graph_entry->initial_definitions();
for (intptr_t i = 0; i < initial_definitions->length(); ++i) {
Definition* def = (*initial_definitions)[i];
value_representations_[def->ssa_temp_index()] =
value_representations_[def->vreg(0)] =
RepresentationForRange(def->representation());
if (def->HasPairRepresentation()) {
value_representations_[ToSecondPairVreg(def->ssa_temp_index())] =
value_representations_[def->vreg(1)] =
RepresentationForRange(def->representation());
}
}
@ -3107,21 +3083,21 @@ void FlowGraphAllocator::CollectRepresentations() {
initial_definitions = entry->initial_definitions();
for (intptr_t i = 0; i < initial_definitions->length(); ++i) {
Definition* def = (*initial_definitions)[i];
value_representations_[def->ssa_temp_index()] =
value_representations_[def->vreg(0)] =
RepresentationForRange(def->representation());
if (def->HasPairRepresentation()) {
value_representations_[ToSecondPairVreg(def->ssa_temp_index())] =
value_representations_[def->vreg(1)] =
RepresentationForRange(def->representation());
}
}
} else if (auto join = block->AsJoinEntry()) {
for (PhiIterator it(join); !it.Done(); it.Advance()) {
PhiInstr* phi = it.Current();
ASSERT(phi != NULL && phi->ssa_temp_index() >= 0);
value_representations_[phi->ssa_temp_index()] =
ASSERT(phi != NULL && phi->vreg(0) >= 0);
value_representations_[phi->vreg(0)] =
RepresentationForRange(phi->representation());
if (phi->HasPairRepresentation()) {
value_representations_[ToSecondPairVreg(phi->ssa_temp_index())] =
value_representations_[phi->vreg(1)] =
RepresentationForRange(phi->representation());
}
}
@ -3131,12 +3107,12 @@ void FlowGraphAllocator::CollectRepresentations() {
for (ForwardInstructionIterator instr_it(block); !instr_it.Done();
instr_it.Advance()) {
Definition* def = instr_it.Current()->AsDefinition();
if ((def != NULL) && (def->ssa_temp_index() >= 0)) {
const intptr_t vreg = def->ssa_temp_index();
if ((def != NULL) && (def->vreg(0) >= 0)) {
const intptr_t vreg = def->vreg(0);
value_representations_[vreg] =
RepresentationForRange(def->representation());
if (def->HasPairRepresentation()) {
value_representations_[ToSecondPairVreg(vreg)] =
value_representations_[def->vreg(1)] =
RepresentationForRange(def->representation());
}
}
@ -3290,10 +3266,10 @@ void FlowGraphAllocator::RemoveFrameIfNotNeeded() {
if (FunctionEntryInstr* entry = block->AsFunctionEntry()) {
for (auto defn : *entry->initial_definitions()) {
if (auto param = defn->AsParameter()) {
const auto vreg = param->ssa_temp_index();
const auto vreg = param->vreg(0);
fix_location_for(block, param, vreg, 0);
if (param->HasPairRepresentation()) {
fix_location_for(block, param, ToSecondPairVreg(vreg),
fix_location_for(block, param, param->vreg(1),
/*pair_index=*/1);
}
}

View file

@ -39,8 +39,7 @@ class ReachingDefs : public ValueObject {
class SSALivenessAnalysis : public LivenessAnalysis {
public:
explicit SSALivenessAnalysis(const FlowGraph& flow_graph)
: LivenessAnalysis(flow_graph.max_virtual_register_number(),
flow_graph.postorder()),
: LivenessAnalysis(flow_graph.max_vreg(), flow_graph.postorder()),
graph_entry_(flow_graph.graph_entry()) {}
private:

View file

@ -66,6 +66,19 @@ enum Representation {
kNumRepresentations
};
static const intptr_t kMaxLocationCount = 2;
inline intptr_t LocationCount(Representation rep) {
switch (rep) {
case kPairOfTagged:
return 2;
case kUnboxedInt64:
return compiler::target::kWordSize == 8 ? 1 : 2;
default:
return 1;
}
}
struct RepresentationUtils : AllStatic {
// Whether the representation is for a type of unboxed integer.
static bool IsUnboxedInteger(Representation rep);

View file

@ -2611,7 +2611,7 @@ class LoadOptimizer : public ValueObject {
replacement->AddInputUse(input);
}
graph_->AllocateSSAIndexes(phi);
graph_->AllocateSSAIndex(phi);
phis_.Add(phi); // Postpone phi insertion until after load forwarding.
if (FLAG_support_il_printer && FLAG_trace_load_optimization) {
@ -4259,10 +4259,7 @@ void TryCatchAnalyzer::Optimize() {
ConstantInstr* orig = cdefs[j]->AsConstant();
ConstantInstr* copy =
new (flow_graph_->zone()) ConstantInstr(orig->value());
copy->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
if (FlowGraph::NeedsPairLocation(copy->representation())) {
flow_graph_->alloc_ssa_temp_index();
}
flow_graph_->AllocateSSAIndex(copy);
old->ReplaceUsesWith(copy);
copy->set_previous(old->previous()); // partial link
(*idefs)[j] = copy;

View file

@ -286,7 +286,7 @@ void FlowGraphTypePropagator::VisitCheckNull(CheckNullInstr* check) {
// motion of the check may still enable valid code motion
// of the checked code.
if (check->ssa_temp_index() == -1) {
flow_graph_->AllocateSSAIndexes(check);
flow_graph_->AllocateSSAIndex(check);
GrowTypes(check->ssa_temp_index() + 1);
}
FlowGraph::RenameDominatedUses(receiver, check, check);
@ -370,7 +370,7 @@ void FlowGraphTypePropagator::VisitAssertAssignable(
auto defn = check->value()->definition();
SetTypeOf(defn, new (zone()) CompileType(check->ComputeType()));
if (check->ssa_temp_index() == -1) {
flow_graph_->AllocateSSAIndexes(check);
flow_graph_->AllocateSSAIndex(check);
GrowTypes(check->ssa_temp_index() + 1);
}
FlowGraph::RenameDominatedUses(defn, check, check);

View file

@ -41,13 +41,13 @@ void InlineExitCollector::PrepareGraphs(FlowGraph* callee_graph) {
COMPILER_TIMINGS_TIMER_SCOPE(callee_graph->thread(), PrepareGraphs);
ASSERT(callee_graph->graph_entry()->SuccessorCount() == 1);
ASSERT(callee_graph->max_block_id() > caller_graph_->max_block_id());
ASSERT(callee_graph->max_virtual_register_number() >
caller_graph_->max_virtual_register_number());
ASSERT(callee_graph->current_ssa_temp_index() >
caller_graph_->current_ssa_temp_index());
// Adjust the caller's maximum block id and current SSA temp index.
caller_graph_->set_max_block_id(callee_graph->max_block_id());
caller_graph_->set_current_ssa_temp_index(
callee_graph->max_virtual_register_number());
callee_graph->current_ssa_temp_index());
// Attach the outer environment on each instruction in the callee graph.
ASSERT(call_->env() != NULL);
@ -218,7 +218,7 @@ Definition* InlineExitCollector::JoinReturns(BlockEntryInstr** exit_block,
if (call_->HasUses()) {
// Add a phi of the return values.
PhiInstr* phi = new (Z) PhiInstr(join, num_exits);
caller_graph_->AllocateSSAIndexes(phi);
caller_graph_->AllocateSSAIndex(phi);
phi->mark_alive();
for (intptr_t i = 0; i < num_exits; ++i) {
ReturnAt(i)->RemoveEnvironment();