diff options
Diffstat (limited to 'compiler/optimizing')
29 files changed, 414 insertions, 131 deletions
diff --git a/compiler/optimizing/code_generator.cc b/compiler/optimizing/code_generator.cc index b7c80756b0..5136d7d2b8 100644 --- a/compiler/optimizing/code_generator.cc +++ b/compiler/optimizing/code_generator.cc @@ -42,18 +42,23 @@ #endif #include "bytecode_utils.h" +#include "class_linker.h" #include "compiled_method.h" #include "dex/verified_method.h" #include "driver/compiler_driver.h" #include "graph_visualizer.h" +#include "intern_table.h" #include "intrinsics.h" #include "leb128.h" #include "mirror/array-inl.h" #include "mirror/object_array-inl.h" #include "mirror/object_reference.h" +#include "mirror/reference.h" #include "mirror/string.h" #include "parallel_move_resolver.h" #include "ssa_liveness_analysis.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "utils/assembler.h" namespace art { diff --git a/compiler/optimizing/code_generator_arm64.h b/compiler/optimizing/code_generator_arm64.h index 58feea2423..332ab49153 100644 --- a/compiler/optimizing/code_generator_arm64.h +++ b/compiler/optimizing/code_generator_arm64.h @@ -321,7 +321,9 @@ class InstructionCodeGeneratorARM64 : public InstructionCodeGenerator { vixl::aarch64::MemOperand CreateVecMemRegisters( HVecMemoryOperation* instruction, Location* reg_loc, - bool is_load); + bool is_load, + // This function may acquire a scratch register. + vixl::aarch64::UseScratchRegisterScope* temps_scope); Arm64Assembler* const assembler_; CodeGeneratorARM64* const codegen_; diff --git a/compiler/optimizing/code_generator_vector_arm.cc b/compiler/optimizing/code_generator_vector_arm.cc index 6e82123e56..f8552dcfc9 100644 --- a/compiler/optimizing/code_generator_vector_arm.cc +++ b/compiler/optimizing/code_generator_vector_arm.cc @@ -245,6 +245,14 @@ void InstructionCodeGeneratorARM::VisitVecUShr(HVecUShr* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } +void LocationsBuilderARM::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorARM::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + void LocationsBuilderARM::VisitVecLoad(HVecLoad* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } diff --git a/compiler/optimizing/code_generator_vector_arm64.cc b/compiler/optimizing/code_generator_vector_arm64.cc index 2dfccfff85..93befa439c 100644 --- a/compiler/optimizing/code_generator_vector_arm64.cc +++ b/compiler/optimizing/code_generator_vector_arm64.cc @@ -27,6 +27,7 @@ using helpers::HeapOperand; using helpers::InputRegisterAt; using helpers::Int64ConstantFrom; using helpers::XRegisterFrom; +using helpers::WRegisterFrom; #define __ GetVIXLAssembler()-> @@ -681,6 +682,67 @@ void InstructionCodeGeneratorARM64::VisitVecUShr(HVecUShr* instruction) { } } +void LocationsBuilderARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LocationSummary* locations = new (GetGraph()->GetArena()) LocationSummary(instr); + switch (instr->GetPackedType()) { + case Primitive::kPrimByte: + case Primitive::kPrimChar: + case Primitive::kPrimShort: + case Primitive::kPrimInt: + locations->SetInAt( + HVecMultiplyAccumulate::kInputAccumulatorIndex, Location::RequiresFpuRegister()); + locations->SetInAt( + HVecMultiplyAccumulate::kInputMulLeftIndex, Location::RequiresFpuRegister()); + locations->SetInAt( + HVecMultiplyAccumulate::kInputMulRightIndex, Location::RequiresFpuRegister()); + DCHECK_EQ(HVecMultiplyAccumulate::kInputAccumulatorIndex, 0); + locations->SetOut(Location::SameAsFirstInput()); + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + UNREACHABLE(); + } +} + +// Some early revisions of the Cortex-A53 have an erratum (835769) whereby it is possible for a +// 64-bit scalar multiply-accumulate instruction in AArch64 state to generate an incorrect result. +// However vector MultiplyAccumulate instruction is not affected. +void InstructionCodeGeneratorARM64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LocationSummary* locations = instr->GetLocations(); + VRegister acc = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputAccumulatorIndex)); + VRegister left = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulLeftIndex)); + VRegister right = VRegisterFrom(locations->InAt(HVecMultiplyAccumulate::kInputMulRightIndex)); + switch (instr->GetPackedType()) { + case Primitive::kPrimByte: + DCHECK_EQ(16u, instr->GetVectorLength()); + if (instr->GetOpKind() == HInstruction::kAdd) { + __ Mla(acc.V16B(), left.V16B(), right.V16B()); + } else { + __ Mls(acc.V16B(), left.V16B(), right.V16B()); + } + break; + case Primitive::kPrimChar: + case Primitive::kPrimShort: + DCHECK_EQ(8u, instr->GetVectorLength()); + if (instr->GetOpKind() == HInstruction::kAdd) { + __ Mla(acc.V8H(), left.V8H(), right.V8H()); + } else { + __ Mls(acc.V8H(), left.V8H(), right.V8H()); + } + break; + case Primitive::kPrimInt: + DCHECK_EQ(4u, instr->GetVectorLength()); + if (instr->GetOpKind() == HInstruction::kAdd) { + __ Mla(acc.V4S(), left.V4S(), right.V4S()); + } else { + __ Mls(acc.V4S(), left.V4S(), right.V4S()); + } + break; + default: + LOG(FATAL) << "Unsupported SIMD type"; + } +} + // Helper to set up locations for vector memory operations. static void CreateVecMemLocations(ArenaAllocator* arena, HVecMemoryOperation* instruction, @@ -713,7 +775,8 @@ static void CreateVecMemLocations(ArenaAllocator* arena, MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters( HVecMemoryOperation* instruction, Location* reg_loc, - bool is_load) { + bool is_load, + UseScratchRegisterScope* temps_scope) { LocationSummary* locations = instruction->GetLocations(); Register base = InputRegisterAt(instruction, 0); Location index = locations->InAt(1); @@ -723,20 +786,18 @@ MemOperand InstructionCodeGeneratorARM64::CreateVecMemRegisters( uint32_t offset = mirror::Array::DataOffset(Primitive::ComponentSize(packed_type)).Uint32Value(); size_t shift = Primitive::ComponentSizeShift(packed_type); - UseScratchRegisterScope temps(GetVIXLAssembler()); - Register temp = temps.AcquireSameSizeAs(base); + // HIntermediateAddress optimization is only applied for scalar ArrayGet and ArraySet. + DCHECK(!instruction->InputAt(0)->IsIntermediateAddress()); + if (index.IsConstant()) { offset += Int64ConstantFrom(index) << shift; - __ Add(temp, base, offset); + return HeapOperand(base, offset); } else { - if (instruction->InputAt(0)->IsIntermediateAddress()) { - temp = base; - } else { - __ Add(temp, base, offset); - } - __ Add(temp.X(), temp.X(), Operand(XRegisterFrom(index), LSL, shift)); + Register temp = temps_scope->AcquireSameSizeAs(base); + __ Add(temp, base, Operand(WRegisterFrom(index), LSL, shift)); + + return HeapOperand(temp, offset); } - return HeapOperand(temp); } void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) { @@ -745,28 +806,22 @@ void LocationsBuilderARM64::VisitVecLoad(HVecLoad* instruction) { void InstructionCodeGeneratorARM64::VisitVecLoad(HVecLoad* instruction) { Location reg_loc = Location::NoLocation(); - MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ true); + UseScratchRegisterScope temps(GetVIXLAssembler()); + MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ true, &temps); VRegister reg = VRegisterFrom(reg_loc); + switch (instruction->GetPackedType()) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: - DCHECK_EQ(16u, instruction->GetVectorLength()); - __ Ld1(reg.V16B(), mem); - break; case Primitive::kPrimChar: case Primitive::kPrimShort: - DCHECK_EQ(8u, instruction->GetVectorLength()); - __ Ld1(reg.V8H(), mem); - break; case Primitive::kPrimInt: case Primitive::kPrimFloat: - DCHECK_EQ(4u, instruction->GetVectorLength()); - __ Ld1(reg.V4S(), mem); - break; case Primitive::kPrimLong: case Primitive::kPrimDouble: - DCHECK_EQ(2u, instruction->GetVectorLength()); - __ Ld1(reg.V2D(), mem); + DCHECK_LE(2u, instruction->GetVectorLength()); + DCHECK_LE(instruction->GetVectorLength(), 16u); + __ Ldr(reg, mem); break; default: LOG(FATAL) << "Unsupported SIMD type"; @@ -780,28 +835,22 @@ void LocationsBuilderARM64::VisitVecStore(HVecStore* instruction) { void InstructionCodeGeneratorARM64::VisitVecStore(HVecStore* instruction) { Location reg_loc = Location::NoLocation(); - MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ false); + UseScratchRegisterScope temps(GetVIXLAssembler()); + MemOperand mem = CreateVecMemRegisters(instruction, ®_loc, /*is_load*/ false, &temps); VRegister reg = VRegisterFrom(reg_loc); + switch (instruction->GetPackedType()) { case Primitive::kPrimBoolean: case Primitive::kPrimByte: - DCHECK_EQ(16u, instruction->GetVectorLength()); - __ St1(reg.V16B(), mem); - break; case Primitive::kPrimChar: case Primitive::kPrimShort: - DCHECK_EQ(8u, instruction->GetVectorLength()); - __ St1(reg.V8H(), mem); - break; case Primitive::kPrimInt: case Primitive::kPrimFloat: - DCHECK_EQ(4u, instruction->GetVectorLength()); - __ St1(reg.V4S(), mem); - break; case Primitive::kPrimLong: case Primitive::kPrimDouble: - DCHECK_EQ(2u, instruction->GetVectorLength()); - __ St1(reg.V2D(), mem); + DCHECK_LE(2u, instruction->GetVectorLength()); + DCHECK_LE(instruction->GetVectorLength(), 16u); + __ Str(reg, mem); break; default: LOG(FATAL) << "Unsupported SIMD type"; diff --git a/compiler/optimizing/code_generator_vector_arm_vixl.cc b/compiler/optimizing/code_generator_vector_arm_vixl.cc index 990178b31b..53f314ec40 100644 --- a/compiler/optimizing/code_generator_vector_arm_vixl.cc +++ b/compiler/optimizing/code_generator_vector_arm_vixl.cc @@ -245,6 +245,14 @@ void InstructionCodeGeneratorARMVIXL::VisitVecUShr(HVecUShr* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } +void LocationsBuilderARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorARMVIXL::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + void LocationsBuilderARMVIXL::VisitVecLoad(HVecLoad* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } diff --git a/compiler/optimizing/code_generator_vector_mips.cc b/compiler/optimizing/code_generator_vector_mips.cc index 8ea1ca7d90..c4a32252d9 100644 --- a/compiler/optimizing/code_generator_vector_mips.cc +++ b/compiler/optimizing/code_generator_vector_mips.cc @@ -245,6 +245,14 @@ void InstructionCodeGeneratorMIPS::VisitVecUShr(HVecUShr* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } +void LocationsBuilderMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorMIPS::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + void LocationsBuilderMIPS::VisitVecLoad(HVecLoad* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } diff --git a/compiler/optimizing/code_generator_vector_mips64.cc b/compiler/optimizing/code_generator_vector_mips64.cc index a484bb4774..50b95c17cb 100644 --- a/compiler/optimizing/code_generator_vector_mips64.cc +++ b/compiler/optimizing/code_generator_vector_mips64.cc @@ -245,6 +245,14 @@ void InstructionCodeGeneratorMIPS64::VisitVecUShr(HVecUShr* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } +void LocationsBuilderMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorMIPS64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + void LocationsBuilderMIPS64::VisitVecLoad(HVecLoad* instruction) { LOG(FATAL) << "No SIMD for " << instruction->GetId(); } diff --git a/compiler/optimizing/code_generator_vector_x86.cc b/compiler/optimizing/code_generator_vector_x86.cc index a86d060821..013b092b5a 100644 --- a/compiler/optimizing/code_generator_vector_x86.cc +++ b/compiler/optimizing/code_generator_vector_x86.cc @@ -730,6 +730,14 @@ void InstructionCodeGeneratorX86::VisitVecUShr(HVecUShr* instruction) { } } +void LocationsBuilderX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorX86::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + // Helper to set up locations for vector memory operations. static void CreateVecMemLocations(ArenaAllocator* arena, HVecMemoryOperation* instruction, diff --git a/compiler/optimizing/code_generator_vector_x86_64.cc b/compiler/optimizing/code_generator_vector_x86_64.cc index 696735367e..66f19a4376 100644 --- a/compiler/optimizing/code_generator_vector_x86_64.cc +++ b/compiler/optimizing/code_generator_vector_x86_64.cc @@ -719,6 +719,14 @@ void InstructionCodeGeneratorX86_64::VisitVecUShr(HVecUShr* instruction) { } } +void LocationsBuilderX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + +void InstructionCodeGeneratorX86_64::VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instr) { + LOG(FATAL) << "No SIMD for " << instr->GetId(); +} + // Helper to set up locations for vector memory operations. static void CreateVecMemLocations(ArenaAllocator* arena, HVecMemoryOperation* instruction, diff --git a/compiler/optimizing/code_sinking.cc b/compiler/optimizing/code_sinking.cc index dc3d378e75..0b4dcd30a1 100644 --- a/compiler/optimizing/code_sinking.cc +++ b/compiler/optimizing/code_sinking.cc @@ -161,9 +161,15 @@ static HInstruction* FindIdealPosition(HInstruction* instruction, for (const HUseListNode<HInstruction*>& use : instruction->GetUses()) { HInstruction* user = use.GetUser(); if (!(filter && ShouldFilterUse(instruction, user, post_dominated))) { - finder.Update(user->IsPhi() - ? user->GetBlock()->GetPredecessors()[use.GetIndex()] - : user->GetBlock()); + HBasicBlock* block = user->GetBlock(); + if (user->IsPhi()) { + // Special case phis by taking the incoming block for regular ones, + // or the dominator for catch phis. + block = user->AsPhi()->IsCatchPhi() + ? block->GetDominator() + : block->GetPredecessors()[use.GetIndex()]; + } + finder.Update(block); } } for (const HUseListNode<HEnvironment*>& use : instruction->GetEnvUses()) { diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc index 1b2b9f80ac..e5d94c3504 100644 --- a/compiler/optimizing/graph_visualizer.cc +++ b/compiler/optimizing/graph_visualizer.cc @@ -514,6 +514,10 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor { StartAttributeStream("rounded") << std::boolalpha << hadd->IsRounded() << std::noboolalpha; } + void VisitVecMultiplyAccumulate(HVecMultiplyAccumulate* instruction) OVERRIDE { + StartAttributeStream("kind") << instruction->GetOpKind(); + } + #if defined(ART_ENABLE_CODEGEN_arm) || defined(ART_ENABLE_CODEGEN_arm64) void VisitMultiplyAccumulate(HMultiplyAccumulate* instruction) OVERRIDE { StartAttributeStream("kind") << instruction->GetOpKind(); diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc index 66948ebf8c..1f8a58cdaa 100644 --- a/compiler/optimizing/inliner.cc +++ b/compiler/optimizing/inliner.cc @@ -22,6 +22,7 @@ #include "class_linker.h" #include "constant_folding.h" #include "dead_code_elimination.h" +#include "dex/inline_method_analyser.h" #include "dex/verified_method.h" #include "dex/verification_results.h" #include "driver/compiler_driver-inl.h" @@ -37,7 +38,6 @@ #include "optimizing_compiler.h" #include "reference_type_propagation.h" #include "register_allocator_linear_scan.h" -#include "quick/inline_method_analyser.h" #include "sharpening.h" #include "ssa_builder.h" #include "ssa_phi_elimination.h" @@ -1539,6 +1539,14 @@ HInstanceFieldSet* HInliner::CreateInstanceFieldSet(uint32_t field_index, return iput; } +template <typename T> +static inline Handle<T> NewHandleIfDifferent(T* object, + Handle<T> hint, + VariableSizedHandleScope* handles) + REQUIRES_SHARED(Locks::mutator_lock_) { + return (object != hint.Get()) ? handles->NewHandle(object) : hint; +} + bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, ArtMethod* resolved_method, ReferenceTypeInfo receiver_type, @@ -1550,9 +1558,13 @@ bool HInliner::TryBuildAndInlineHelper(HInvoke* invoke_instruction, const DexFile& callee_dex_file = *resolved_method->GetDexFile(); uint32_t method_index = resolved_method->GetDexMethodIndex(); ClassLinker* class_linker = caller_compilation_unit_.GetClassLinker(); - Handle<mirror::DexCache> dex_cache(handles_->NewHandle(resolved_method->GetDexCache())); - Handle<mirror::ClassLoader> class_loader(handles_->NewHandle( - resolved_method->GetDeclaringClass()->GetClassLoader())); + Handle<mirror::DexCache> dex_cache = NewHandleIfDifferent(resolved_method->GetDexCache(), + caller_compilation_unit_.GetDexCache(), + handles_); + Handle<mirror::ClassLoader> class_loader = + NewHandleIfDifferent(resolved_method->GetDeclaringClass()->GetClassLoader(), + caller_compilation_unit_.GetClassLoader(), + handles_); DexCompilationUnit dex_compilation_unit( class_loader, diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 60790e5b84..2dcc12e294 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -16,6 +16,8 @@ #include "instruction_simplifier.h" +#include "art_method-inl.h" +#include "class_linker-inl.h" #include "escape.h" #include "intrinsics.h" #include "mirror/class-inl.h" diff --git a/compiler/optimizing/instruction_simplifier_arm.cc b/compiler/optimizing/instruction_simplifier_arm.cc index 5f5e29b024..3fc7c50bb1 100644 --- a/compiler/optimizing/instruction_simplifier_arm.cc +++ b/compiler/optimizing/instruction_simplifier_arm.cc @@ -19,6 +19,7 @@ #include "instruction_simplifier_arm.h" #include "instruction_simplifier_shared.h" #include "mirror/array-inl.h" +#include "mirror/string.h" #include "nodes.h" namespace art { diff --git a/compiler/optimizing/instruction_simplifier_arm64.cc b/compiler/optimizing/instruction_simplifier_arm64.cc index 73b7b2bd95..f16e3727c8 100644 --- a/compiler/optimizing/instruction_simplifier_arm64.cc +++ b/compiler/optimizing/instruction_simplifier_arm64.cc @@ -210,5 +210,11 @@ void InstructionSimplifierArm64Visitor::VisitXor(HXor* instruction) { } } +void InstructionSimplifierArm64Visitor::VisitVecMul(HVecMul* instruction) { + if (TryCombineVecMultiplyAccumulate(instruction, kArm64)) { + RecordSimplification(); + } +} + } // namespace arm64 } // namespace art diff --git a/compiler/optimizing/instruction_simplifier_arm64.h b/compiler/optimizing/instruction_simplifier_arm64.h index 65654f50f4..eec4e49792 100644 --- a/compiler/optimizing/instruction_simplifier_arm64.h +++ b/compiler/optimizing/instruction_simplifier_arm64.h @@ -74,6 +74,7 @@ class InstructionSimplifierArm64Visitor : public HGraphVisitor { void VisitTypeConversion(HTypeConversion* instruction) OVERRIDE; void VisitUShr(HUShr* instruction) OVERRIDE; void VisitXor(HXor* instruction) OVERRIDE; + void VisitVecMul(HVecMul* instruction) OVERRIDE; OptimizingCompilerStats* stats_; }; diff --git a/compiler/optimizing/instruction_simplifier_shared.cc b/compiler/optimizing/instruction_simplifier_shared.cc index c2b1374f62..7d1f146587 100644 --- a/compiler/optimizing/instruction_simplifier_shared.cc +++ b/compiler/optimizing/instruction_simplifier_shared.cc @@ -278,5 +278,71 @@ bool TryExtractArrayAccessAddress(HInstruction* access, return true; } +bool TryCombineVecMultiplyAccumulate(HVecMul* mul, InstructionSet isa) { + Primitive::Type type = mul->GetPackedType(); + switch (isa) { + case kArm64: + if (!(type == Primitive::kPrimByte || + type == Primitive::kPrimChar || + type == Primitive::kPrimShort || + type == Primitive::kPrimInt)) { + return false; + } + break; + default: + return false; + } + + ArenaAllocator* arena = mul->GetBlock()->GetGraph()->GetArena(); + + if (mul->HasOnlyOneNonEnvironmentUse()) { + HInstruction* use = mul->GetUses().front().GetUser(); + if (use->IsVecAdd() || use->IsVecSub()) { + // Replace code looking like + // VECMUL tmp, x, y + // VECADD/SUB dst, acc, tmp + // with + // VECMULACC dst, acc, x, y + // Note that we do not want to (unconditionally) perform the merge when the + // multiplication has multiple uses and it can be merged in all of them. + // Multiple uses could happen on the same control-flow path, and we would + // then increase the amount of work. In the future we could try to evaluate + // whether all uses are on different control-flow paths (using dominance and + // reverse-dominance information) and only perform the merge when they are. + HInstruction* accumulator = nullptr; + HVecBinaryOperation* binop = use->AsVecBinaryOperation(); + HInstruction* binop_left = binop->GetLeft(); + HInstruction* binop_right = binop->GetRight(); + // This is always true since the `HVecMul` has only one use (which is checked above). + DCHECK_NE(binop_left, binop_right); + if (binop_right == mul) { + accumulator = binop_left; + } else if (use->IsVecAdd()) { + DCHECK_EQ(binop_left, mul); + accumulator = binop_right; + } + + HInstruction::InstructionKind kind = + use->IsVecAdd() ? HInstruction::kAdd : HInstruction::kSub; + if (accumulator != nullptr) { + HVecMultiplyAccumulate* mulacc = + new (arena) HVecMultiplyAccumulate(arena, + kind, + accumulator, + mul->GetLeft(), + mul->GetRight(), + binop->GetPackedType(), + binop->GetVectorLength()); + + binop->GetBlock()->ReplaceAndRemoveInstructionWith(binop, mulacc); + DCHECK(!mul->HasUses()); + mul->GetBlock()->RemoveInstruction(mul); + return true; + } + } + } + + return false; +} } // namespace art diff --git a/compiler/optimizing/instruction_simplifier_shared.h b/compiler/optimizing/instruction_simplifier_shared.h index 83e3ffca57..2ea103a518 100644 --- a/compiler/optimizing/instruction_simplifier_shared.h +++ b/compiler/optimizing/instruction_simplifier_shared.h @@ -58,6 +58,8 @@ bool TryExtractArrayAccessAddress(HInstruction* access, HInstruction* index, size_t data_offset); +bool TryCombineVecMultiplyAccumulate(HVecMul* mul, InstructionSet isa); + } // namespace art #endif // ART_COMPILER_OPTIMIZING_INSTRUCTION_SIMPLIFIER_SHARED_H_ diff --git a/compiler/optimizing/intrinsics.cc b/compiler/optimizing/intrinsics.cc index 8df80adc9f..6236bd87ab 100644 --- a/compiler/optimizing/intrinsics.cc +++ b/compiler/optimizing/intrinsics.cc @@ -16,7 +16,8 @@ #include "intrinsics.h" -#include "art_method.h" +#include "art_field-inl.h" +#include "art_method-inl.h" #include "class_linker.h" #include "driver/compiler_driver.h" #include "driver/compiler_options.h" diff --git a/compiler/optimizing/intrinsics_arm.cc b/compiler/optimizing/intrinsics_arm.cc index 1006a776f0..750f9cc213 100644 --- a/compiler/optimizing/intrinsics_arm.cc +++ b/compiler/optimizing/intrinsics_arm.cc @@ -22,9 +22,13 @@ #include "entrypoints/quick/quick_entrypoints.h" #include "intrinsics.h" #include "intrinsics_utils.h" +#include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/reference.h" #include "mirror/string.h" -#include "thread.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "utils/arm/assembler_arm.h" namespace art { diff --git a/compiler/optimizing/intrinsics_arm64.cc b/compiler/optimizing/intrinsics_arm64.cc index 47bcb5d000..4d360158a2 100644 --- a/compiler/optimizing/intrinsics_arm64.cc +++ b/compiler/optimizing/intrinsics_arm64.cc @@ -22,9 +22,13 @@ #include "common_arm64.h" #include "entrypoints/quick/quick_entrypoints.h" #include "intrinsics.h" +#include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/reference.h" #include "mirror/string-inl.h" -#include "thread.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "utils/arm64/assembler_arm64.h" using namespace vixl::aarch64; // NOLINT(build/namespaces) diff --git a/compiler/optimizing/intrinsics_arm_vixl.cc b/compiler/optimizing/intrinsics_arm_vixl.cc index 0d933eaf82..fd8a37ae05 100644 --- a/compiler/optimizing/intrinsics_arm_vixl.cc +++ b/compiler/optimizing/intrinsics_arm_vixl.cc @@ -17,10 +17,16 @@ #include "intrinsics_arm_vixl.h" #include "arch/arm/instruction_set_features_arm.h" +#include "art_method.h" #include "code_generator_arm_vixl.h" #include "common_arm.h" #include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/reference.h" +#include "mirror/string.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "aarch32/constants-aarch32.h" diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc index ecf919bceb..8e4574774f 100644 --- a/compiler/optimizing/intrinsics_x86.cc +++ b/compiler/optimizing/intrinsics_x86.cc @@ -25,9 +25,13 @@ #include "entrypoints/quick/quick_entrypoints.h" #include "intrinsics.h" #include "intrinsics_utils.h" +#include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/reference.h" #include "mirror/string.h" -#include "thread.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "utils/x86/assembler_x86.h" #include "utils/x86/constants_x86.h" diff --git a/compiler/optimizing/intrinsics_x86_64.cc b/compiler/optimizing/intrinsics_x86_64.cc index 13956dfb8e..8ed2ad86bf 100644 --- a/compiler/optimizing/intrinsics_x86_64.cc +++ b/compiler/optimizing/intrinsics_x86_64.cc @@ -19,15 +19,19 @@ #include <limits> #include "arch/x86_64/instruction_set_features_x86_64.h" -#include "art_method-inl.h" +#include "art_method.h" #include "base/bit_utils.h" #include "code_generator_x86_64.h" #include "entrypoints/quick/quick_entrypoints.h" #include "intrinsics.h" #include "intrinsics_utils.h" +#include "lock_word.h" #include "mirror/array-inl.h" +#include "mirror/object_array-inl.h" +#include "mirror/reference.h" #include "mirror/string.h" -#include "thread.h" +#include "scoped_thread_state_change-inl.h" +#include "thread-inl.h" #include "utils/x86_64/assembler_x86_64.h" #include "utils/x86_64/constants_x86_64.h" diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc index e71fea92a9..ca953a1a7e 100644 --- a/compiler/optimizing/nodes.cc +++ b/compiler/optimizing/nodes.cc @@ -17,6 +17,8 @@ #include <cfloat> +#include "art_method-inl.h" +#include "class_linker-inl.h" #include "code_generator.h" #include "common_dominator.h" #include "ssa_builder.h" diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h index 6be237e612..8368026e92 100644 --- a/compiler/optimizing/nodes.h +++ b/compiler/optimizing/nodes.h @@ -1362,7 +1362,6 @@ class HLoopInformationOutwardIterator : public ValueObject { M(UShr, BinaryOperation) \ M(Xor, BinaryOperation) \ M(VecReplicateScalar, VecUnaryOperation) \ - M(VecSetScalars, VecUnaryOperation) \ M(VecSumReduce, VecUnaryOperation) \ M(VecCnv, VecUnaryOperation) \ M(VecNeg, VecUnaryOperation) \ @@ -1382,6 +1381,8 @@ class HLoopInformationOutwardIterator : public ValueObject { M(VecShl, VecBinaryOperation) \ M(VecShr, VecBinaryOperation) \ M(VecUShr, VecBinaryOperation) \ + M(VecSetScalars, VecOperation) \ + M(VecMultiplyAccumulate, VecOperation) \ M(VecLoad, VecMemoryOperation) \ M(VecStore, VecMemoryOperation) \ diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h index bff58d0910..fb9dfb7afa 100644 --- a/compiler/optimizing/nodes_vector.h +++ b/compiler/optimizing/nodes_vector.h @@ -116,16 +116,23 @@ class HVecOperation : public HVariableInputSizeInstruction { class HVecUnaryOperation : public HVecOperation { public: HVecUnaryOperation(ArenaAllocator* arena, + HInstruction* input, Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc) : HVecOperation(arena, packed_type, SideEffects::None(), - /*number_of_inputs*/ 1, + /* number_of_inputs */ 1, vector_length, - dex_pc) { } + dex_pc) { + SetRawInputAt(0, input); + } + + HInstruction* GetInput() const { return InputAt(0); } + DECLARE_ABSTRACT_INSTRUCTION(VecUnaryOperation); + private: DISALLOW_COPY_AND_ASSIGN(HVecUnaryOperation); }; @@ -134,16 +141,26 @@ class HVecUnaryOperation : public HVecOperation { class HVecBinaryOperation : public HVecOperation { public: HVecBinaryOperation(ArenaAllocator* arena, + HInstruction* left, + HInstruction* right, Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc) : HVecOperation(arena, packed_type, SideEffects::None(), - /*number_of_inputs*/ 2, + /* number_of_inputs */ 2, vector_length, - dex_pc) { } + dex_pc) { + SetRawInputAt(0, left); + SetRawInputAt(1, right); + } + + HInstruction* GetLeft() const { return InputAt(0); } + HInstruction* GetRight() const { return InputAt(1); } + DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation); + private: DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation); }; @@ -175,7 +192,7 @@ class HVecMemoryOperation : public HVecOperation { }; // -// Definitions of concrete vector operations in HIR. +// Definitions of concrete unary vector operations in HIR. // // Replicates the given scalar into a vector, @@ -187,32 +204,14 @@ class HVecReplicateScalar FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { - SetRawInputAt(0, scalar); + : HVecUnaryOperation(arena, scalar, packed_type, vector_length, dex_pc) { + DCHECK(!scalar->IsVecOperation()); } DECLARE_INSTRUCTION(VecReplicateScalar); private: DISALLOW_COPY_AND_ASSIGN(HVecReplicateScalar); }; -// Assigns the given scalar elements to a vector, -// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ]. -class HVecSetScalars FINAL : public HVecUnaryOperation { - HVecSetScalars(ArenaAllocator* arena, - HInstruction** scalars, // array - Primitive::Type packed_type, - size_t vector_length, - uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { - for (size_t i = 0; i < vector_length; i++) { - SetRawInputAt(0, scalars[i]); - } - } - DECLARE_INSTRUCTION(VecSetScalars); - private: - DISALLOW_COPY_AND_ASSIGN(HVecSetScalars); -}; - // Sum-reduces the given vector into a shorter vector (m < n) or scalar (m = 1), // viz. sum-reduce[ x1, .. , xn ] = [ y1, .., ym ], where yi = sum_j x_j. class HVecSumReduce FINAL : public HVecUnaryOperation { @@ -221,10 +220,9 @@ class HVecSumReduce FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, input); } // TODO: probably integral promotion @@ -244,10 +242,9 @@ class HVecCnv FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); DCHECK_NE(input->AsVecOperation()->GetPackedType(), packed_type); // actual convert - SetRawInputAt(0, input); } Primitive::Type GetInputType() const { return InputAt(0)->AsVecOperation()->GetPackedType(); } @@ -268,10 +265,9 @@ class HVecNeg FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, input); } DECLARE_INSTRUCTION(VecNeg); private: @@ -287,10 +283,9 @@ class HVecAbs FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); DCHECK_EQ(input->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, input); } DECLARE_INSTRUCTION(VecAbs); private: @@ -307,15 +302,18 @@ class HVecNot FINAL : public HVecUnaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecUnaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecUnaryOperation(arena, input, packed_type, vector_length, dex_pc) { DCHECK(input->IsVecOperation()); - SetRawInputAt(0, input); } DECLARE_INSTRUCTION(VecNot); private: DISALLOW_COPY_AND_ASSIGN(HVecNot); }; +// +// Definitions of concrete binary vector operations in HIR. +// + // Adds every component in the two vectors, // viz. [ x1, .. , xn ] + [ y1, .. , yn ] = [ x1 + y1, .. , xn + yn ]. class HVecAdd FINAL : public HVecBinaryOperation { @@ -326,12 +324,10 @@ class HVecAdd FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecAdd); private: @@ -352,14 +348,12 @@ class HVecHalvingAdd FINAL : public HVecBinaryOperation { bool is_unsigned, bool is_rounded, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc), + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc), is_unsigned_(is_unsigned), is_rounded_(is_rounded) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } bool IsUnsigned() const { return is_unsigned_; } @@ -384,12 +378,10 @@ class HVecSub FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecSub); private: @@ -406,12 +398,10 @@ class HVecMul FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecMul); private: @@ -428,12 +418,10 @@ class HVecDiv FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecDiv); private: @@ -450,12 +438,10 @@ class HVecMin FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecMin); private: @@ -472,12 +458,10 @@ class HVecMax FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); DCHECK_EQ(right->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecMax); private: @@ -494,10 +478,8 @@ class HVecAnd FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecAnd); private: @@ -514,10 +496,8 @@ class HVecAndNot FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecAndNot); private: @@ -534,10 +514,8 @@ class HVecOr FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecOr); private: @@ -554,10 +532,8 @@ class HVecXor FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation() && right->IsVecOperation()); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecXor); private: @@ -574,11 +550,9 @@ class HVecShl FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecShl); private: @@ -595,11 +569,9 @@ class HVecShr FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecShr); private: @@ -616,17 +588,96 @@ class HVecUShr FINAL : public HVecBinaryOperation { Primitive::Type packed_type, size_t vector_length, uint32_t dex_pc = kNoDexPc) - : HVecBinaryOperation(arena, packed_type, vector_length, dex_pc) { + : HVecBinaryOperation(arena, left, right, packed_type, vector_length, dex_pc) { DCHECK(left->IsVecOperation()); DCHECK_EQ(left->AsVecOperation()->GetPackedType(), packed_type); - SetRawInputAt(0, left); - SetRawInputAt(1, right); } DECLARE_INSTRUCTION(VecUShr); private: DISALLOW_COPY_AND_ASSIGN(HVecUShr); }; +// +// Definitions of concrete miscellaneous vector operations in HIR. +// + +// Assigns the given scalar elements to a vector, +// viz. set( array(x1, .., xn) ) = [ x1, .. , xn ]. +class HVecSetScalars FINAL : public HVecOperation { + HVecSetScalars(ArenaAllocator* arena, + HInstruction** scalars, // array + Primitive::Type packed_type, + size_t vector_length, + uint32_t dex_pc = kNoDexPc) + : HVecOperation(arena, + packed_type, + SideEffects::None(), + /* number_of_inputs */ vector_length, + vector_length, + dex_pc) { + for (size_t i = 0; i < vector_length; i++) { + DCHECK(!scalars[i]->IsVecOperation()); + SetRawInputAt(0, scalars[i]); + } + } + DECLARE_INSTRUCTION(VecSetScalars); + private: + DISALLOW_COPY_AND_ASSIGN(HVecSetScalars); +}; + +// Multiplies every component in the two vectors, adds the result vector to the accumulator vector. +// viz. [ acc1, .., accn ] + [ x1, .. , xn ] * [ y1, .. , yn ] = +// [ acc1 + x1 * y1, .. , accn + xn * yn ]. +class HVecMultiplyAccumulate FINAL : public HVecOperation { + public: + HVecMultiplyAccumulate(ArenaAllocator* arena, + InstructionKind op, + HInstruction* accumulator, + HInstruction* mul_left, + HInstruction* mul_right, + Primitive::Type packed_type, + size_t vector_length, + uint32_t dex_pc = kNoDexPc) + : HVecOperation(arena, + packed_type, + SideEffects::None(), + /* number_of_inputs */ 3, + vector_length, + dex_pc), + op_kind_(op) { + DCHECK(op == InstructionKind::kAdd || op == InstructionKind::kSub); + DCHECK(accumulator->IsVecOperation()); + DCHECK(mul_left->IsVecOperation() && mul_right->IsVecOperation()); + DCHECK_EQ(accumulator->AsVecOperation()->GetPackedType(), packed_type); + DCHECK_EQ(mul_left->AsVecOperation()->GetPackedType(), packed_type); + DCHECK_EQ(mul_right->AsVecOperation()->GetPackedType(), packed_type); + + SetRawInputAt(kInputAccumulatorIndex, accumulator); + SetRawInputAt(kInputMulLeftIndex, mul_left); + SetRawInputAt(kInputMulRightIndex, mul_right); + } + + static constexpr int kInputAccumulatorIndex = 0; + static constexpr int kInputMulLeftIndex = 1; + static constexpr int kInputMulRightIndex = 2; + + bool CanBeMoved() const OVERRIDE { return true; } + + bool InstructionDataEquals(const HInstruction* other) const OVERRIDE { + return op_kind_ == other->AsVecMultiplyAccumulate()->op_kind_; + } + + InstructionKind GetOpKind() const { return op_kind_; } + + DECLARE_INSTRUCTION(VecMultiplyAccumulate); + + private: + // Indicates if this is a MADD or MSUB. + const InstructionKind op_kind_; + + DISALLOW_COPY_AND_ASSIGN(HVecMultiplyAccumulate); +}; + // Loads a vector from memory, viz. load(mem, 1) // yield the vector [ mem(1), .. , mem(n) ]. class HVecLoad FINAL : public HVecMemoryOperation { @@ -640,7 +691,7 @@ class HVecLoad FINAL : public HVecMemoryOperation { : HVecMemoryOperation(arena, packed_type, SideEffects::ArrayReadOfType(packed_type), - /*number_of_inputs*/ 2, + /* number_of_inputs */ 2, vector_length, dex_pc) { SetRawInputAt(0, base); @@ -665,7 +716,7 @@ class HVecStore FINAL : public HVecMemoryOperation { : HVecMemoryOperation(arena, packed_type, SideEffects::ArrayWriteOfType(packed_type), - /*number_of_inputs*/ 3, + /* number_of_inputs */ 3, vector_length, dex_pc) { DCHECK(value->IsVecOperation()); diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc index 8aad539851..065c11eddb 100644 --- a/compiler/optimizing/optimizing_compiler.cc +++ b/compiler/optimizing/optimizing_compiler.cc @@ -98,7 +98,7 @@ #include "ssa_liveness_analysis.h" #include "ssa_phi_elimination.h" #include "utils/assembler.h" -#include "verifier/method_verifier.h" +#include "verifier/verifier_compiler_binding.h" namespace art { @@ -1041,7 +1041,7 @@ CompiledMethod* OptimizingCompiler::Compile(const DexFile::CodeItem* code_item, const VerifiedMethod* verified_method = compiler_driver->GetVerifiedMethod(&dex_file, method_idx); DCHECK(!verified_method->HasRuntimeThrow()); if (compiler_driver->IsMethodVerifiedWithoutFailures(method_idx, class_def_idx, dex_file) - || verifier::MethodVerifier::CanCompilerHandleVerificationFailure( + || verifier::CanCompilerHandleVerificationFailure( verified_method->GetEncounteredVerificationFailures())) { ArenaAllocator arena(Runtime::Current()->GetArenaPool()); CodeVectorAllocator code_allocator(&arena); diff --git a/compiler/optimizing/reference_type_propagation.cc b/compiler/optimizing/reference_type_propagation.cc index d5637b9b75..98332d35fb 100644 --- a/compiler/optimizing/reference_type_propagation.cc +++ b/compiler/optimizing/reference_type_propagation.cc @@ -16,6 +16,8 @@ #include "reference_type_propagation.h" +#include "art_field-inl.h" +#include "art_method-inl.h" #include "base/enums.h" #include "class_linker-inl.h" #include "mirror/class-inl.h" |