ARM64: Support MultiplyAccumulate for SIMD.
Test: test-art-host, test-art-target.
Change-Id: I06af8415e15352d09d176cae828163cbe99ae7a7
diff --git a/compiler/optimizing/nodes_vector.h b/compiler/optimizing/nodes_vector.h
index bff58d0..450691c 100644
--- a/compiler/optimizing/nodes_vector.h
+++ b/compiler/optimizing/nodes_vector.h
@@ -143,6 +143,10 @@
/*number_of_inputs*/ 2,
vector_length,
dex_pc) { }
+
+ HInstruction* GetLeft() const { return InputAt(0); }
+ HInstruction* GetRight() const { return InputAt(1); }
+
DECLARE_ABSTRACT_INSTRUCTION(VecBinaryOperation);
private:
DISALLOW_COPY_AND_ASSIGN(HVecBinaryOperation);
@@ -627,6 +631,59 @@
DISALLOW_COPY_AND_ASSIGN(HVecUShr);
};
+// 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 {