ART: Force constants into the entry block
Optimizations such as GVN and BCE make the assumption that all
constants are located in the entry block of the CFG, but not all
passes adhere to this rule.
This patch makes constructors of constants private and only accessible
to friend classes - HGraph for int/long constants and SsaBuilder for
float/double - which ensure that they are placed correctly and not
duplicated.
Note that the ArenaAllocatorAdapter was modified to not increment
the ArenaAllocator's internal reference counter in order to allow
for use of ArenaSafeMap inside an arena-allocated objects. Because
their destructor is not called, the counter does not get decremented.
Change-Id: I36a4fa29ae34fb905cdefd482ccbf386cff14166
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index f81935a..2cdd5af 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -215,7 +215,7 @@
DCHECK(fallthrough_target != nullptr);
PotentiallyAddSuspendCheck(branch_target, dex_pc);
HInstruction* value = LoadLocal(instruction.VRegA(), Primitive::kPrimInt);
- T* comparison = new (arena_) T(value, GetIntConstant(0));
+ T* comparison = new (arena_) T(value, graph_->GetIntConstant(0));
current_block_->AddInstruction(comparison);
HInstruction* ifinst = new (arena_) HIf(comparison);
current_block_->AddInstruction(ifinst);
@@ -515,7 +515,7 @@
template<typename T>
void HGraphBuilder::Binop_22s(const Instruction& instruction, bool reverse) {
HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- HInstruction* second = GetIntConstant(instruction.VRegC_22s());
+ HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22s());
if (reverse) {
std::swap(first, second);
}
@@ -526,7 +526,7 @@
template<typename T>
void HGraphBuilder::Binop_22b(const Instruction& instruction, bool reverse) {
HInstruction* first = LoadLocal(instruction.VRegB(), Primitive::kPrimInt);
- HInstruction* second = GetIntConstant(instruction.VRegC_22b());
+ HInstruction* second = graph_->GetIntConstant(instruction.VRegC_22b());
if (reverse) {
std::swap(first, second);
}
@@ -824,9 +824,9 @@
HInstruction* second = nullptr;
if (second_is_constant) {
if (type == Primitive::kPrimInt) {
- second = GetIntConstant(second_vreg_or_constant);
+ second = graph_->GetIntConstant(second_vreg_or_constant);
} else {
- second = GetLongConstant(second_vreg_or_constant);
+ second = graph_->GetLongConstant(second_vreg_or_constant);
}
} else {
second = LoadLocal(second_vreg_or_constant, type);
@@ -890,7 +890,7 @@
bool is_range,
uint32_t* args,
uint32_t register_index) {
- HInstruction* length = GetIntConstant(number_of_vreg_arguments);
+ HInstruction* length = graph_->GetIntConstant(number_of_vreg_arguments);
QuickEntrypointEnum entrypoint = NeedsAccessCheck(type_index)
? kQuickAllocArrayWithAccessCheck
: kQuickAllocArray;
@@ -910,7 +910,7 @@
temps.Add(object);
for (size_t i = 0; i < number_of_vreg_arguments; ++i) {
HInstruction* value = LoadLocal(is_range ? register_index + i : args[i], type);
- HInstruction* index = GetIntConstant(i);
+ HInstruction* index = graph_->GetIntConstant(i);
current_block_->AddInstruction(
new (arena_) HArraySet(object, index, value, type, dex_pc));
}
@@ -924,8 +924,8 @@
Primitive::Type anticipated_type,
uint32_t dex_pc) {
for (uint32_t i = 0; i < element_count; ++i) {
- HInstruction* index = GetIntConstant(i);
- HInstruction* value = GetIntConstant(data[i]);
+ HInstruction* index = graph_->GetIntConstant(i);
+ HInstruction* value = graph_->GetIntConstant(data[i]);
current_block_->AddInstruction(new (arena_) HArraySet(
object, index, value, anticipated_type, dex_pc));
}
@@ -949,7 +949,7 @@
// Implementation of this DEX instruction seems to be that the bounds check is
// done before doing any stores.
- HInstruction* last_index = GetIntConstant(payload->element_count - 1);
+ HInstruction* last_index = graph_->GetIntConstant(payload->element_count - 1);
current_block_->AddInstruction(new (arena_) HBoundsCheck(last_index, length, dex_pc));
switch (payload->element_width) {
@@ -990,8 +990,8 @@
uint32_t element_count,
uint32_t dex_pc) {
for (uint32_t i = 0; i < element_count; ++i) {
- HInstruction* index = GetIntConstant(i);
- HInstruction* value = GetLongConstant(data[i]);
+ HInstruction* index = graph_->GetIntConstant(i);
+ HInstruction* value = graph_->GetLongConstant(data[i]);
current_block_->AddInstruction(new (arena_) HArraySet(
object, index, value, Primitive::kPrimLong, dex_pc));
}
@@ -1082,7 +1082,7 @@
PotentiallyAddSuspendCheck(case_target, dex_pc);
// The current case's value.
- HInstruction* this_case_value = GetIntConstant(case_value_int);
+ HInstruction* this_case_value = graph_->GetIntConstant(case_value_int);
// Compare value and this_case_value.
HEqual* comparison = new (arena_) HEqual(value, this_case_value);
@@ -1140,28 +1140,28 @@
switch (instruction.Opcode()) {
case Instruction::CONST_4: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = GetIntConstant(instruction.VRegB_11n());
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_11n());
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_16: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = GetIntConstant(instruction.VRegB_21s());
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21s());
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = GetIntConstant(instruction.VRegB_31i());
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_31i());
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_HIGH16: {
int32_t register_index = instruction.VRegA();
- HIntConstant* constant = GetIntConstant(instruction.VRegB_21h() << 16);
+ HIntConstant* constant = graph_->GetIntConstant(instruction.VRegB_21h() << 16);
UpdateLocal(register_index, constant);
break;
}
@@ -1172,7 +1172,7 @@
int64_t value = instruction.VRegB_21s();
value <<= 48;
value >>= 48;
- HLongConstant* constant = GetLongConstant(value);
+ HLongConstant* constant = graph_->GetLongConstant(value);
UpdateLocal(register_index, constant);
break;
}
@@ -1183,14 +1183,14 @@
int64_t value = instruction.VRegB_31i();
value <<= 32;
value >>= 32;
- HLongConstant* constant = GetLongConstant(value);
+ HLongConstant* constant = graph_->GetLongConstant(value);
UpdateLocal(register_index, constant);
break;
}
case Instruction::CONST_WIDE: {
int32_t register_index = instruction.VRegA();
- HLongConstant* constant = GetLongConstant(instruction.VRegB_51l());
+ HLongConstant* constant = graph_->GetLongConstant(instruction.VRegB_51l());
UpdateLocal(register_index, constant);
break;
}
@@ -1198,7 +1198,7 @@
case Instruction::CONST_WIDE_HIGH16: {
int32_t register_index = instruction.VRegA();
int64_t value = static_cast<int64_t>(instruction.VRegB_21h()) << 48;
- HLongConstant* constant = GetLongConstant(value);
+ HLongConstant* constant = graph_->GetLongConstant(value);
UpdateLocal(register_index, constant);
break;
}
@@ -2100,24 +2100,6 @@
return true;
} // NOLINT(readability/fn_size)
-HIntConstant* HGraphBuilder::GetIntConstant(int32_t constant) {
- switch (constant) {
- case 0: return graph_->GetIntConstant0();
- case 1: return graph_->GetIntConstant1();
- default: {
- HIntConstant* instruction = new (arena_) HIntConstant(constant);
- graph_->AddConstant(instruction);
- return instruction;
- }
- }
-}
-
-HLongConstant* HGraphBuilder::GetLongConstant(int64_t constant) {
- HLongConstant* instruction = new (arena_) HLongConstant(constant);
- graph_->AddConstant(instruction);
- return instruction;
-}
-
HLocal* HGraphBuilder::GetLocalAt(int register_index) const {
return locals_.Get(register_index);
}