summaryrefslogtreecommitdiff
path: root/compiler/optimizing/optimizing_unit_test.h
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2024-08-06 07:54:26 +0000
committer Treehugger Robot <android-test-infra-autosubmit@system.gserviceaccount.com> 2024-08-12 14:00:38 +0000
commit4018a7d772fc09c7955eb4c88eea788be5cc2143 (patch)
tree45ebb2078a2ad1c5d61cfcb76a4585ab84159ef1 /compiler/optimizing/optimizing_unit_test.h
parentbed0b477e8f55d57cf100c585eb6d5838c9ffcee (diff)
ART: Clean up HIR construction in gtests.
Make `OptimizingUnitTestHelper::Make*()` functions add the the new instruction to the block. If the block already ends with a control flow instruction, the new instruction is inserted before the control flow instruction (some tests create the control flow before adding instruction). Add new helper functions for additional instruction types, rename and clean up existing helpers. Test: m test-art-host-gtest Change-Id: I0bb88bc4d2ff6ce98ddbec25990a1ae68f582042
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;