diff options
author | 2017-07-20 16:07:36 +0200 | |
---|---|---|
committer | 2017-08-14 10:16:34 +0200 | |
commit | bc5460b850a0fa2d8dcf6c8d36b0eb86f8fe46a8 (patch) | |
tree | 0db1314987cd0f24c7294c4ad540c7f28e2739d9 /compiler/optimizing/instruction_simplifier.cc | |
parent | c1bb1cd339b2ebea9c4770fb4d61bacd7d77746f (diff) |
MIPS: Support MultiplyAccumulate for SIMD.
Moved support for multiply accumulate from arm64-specific to
general instruction simplification.
Also extended 550-checker-multiply-accumulate test.
Test: test-art-host, test-art-target
Change-Id: If113f0f0d5cb48e8a76273c919cfa2f49fce667d
Diffstat (limited to 'compiler/optimizing/instruction_simplifier.cc')
-rw-r--r-- | compiler/optimizing/instruction_simplifier.cc | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/compiler/optimizing/instruction_simplifier.cc b/compiler/optimizing/instruction_simplifier.cc index 5c79511bab..f2a829fa56 100644 --- a/compiler/optimizing/instruction_simplifier.cc +++ b/compiler/optimizing/instruction_simplifier.cc @@ -59,6 +59,7 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { bool TryDeMorganNegationFactoring(HBinaryOperation* op); bool TryHandleAssociativeAndCommutativeOperation(HBinaryOperation* instruction); bool TrySubtractionChainSimplification(HBinaryOperation* instruction); + bool TryCombineVecMultiplyAccumulate(HVecMul* mul); void VisitShift(HBinaryOperation* shift); @@ -98,6 +99,7 @@ class InstructionSimplifierVisitor : public HGraphDelegateVisitor { void VisitInstanceOf(HInstanceOf* instruction) OVERRIDE; void VisitInvoke(HInvoke* invoke) OVERRIDE; void VisitDeoptimize(HDeoptimize* deoptimize) OVERRIDE; + void VisitVecMul(HVecMul* instruction) OVERRIDE; bool CanEnsureNotNullAt(HInstruction* instr, HInstruction* at) const; @@ -243,6 +245,84 @@ bool InstructionSimplifierVisitor::TryDeMorganNegationFactoring(HBinaryOperation return false; } +bool InstructionSimplifierVisitor::TryCombineVecMultiplyAccumulate(HVecMul* mul) { + Primitive::Type type = mul->GetPackedType(); + InstructionSet isa = codegen_->GetInstructionSet(); + switch (isa) { + case kArm64: + if (!(type == Primitive::kPrimByte || + type == Primitive::kPrimChar || + type == Primitive::kPrimShort || + type == Primitive::kPrimInt)) { + return false; + } + break; + case kMips: + case kMips64: + if (!(type == Primitive::kPrimByte || + type == Primitive::kPrimChar || + type == Primitive::kPrimShort || + type == Primitive::kPrimInt || + type == Primitive::kPrimLong)) { + 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; +} + void InstructionSimplifierVisitor::VisitShift(HBinaryOperation* instruction) { DCHECK(instruction->IsShl() || instruction->IsShr() || instruction->IsUShr()); HInstruction* shift_amount = instruction->GetRight(); @@ -2301,4 +2381,10 @@ bool InstructionSimplifierVisitor::TrySubtractionChainSimplification( return true; } +void InstructionSimplifierVisitor::VisitVecMul(HVecMul* instruction) { + if (TryCombineVecMultiplyAccumulate(instruction)) { + RecordSimplification(); + } +} + } // namespace art |