diff options
Diffstat (limited to 'compiler/optimizing/optimizing_unit_test.h')
-rw-r--r-- | compiler/optimizing/optimizing_unit_test.h | 282 |
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, ¤t_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; |