intrinsics.h revision ee3cf0731d0ef0787bc2947c8e3ca432b513956b
171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe/* 271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Copyright (C) 2015 The Android Open Source Project 371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Licensed under the Apache License, Version 2.0 (the "License"); 571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * you may not use this file except in compliance with the License. 671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * You may obtain a copy of the License at 771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * http://www.apache.org/licenses/LICENSE-2.0 971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * 1071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * Unless required by applicable law or agreed to in writing, software 1171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * distributed under the License is distributed on an "AS IS" BASIS, 1271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * See the License for the specific language governing permissions and 1471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe * limitations under the License. 1571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe */ 1671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 1771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#ifndef ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 1871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#define ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 1971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 20ec525fc30848189051b888da53ba051bc0878b78Roland Levillain#include "code_generator.h" 2171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "nodes.h" 2271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "optimization.h" 23ec525fc30848189051b888da53ba051bc0878b78Roland Levillain#include "parallel_move_resolver.h" 2471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 2571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampenamespace art { 2671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 2771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass CompilerDriver; 2871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass DexFile; 2971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 3071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe// Recognize intrinsics from HInvoke nodes. 3171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicsRecognizer : public HOptimization { 3271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 33d5111bf05fc0a9974280a80eeb43db6d5227a81eNicolas Geoffray IntrinsicsRecognizer(HGraph* graph, CompilerDriver* driver) 3469ba7b7112c2277ac225615b37e6df74c055740dDavid Brazdil : HOptimization(graph, kIntrinsicsRecognizerPassName), 35d5111bf05fc0a9974280a80eeb43db6d5227a81eNicolas Geoffray driver_(driver) {} 3671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 3771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Run() OVERRIDE; 3871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 397c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition"; 407c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe 4171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 4271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe CompilerDriver* driver_; 4371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer); 4571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 4671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicVisitor : public ValueObject { 4871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 4971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual ~IntrinsicVisitor() {} 5071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Dispatch logic. 5271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Dispatch(HInvoke* invoke) { 5471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (invoke->GetIntrinsic()) { 5571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 5671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 5757b81ecbe74138992dd447251e94ed06cd5eb802agicsaki#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ 5871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::k ## Name: \ 5971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe Visit ## Name(invoke); \ 6071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 6171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 6271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 6371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 6471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 6571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 6671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Do not put a default case. That way the compiler will complain if we missed a case. 6771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 6871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 6971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Define visitor methods. 7171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7257b81ecbe74138992dd447251e94ed06cd5eb802agicsaki#define OPTIMIZING_INTRINSICS(Name, IsStatic, NeedsEnvironment) \ 7371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 7471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 7671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 7771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 7871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 7971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 80ec525fc30848189051b888da53ba051bc0878b78Roland Levillain static void MoveArguments(HInvoke* invoke, 81ec525fc30848189051b888da53ba051bc0878b78Roland Levillain CodeGenerator* codegen, 82ec525fc30848189051b888da53ba051bc0878b78Roland Levillain InvokeDexCallingConventionVisitor* calling_convention_visitor) { 83ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect()) { 84ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect(); 85ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // When we do not run baseline, explicit clinit checks triggered by static 86ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // invokes must have been pruned by art::PrepareForRegisterAllocation. 87ec525fc30848189051b888da53ba051bc0878b78Roland Levillain DCHECK(codegen->IsBaseline() || !invoke_static_or_direct->IsStaticWithExplicitClinitCheck()); 88ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 89ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 90ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (invoke->GetNumberOfArguments() == 0) { 91ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // No argument to move. 92ec525fc30848189051b888da53ba051bc0878b78Roland Levillain return; 93ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 94ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 95ec525fc30848189051b888da53ba051bc0878b78Roland Levillain LocationSummary* locations = invoke->GetLocations(); 96ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 97ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // We're moving potentially two or more locations to locations that could overlap, so we need 98ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // a parallel move resolver. 99ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HParallelMove parallel_move(codegen->GetGraph()->GetArena()); 100ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 101ec525fc30848189051b888da53ba051bc0878b78Roland Levillain for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) { 102ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInstruction* input = invoke->InputAt(i); 103ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location cc_loc = calling_convention_visitor->GetNextLocation(input->GetType()); 104ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location actual_loc = locations->InAt(i); 105ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 106ec525fc30848189051b888da53ba051bc0878b78Roland Levillain parallel_move.AddMove(actual_loc, cc_loc, input->GetType(), nullptr); 107ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 108ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 109ec525fc30848189051b888da53ba051bc0878b78Roland Levillain codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); 110ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 111ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 11271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe protected: 11371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe IntrinsicVisitor() {} 11471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 11571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 11671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); 11771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 11871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 119a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define GENERIC_OPTIMIZATION(name, bit) \ 12012be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 12112be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 12212be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 12312be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 12412be662a580278edc37a52087255d87935660869Nicolas Geoffraystatic constexpr int k##name = bit 125a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 126a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass IntrinsicOptimizations : public ValueObject { 127a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 12812be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit IntrinsicOptimizations(HInvoke* invoke) : value_(invoke->GetIntrinsicOptimizations()) {} 12912be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit IntrinsicOptimizations(const HInvoke& invoke) 13012be662a580278edc37a52087255d87935660869Nicolas Geoffray : value_(invoke.GetIntrinsicOptimizations()) {} 131a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 132a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray static constexpr int kNumberOfGenericOptimizations = 2; 133a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedDexCache, 0); 134a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 1); 135a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 136a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray protected: 137a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray bool IsBitSet(uint32_t bit) const { 138a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray return (*value_ & (1 << bit)) != 0u; 139a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 140a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 141a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray void SetBit(uint32_t bit) { 142a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray *(const_cast<uint32_t*>(value_)) |= (1 << bit); 143a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 144a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 145a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 146a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray const uint32_t *value_; 147a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 148a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(IntrinsicOptimizations); 149a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 150a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 151a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef GENERIC_OPTIMIZATION 152a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 153a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define INTRINSIC_OPTIMIZATION(name, bit) \ 15412be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 15512be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 15612be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 15712be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 15812be662a580278edc37a52087255d87935660869Nicolas Geoffraystatic constexpr int k##name = bit + kNumberOfGenericOptimizations 159a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 160a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass StringEqualsOptimizations : public IntrinsicOptimizations { 161a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 16212be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit StringEqualsOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 163a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 164a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); 165a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); 166a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 167a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 168a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); 169a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 170a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 171ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayclass SystemArrayCopyOptimizations : public IntrinsicOptimizations { 172ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray public: 173ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray explicit SystemArrayCopyOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 174ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 175ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNotNull, 0); 176ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNotNull, 1); 177ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsSource, 2); 178ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsSourceLength, 3); 179ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsDestinationLength, 4); 180ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DoesNotNeedTypeCheck, 5); 181ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsTypedObjectArray, 6); 182ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNonPrimitiveArray, 7); 183ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsPrimitiveArray, 8); 184ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNonPrimitiveArray, 9); 185ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsPrimitiveArray, 10); 186ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 187ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray private: 188ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SystemArrayCopyOptimizations); 189ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray}; 190ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 191a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef INTRISIC_OPTIMIZATION 192a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 19371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} // namespace art 19471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 19571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 196