diff options
| author | 2017-04-05 20:22:42 +0000 | |
|---|---|---|
| committer | 2017-04-05 20:22:44 +0000 | |
| commit | a2078418d152ca2c5b76b24d0a4aa96bf6cf0c0e (patch) | |
| tree | 7440c9a83a7cd13b58593b13656a10b6987ad911 /compiler/optimizing/loop_optimization.cc | |
| parent | b27febced608c5c4944137cbd9193febe7436afe (diff) | |
| parent | 6daebeba6ceab4e7dff5a3d65929eeac9a334004 (diff) | |
Merge "Implemented ABS vectorization."
Diffstat (limited to 'compiler/optimizing/loop_optimization.cc')
| -rw-r--r-- | compiler/optimizing/loop_optimization.cc | 74 | 
1 files changed, 66 insertions, 8 deletions
| diff --git a/compiler/optimizing/loop_optimization.cc b/compiler/optimizing/loop_optimization.cc index 42ed04dfa3..b5f46a6807 100644 --- a/compiler/optimizing/loop_optimization.cc +++ b/compiler/optimizing/loop_optimization.cc @@ -735,8 +735,32 @@ bool HLoopOptimization::VectorizeUse(LoopNode* node,        return true;      }    } else if (instruction->IsInvokeStaticOrDirect()) { -    // TODO: coming soon. -    return false; +    // Accept particular intrinsics. +    HInvokeStaticOrDirect* invoke = instruction->AsInvokeStaticOrDirect(); +    switch (invoke->GetIntrinsic()) { +      case Intrinsics::kMathAbsInt: +      case Intrinsics::kMathAbsLong: +      case Intrinsics::kMathAbsFloat: +      case Intrinsics::kMathAbsDouble: { +        // Deal with vector restrictions. +        if (HasVectorRestrictions(restrictions, kNoAbs) || +            HasVectorRestrictions(restrictions, kNoHiBits)) { +          // TODO: we can do better for some hibits cases. +          return false; +        } +        // Accept ABS(x) for vectorizable operand. +        HInstruction* opa = instruction->InputAt(0); +        if (VectorizeUse(node, opa, generate_code, type, restrictions)) { +          if (generate_code) { +            GenerateVecOp(instruction, vector_map_->Get(opa), nullptr, type); +          } +          return true; +        } +        return false; +      } +      default: +        return false; +    }  // switch    }    return false;  } @@ -754,11 +778,11 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric        switch (type) {          case Primitive::kPrimBoolean:          case Primitive::kPrimByte: -          *restrictions |= kNoDiv; +          *restrictions |= kNoDiv | kNoAbs;            return TrySetVectorLength(8);          case Primitive::kPrimChar:          case Primitive::kPrimShort: -          *restrictions |= kNoDiv; +          *restrictions |= kNoDiv | kNoAbs;            return TrySetVectorLength(4);          case Primitive::kPrimInt:            *restrictions |= kNoDiv; @@ -775,17 +799,17 @@ bool HLoopOptimization::TrySetVectorType(Primitive::Type type, uint64_t* restric          switch (type) {            case Primitive::kPrimBoolean:            case Primitive::kPrimByte: -            *restrictions |= kNoMul | kNoDiv | kNoShift; +            *restrictions |= kNoMul | kNoDiv | kNoShift | kNoAbs;              return TrySetVectorLength(16);            case Primitive::kPrimChar:            case Primitive::kPrimShort: -            *restrictions |= kNoDiv; +            *restrictions |= kNoDiv | kNoAbs;              return TrySetVectorLength(8);            case Primitive::kPrimInt:              *restrictions |= kNoDiv;              return TrySetVectorLength(4);            case Primitive::kPrimLong: -            *restrictions |= kNoMul | kNoDiv | kNoShr; +            *restrictions |= kNoMul | kNoDiv | kNoShr | kNoAbs;              return TrySetVectorLength(2);            case Primitive::kPrimFloat:              return TrySetVectorLength(4); @@ -956,7 +980,41 @@ void HLoopOptimization::GenerateVecOp(HInstruction* org,            new (global_allocator_) HVecUShr(global_allocator_, opa, opb, type, vector_length_),            new (global_allocator_) HUShr(type, opa, opb));      case HInstruction::kInvokeStaticOrDirect: { -      // TODO: coming soon. +      HInvokeStaticOrDirect* invoke = org->AsInvokeStaticOrDirect(); +      if (vector_mode_ == kVector) { +        switch (invoke->GetIntrinsic()) { +          case Intrinsics::kMathAbsInt: +          case Intrinsics::kMathAbsLong: +          case Intrinsics::kMathAbsFloat: +          case Intrinsics::kMathAbsDouble: +            DCHECK(opb == nullptr); +            vector = new (global_allocator_) HVecAbs(global_allocator_, opa, type, vector_length_); +            break; +          default: +            LOG(FATAL) << "Unsupported SIMD intrinsic"; +            UNREACHABLE(); +        }  // switch invoke +      } else { +        // In scalar code, simply clone the method invoke, and replace its operands +        // with the corresponding new scalar instructions in the loop. +        DCHECK(vector_mode_ == kSequential); +        HInvokeStaticOrDirect* new_invoke = new (global_allocator_) HInvokeStaticOrDirect( +            global_allocator_, +            invoke->GetNumberOfArguments(), +            invoke->GetType(), +            invoke->GetDexPc(), +            invoke->GetDexMethodIndex(), +            invoke->GetResolvedMethod(), +            invoke->GetDispatchInfo(), +            invoke->GetInvokeType(), +            invoke->GetTargetMethod(), +            invoke->GetClinitCheckRequirement()); +        HInputsRef inputs = invoke->GetInputs(); +        for (size_t index = 0; index < inputs.size(); ++index) { +          new_invoke->SetArgumentAt(index, vector_map_->Get(inputs[index])); +        } +        vector = new_invoke; +      }        break;      }      default: |