summaryrefslogtreecommitdiff
path: root/compiler/optimizing/optimizing_unit_test.h
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing/optimizing_unit_test.h')
-rw-r--r--compiler/optimizing/optimizing_unit_test.h282
1 files changed, 220 insertions, 62 deletions
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index e1d8969b2b..b256d439fb 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -306,11 +306,6 @@ class OptimizingUnitTestHelper {
exit_block_->AddInstruction(new (GetAllocator()) HExit());
}
- void AddParameter(HInstruction* parameter) {
- entry_block_->AddInstruction(parameter);
- parameters_.push_back(parameter);
- }
-
HBasicBlock* AddNewBlock() {
HBasicBlock* block = new (GetAllocator()) HBasicBlock(graph_);
graph_->AddBlock(block);
@@ -391,68 +386,167 @@ class OptimizingUnitTestHelper {
OptimizingUnitTestHelper::ManuallyBuildEnvFor(ins, &current_locals);
}
- HLoadClass* MakeClassLoad(std::optional<dex::TypeIndex> ti = std::nullopt,
- std::optional<Handle<mirror::Class>> klass = std::nullopt) {
- return new (GetAllocator()) HLoadClass(graph_->GetCurrentMethod(),
- ti ? *ti : dex::TypeIndex(class_idx_++),
- graph_->GetDexFile(),
- /* klass= */ klass ? *klass : null_klass_,
- /* is_referrers_class= */ false,
- /* dex_pc= */ 0,
- /* needs_access_check= */ false);
+ HLoadClass* MakeLoadClass(HBasicBlock* block,
+ std::optional<dex::TypeIndex> ti = std::nullopt,
+ std::optional<Handle<mirror::Class>> klass = std::nullopt,
+ uint32_t dex_pc = kNoDexPc) {
+ HLoadClass* load_class = new (GetAllocator()) HLoadClass(
+ graph_->GetCurrentMethod(),
+ ti ? *ti : dex::TypeIndex(class_idx_++),
+ graph_->GetDexFile(),
+ /* klass= */ klass ? *klass : null_klass_,
+ /* is_referrers_class= */ false,
+ dex_pc,
+ /* needs_access_check= */ false);
+ AddOrInsertInstruction(block, load_class);
+ return load_class;
}
- HNewInstance* MakeNewInstance(HInstruction* cls, uint32_t dex_pc = 0u) {
+ HNewInstance* MakeNewInstance(HBasicBlock* block, HInstruction* cls, uint32_t dex_pc = kNoDexPc) {
EXPECT_TRUE(cls->IsLoadClass() || cls->IsClinitCheck()) << *cls;
HLoadClass* load =
cls->IsLoadClass() ? cls->AsLoadClass() : cls->AsClinitCheck()->GetLoadClass();
- return new (GetAllocator()) HNewInstance(cls,
- dex_pc,
- load->GetTypeIndex(),
- graph_->GetDexFile(),
- /* finalizable= */ false,
- QuickEntrypointEnum::kQuickAllocObjectInitialized);
+ HNewInstance* new_instance = new (GetAllocator()) HNewInstance(
+ cls,
+ dex_pc,
+ load->GetTypeIndex(),
+ graph_->GetDexFile(),
+ /* finalizable= */ false,
+ QuickEntrypointEnum::kQuickAllocObjectInitialized);
+ AddOrInsertInstruction(block, new_instance);
+ return new_instance;
+ }
+
+ HInstanceFieldSet* MakeIFieldSet(HBasicBlock* block,
+ HInstruction* inst,
+ HInstruction* data,
+ MemberOffset off,
+ uint32_t dex_pc = kNoDexPc) {
+ CHECK(data != nullptr);
+ return MakeIFieldSet(block, inst, data, data->GetType(), off, dex_pc);
}
- HInstanceFieldSet* MakeIFieldSet(HInstruction* inst,
+ HInstanceFieldSet* MakeIFieldSet(HBasicBlock* block,
+ HInstruction* inst,
HInstruction* data,
+ DataType::Type field_type,
MemberOffset off,
- uint32_t dex_pc = 0u) {
- return new (GetAllocator()) HInstanceFieldSet(inst,
- data,
- /* field= */ nullptr,
- /* field_type= */ data->GetType(),
- /* field_offset= */ off,
- /* is_volatile= */ false,
- /* field_idx= */ 0,
- /* declaring_class_def_index= */ 0,
- graph_->GetDexFile(),
- dex_pc);
- }
-
- HInstanceFieldGet* MakeIFieldGet(HInstruction* inst,
+ uint32_t dex_pc = kNoDexPc) {
+ HInstanceFieldSet* ifield_set = new (GetAllocator()) HInstanceFieldSet(
+ inst,
+ data,
+ /* field= */ nullptr,
+ field_type,
+ /* field_offset= */ off,
+ /* is_volatile= */ false,
+ kUnknownFieldIndex,
+ kUnknownClassDefIndex,
+ graph_->GetDexFile(),
+ dex_pc);
+ AddOrInsertInstruction(block, ifield_set);
+ return ifield_set;
+ }
+
+ HInstanceFieldGet* MakeIFieldGet(HBasicBlock* block,
+ HInstruction* inst,
DataType::Type type,
MemberOffset off,
- uint32_t dex_pc = 0u) {
- return new (GetAllocator()) HInstanceFieldGet(inst,
- /* field= */ nullptr,
- /* field_type= */ type,
- /* field_offset= */ off,
- /* is_volatile= */ false,
- /* field_idx= */ 0,
- /* declaring_class_def_index= */ 0,
- graph_->GetDexFile(),
- dex_pc);
- }
-
- HInvokeStaticOrDirect* MakeInvoke(DataType::Type return_type,
- const std::vector<HInstruction*>& args) {
+ uint32_t dex_pc = kNoDexPc) {
+ HInstanceFieldGet* ifield_get = new (GetAllocator()) HInstanceFieldGet(
+ inst,
+ /* field= */ nullptr,
+ /* field_type= */ type,
+ /* field_offset= */ off,
+ /* is_volatile= */ false,
+ kUnknownFieldIndex,
+ kUnknownClassDefIndex,
+ graph_->GetDexFile(),
+ dex_pc);
+ AddOrInsertInstruction(block, ifield_get);
+ return ifield_get;
+ }
+
+ HNewArray* MakeNewArray(HBasicBlock* block,
+ HInstruction* cls,
+ HInstruction* length,
+ size_t component_size_shift = DataType::SizeShift(DataType::Type::kInt32),
+ uint32_t dex_pc = kNoDexPc) {
+ HNewArray* new_array =
+ new (GetAllocator()) HNewArray(cls, length, dex_pc, component_size_shift);
+ AddOrInsertInstruction(block, new_array);
+ return new_array;
+ }
+
+ HArraySet* MakeArraySet(HBasicBlock* block,
+ HInstruction* array,
+ HInstruction* index,
+ HInstruction* value,
+ DataType::Type type,
+ uint32_t dex_pc = kNoDexPc) {
+ HArraySet* array_set = new (GetAllocator()) HArraySet(array, index, value, type, dex_pc);
+ AddOrInsertInstruction(block, array_set);
+ return array_set;
+ }
+
+ HArrayGet* MakeArrayGet(HBasicBlock* block,
+ HInstruction* array,
+ HInstruction* index,
+ DataType::Type type,
+ uint32_t dex_pc = kNoDexPc) {
+ HArrayGet* array_get = new (GetAllocator()) HArrayGet(array, index, type, dex_pc);
+ AddOrInsertInstruction(block, array_get);
+ return array_get;
+ }
+
+ HArrayLength* MakeArrayLength(HBasicBlock* block,
+ HInstruction* array,
+ uint32_t dex_pc = kNoDexPc) {
+ HArrayLength* array_length = new (GetAllocator()) HArrayLength(array, dex_pc);
+ AddOrInsertInstruction(block, array_length);
+ return array_length;
+ }
+
+ HNullCheck* MakeNullCheck(HBasicBlock* block,
+ HInstruction* value,
+ uint32_t dex_pc = kNoDexPc) {
+ HNullCheck* null_check = new (GetAllocator()) HNullCheck(value, dex_pc);
+ AddOrInsertInstruction(block, null_check);
+ return null_check;
+ }
+
+ HBoundsCheck* MakeBoundsCheck(HBasicBlock* block,
+ HInstruction* index,
+ HInstruction* length,
+ uint32_t dex_pc = kNoDexPc) {
+ HBoundsCheck* bounds_check = new (GetAllocator()) HBoundsCheck(index, length, dex_pc);
+ AddOrInsertInstruction(block, bounds_check);
+ return bounds_check;
+ }
+
+ HVecStore* MakeVecStore(HBasicBlock* block,
+ HInstruction* base,
+ HInstruction* index,
+ HInstruction* value,
+ DataType::Type packed_type,
+ size_t vector_length = 4,
+ uint32_t dex_pc = kNoDexPc) {
+ SideEffects side_effects = SideEffects::ArrayWriteOfType(packed_type);
+ HVecStore* vec_store = new (GetAllocator()) HVecStore(
+ GetAllocator(), base, index, value, packed_type, side_effects, vector_length, dex_pc);
+ AddOrInsertInstruction(block, vec_store);
+ return vec_store;
+ }
+
+ HInvokeStaticOrDirect* MakeInvokeStatic(HBasicBlock* block,
+ DataType::Type return_type,
+ const std::vector<HInstruction*>& args,
+ uint32_t dex_pc = kNoDexPc) {
MethodReference method_reference{/* file= */ &graph_->GetDexFile(), /* index= */ method_idx_++};
- HInvokeStaticOrDirect* res = new (GetAllocator())
+ HInvokeStaticOrDirect* invoke = new (GetAllocator())
HInvokeStaticOrDirect(GetAllocator(),
args.size(),
return_type,
- /* dex_pc= */ 0,
+ dex_pc,
method_reference,
/* resolved_method= */ nullptr,
HInvokeStaticOrDirect::DispatchInfo{},
@@ -461,25 +555,91 @@ class OptimizingUnitTestHelper {
HInvokeStaticOrDirect::ClinitCheckRequirement::kNone,
!graph_->IsDebuggable());
for (auto [ins, idx] : ZipCount(MakeIterationRange(args))) {
- res->SetRawInputAt(idx, ins);
+ invoke->SetRawInputAt(idx, ins);
+ }
+ AddOrInsertInstruction(block, invoke);
+ return invoke;
+ }
+
+ template <typename Type>
+ Type* MakeBinOp(HBasicBlock* block,
+ DataType::Type result_type,
+ HInstruction* left,
+ HInstruction* right,
+ uint32_t dex_pc = kNoDexPc) {
+ static_assert(std::is_base_of_v<HBinaryOperation, Type>);
+ Type* insn = new (GetAllocator()) Type(result_type, left, right, dex_pc);
+ AddOrInsertInstruction(block, insn);
+ return insn;
+ }
+
+ template <typename Type>
+ Type* MakeCondition(HBasicBlock* block,
+ HInstruction* first,
+ HInstruction* second,
+ uint32_t dex_pc = kNoDexPc) {
+ static_assert(std::is_base_of_v<HCondition, Type>);
+ Type* condition = new (GetAllocator()) Type(first, second, dex_pc);
+ AddOrInsertInstruction(block, condition);
+ return condition;
+ }
+
+ HSuspendCheck* MakeSuspendCheck(HBasicBlock* block, uint32_t dex_pc = kNoDexPc) {
+ HSuspendCheck* suspend_check = new (GetAllocator()) HSuspendCheck(dex_pc);
+ AddOrInsertInstruction(block, suspend_check);
+ return suspend_check;
+ }
+
+ void AddOrInsertInstruction(HBasicBlock* block, HInstruction* instruction) {
+ CHECK(!instruction->IsControlFlow());
+ if (block->GetLastInstruction() != nullptr && block->GetLastInstruction()->IsControlFlow()) {
+ block->InsertInstructionBefore(instruction, block->GetLastInstruction());
+ } else {
+ block->AddInstruction(instruction);
}
- return res;
}
- HPhi* MakePhi(const std::vector<HInstruction*>& ins) {
+ HIf* MakeIf(HBasicBlock* block, HInstruction* cond, uint32_t dex_pc = kNoDexPc) {
+ HIf* if_insn = new (GetAllocator()) HIf(cond, dex_pc);
+ block->AddInstruction(if_insn);
+ return if_insn;
+ }
+
+ HGoto* MakeGoto(HBasicBlock* block, uint32_t dex_pc = kNoDexPc) {
+ HGoto* goto_insn = new (GetAllocator()) HGoto(dex_pc);
+ block->AddInstruction(goto_insn);
+ return goto_insn;
+ }
+
+ HReturnVoid* MakeReturnVoid(HBasicBlock* block, uint32_t dex_pc = kNoDexPc) {
+ HReturnVoid* return_void = new (GetAllocator()) HReturnVoid(dex_pc);
+ block->AddInstruction(return_void);
+ return return_void;
+ }
+
+ HReturn* MakeReturn(HBasicBlock* block, HInstruction* value, uint32_t dex_pc = kNoDexPc) {
+ HReturn* return_insn = new (GetAllocator()) HReturn(value, dex_pc);
+ block->AddInstruction(return_insn);
+ return return_insn;
+ }
+
+ HExit* MakeExit(HBasicBlock* exit_block) {
+ HExit* exit = new (GetAllocator()) HExit();
+ exit_block->AddInstruction(exit);
+ return exit;
+ }
+
+ HPhi* MakePhi(HBasicBlock* block, const std::vector<HInstruction*>& ins) {
EXPECT_GE(ins.size(), 2u) << "Phi requires at least 2 inputs";
HPhi* phi =
new (GetAllocator()) HPhi(GetAllocator(), kNoRegNumber, ins.size(), ins[0]->GetType());
for (auto [i, idx] : ZipCount(MakeIterationRange(ins))) {
phi->SetRawInputAt(idx, i);
}
+ block->AddPhi(phi);
return phi;
}
- void SetupExit(HBasicBlock* exit) {
- exit->AddInstruction(new (GetAllocator()) HExit());
- }
-
dex::TypeIndex DefaultTypeIndexForType(DataType::Type type) {
switch (type) {
case DataType::Type::kBool:
@@ -508,7 +668,7 @@ class OptimizingUnitTestHelper {
}
}
- // Creates a parameter. The instruction is automatically added to the entry-block
+ // Creates a parameter. The instruction is automatically added to the entry-block.
HParameterValue* MakeParam(DataType::Type type, std::optional<dex::TypeIndex> ti = std::nullopt) {
HParameterValue* val = new (GetAllocator()) HParameterValue(
graph_->GetDexFile(), ti ? *ti : DefaultTypeIndexForType(type), param_count_++, type);
@@ -532,8 +692,6 @@ class OptimizingUnitTestHelper {
HBasicBlock* return_block_;
HBasicBlock* exit_block_;
- std::vector<HInstruction*> parameters_;
-
size_t param_count_ = 0;
size_t class_idx_ = 42;
uint32_t method_idx_ = 100;