summaryrefslogtreecommitdiff
path: root/compiler/optimizing
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/optimizing')
-rw-r--r--compiler/optimizing/code_generator.cc5
-rw-r--r--compiler/optimizing/code_generator_arm64.h4
-rw-r--r--compiler/optimizing/code_generator_vector_arm.cc8
-rw-r--r--compiler/optimizing/code_generator_vector_arm64.cc119
-rw-r--r--compiler/optimizing/code_generator_vector_arm_vixl.cc8
-rw-r--r--compiler/optimizing/code_generator_vector_mips.cc8
-rw-r--r--compiler/optimizing/code_generator_vector_mips64.cc8
-rw-r--r--compiler/optimizing/code_generator_vector_x86.cc8
-rw-r--r--compiler/optimizing/code_generator_vector_x86_64.cc8
-rw-r--r--compiler/optimizing/code_sinking.cc12
-rw-r--r--compiler/optimizing/graph_visualizer.cc4
-rw-r--r--compiler/optimizing/inliner.cc20
-rw-r--r--compiler/optimizing/instruction_simplifier.cc2
-rw-r--r--compiler/optimizing/instruction_simplifier_arm.cc1
-rw-r--r--compiler/optimizing/instruction_simplifier_arm64.cc6
-rw-r--r--compiler/optimizing/instruction_simplifier_arm64.h1
-rw-r--r--compiler/optimizing/instruction_simplifier_shared.cc66
-rw-r--r--compiler/optimizing/instruction_simplifier_shared.h2
-rw-r--r--compiler/optimizing/intrinsics.cc3
-rw-r--r--compiler/optimizing/intrinsics_arm.cc6
-rw-r--r--compiler/optimizing/intrinsics_arm64.cc6
-rw-r--r--compiler/optimizing/intrinsics_arm_vixl.cc6
-rw-r--r--compiler/optimizing/intrinsics_x86.cc6
-rw-r--r--compiler/optimizing/intrinsics_x86_64.cc8
-rw-r--r--compiler/optimizing/nodes.cc2
-rw-r--r--compiler/optimizing/nodes.h3
-rw-r--r--compiler/optimizing/nodes_vector.h209
-rw-r--r--compiler/optimizing/optimizing_compiler.cc4
-rw-r--r--compiler/optimizing/reference_type_propagation.cc2
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, &reg_loc, /*is_load*/ true);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, &reg_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, &reg_loc, /*is_load*/ false);
+ UseScratchRegisterScope temps(GetVIXLAssembler());
+ MemOperand mem = CreateVecMemRegisters(instruction, &reg_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"