intrinsics.h revision ca6fff898afcb62491458ae8bcd428bfb3043da1
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 30a3ffea207c7f7a5a1a6467ba154c0c88f118aa34Anton Kirilov// Positive floating-point infinities. 31a3ffea207c7f7a5a1a6467ba154c0c88f118aa34Anton Kirilovstatic constexpr uint32_t kPositiveInfinityFloat = 0x7f800000U; 32a3ffea207c7f7a5a1a6467ba154c0c88f118aa34Anton Kirilovstatic constexpr uint64_t kPositiveInfinityDouble = UINT64_C(0x7ff0000000000000); 33a3ffea207c7f7a5a1a6467ba154c0c88f118aa34Anton Kirilov 34c032e74b57d31861b6bb55500016ebb5476eb142xueliang.zhongstatic constexpr uint32_t kNanFloat = 0x7fc00000U; 35c032e74b57d31861b6bb55500016ebb5476eb142xueliang.zhongstatic constexpr uint64_t kNanDouble = 0x7ff8000000000000; 36c032e74b57d31861b6bb55500016ebb5476eb142xueliang.zhong 3771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe// Recognize intrinsics from HInvoke nodes. 3871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicsRecognizer : public HOptimization { 3971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 40762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray IntrinsicsRecognizer(HGraph* graph, OptimizingCompilerStats* stats) 41762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray : HOptimization(graph, kIntrinsicsRecognizerPassName, stats) {} 4271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Run() OVERRIDE; 4471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 457c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition"; 467c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe 4771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 4871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer); 4971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 5071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicVisitor : public ValueObject { 5271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 5371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual ~IntrinsicVisitor() {} 5471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Dispatch logic. 5671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Dispatch(HInvoke* invoke) { 5871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (invoke->GetIntrinsic()) { 5971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 6071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 61762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 625d75afe333f57546786686d9bee16b52f1bbe971Aart Bik case Intrinsics::k ## Name: \ 635d75afe333f57546786686d9bee16b52f1bbe971Aart Bik Visit ## Name(invoke); \ 6471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 6571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 668cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 6771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 6871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 6971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Do not put a default case. That way the compiler will complain if we missed a case. 7171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Define visitor methods. 7571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 76762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 7771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 7871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 808cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 8171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 8271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 8371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 84ec525fc30848189051b888da53ba051bc0878b78Roland Levillain static void MoveArguments(HInvoke* invoke, 85ec525fc30848189051b888da53ba051bc0878b78Roland Levillain CodeGenerator* codegen, 86ec525fc30848189051b888da53ba051bc0878b78Roland Levillain InvokeDexCallingConventionVisitor* calling_convention_visitor) { 87ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect()) { 88ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect(); 8958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // Explicit clinit checks triggered by static invokes must have been 9058282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // pruned by art::PrepareForRegisterAllocation. 9158282f4510961317b8d5a364a6f740a78926716fDavid Brazdil DCHECK(!invoke_static_or_direct->IsStaticWithExplicitClinitCheck()); 92ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 93ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 94ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (invoke->GetNumberOfArguments() == 0) { 95ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // No argument to move. 96ec525fc30848189051b888da53ba051bc0878b78Roland Levillain return; 97ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 98ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 99ec525fc30848189051b888da53ba051bc0878b78Roland Levillain LocationSummary* locations = invoke->GetLocations(); 100ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 101ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // We're moving potentially two or more locations to locations that could overlap, so we need 102ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // a parallel move resolver. 103ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko HParallelMove parallel_move(codegen->GetGraph()->GetAllocator()); 104ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 105ec525fc30848189051b888da53ba051bc0878b78Roland Levillain for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) { 106ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInstruction* input = invoke->InputAt(i); 107ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location cc_loc = calling_convention_visitor->GetNextLocation(input->GetType()); 108ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location actual_loc = locations->InAt(i); 109ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 110ec525fc30848189051b888da53ba051bc0878b78Roland Levillain parallel_move.AddMove(actual_loc, cc_loc, input->GetType(), nullptr); 111ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 112ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 113ec525fc30848189051b888da53ba051bc0878b78Roland Levillain codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); 114ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 115ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 116331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray static void ComputeIntegerValueOfLocations(HInvoke* invoke, 117331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray CodeGenerator* codegen, 118331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray Location return_location, 119331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray Location first_argument_location); 120331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 121331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Temporary data structure for holding Integer.valueOf useful data. We only 122331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // use it if the mirror::Class* are in the boot image, so it is fine to keep raw 123331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // mirror::Class pointers in this structure. 124331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray struct IntegerValueOfInfo { 125331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray IntegerValueOfInfo() 126331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray : integer_cache(nullptr), 127331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray integer(nullptr), 128331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray cache(nullptr), 129331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray low(0), 130331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray high(0), 131331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray value_offset(0) {} 132331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 133331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The java.lang.IntegerCache class. 134331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::Class* integer_cache; 135331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The java.lang.Integer class. 136331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::Class* integer; 137331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#cache. 138331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::ObjectArray<mirror::Object>* cache; 139331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#low. 140331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t low; 141331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#high. 142331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t high; 143331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The offset of java.lang.Integer.value. 144331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t value_offset; 145331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray }; 146331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 147331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray static IntegerValueOfInfo ComputeIntegerValueOfInfo(); 148331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 14971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe protected: 15071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe IntrinsicVisitor() {} 15171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 15271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 15371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); 15471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 15571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 156a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define GENERIC_OPTIMIZATION(name, bit) \ 15712be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 15812be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 15912be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 16012be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 161ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillainstatic constexpr size_t k##name = bit 162a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 163a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass IntrinsicOptimizations : public ValueObject { 164a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 165ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain explicit IntrinsicOptimizations(HInvoke* invoke) 166ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain : value_(invoke->GetIntrinsicOptimizations()) {} 16712be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit IntrinsicOptimizations(const HInvoke& invoke) 16812be662a580278edc37a52087255d87935660869Nicolas Geoffray : value_(invoke.GetIntrinsicOptimizations()) {} 169a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 170a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray static constexpr int kNumberOfGenericOptimizations = 2; 171a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedDexCache, 0); 172a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 1); 173a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 174a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray protected: 175a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray bool IsBitSet(uint32_t bit) const { 176ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 177a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray return (*value_ & (1 << bit)) != 0u; 178a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 179a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 180a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray void SetBit(uint32_t bit) { 181ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 182ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain *(const_cast<uint32_t* const>(value_)) |= (1 << bit); 183a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 184a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 185a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 186ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain const uint32_t* const value_; 187a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 188a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(IntrinsicOptimizations); 189a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 190a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 191a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef GENERIC_OPTIMIZATION 192a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 193a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define INTRINSIC_OPTIMIZATION(name, bit) \ 19412be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 19512be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 19612be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 19712be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 198fba39972d99701c80bf3beb7451aca508d67593cChih-Hung Hsiehstatic constexpr size_t k##name = (bit) + kNumberOfGenericOptimizations 199a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 200a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass StringEqualsOptimizations : public IntrinsicOptimizations { 201a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 20212be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit StringEqualsOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 203a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 204a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); 205a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); 206a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 207a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 208a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); 209a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 210a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 211ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayclass SystemArrayCopyOptimizations : public IntrinsicOptimizations { 212ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray public: 213ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray explicit SystemArrayCopyOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 214ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 215ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNotNull, 0); 216ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNotNull, 1); 217ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsSource, 2); 218ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsSourceLength, 3); 219ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsDestinationLength, 4); 220ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DoesNotNeedTypeCheck, 5); 221ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsTypedObjectArray, 6); 222ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNonPrimitiveArray, 7); 223ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsPrimitiveArray, 8); 224ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNonPrimitiveArray, 9); 225ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsPrimitiveArray, 10); 226ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 227ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray private: 228ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SystemArrayCopyOptimizations); 229ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray}; 230ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 231a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef INTRISIC_OPTIMIZATION 232a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 2332f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 2342f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Macros for use in the intrinsics code generators. 2352f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 2362f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2372f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines an unimplemented intrinsic: that is, a method call that is recognized as an 2382f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// intrinsic to exploit e.g. no side-effects or exceptions, but otherwise not handled 2392f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// by this architecture-specific intrinsics code generator. Eventually it is implemented 2402f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// as a true method call. 2412f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNIMPLEMENTED_INTRINSIC(Arch, Name) \ 2422f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2432f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2442f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2452f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 2462f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2472f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines a list of unreached intrinsics: that is, method calls that are recognized as 2482f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// an intrinsic, and then always converted into HIR instructions before they reach any 2492f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// architecture-specific intrinsics code generator. 2502f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNREACHABLE_INTRINSIC(Arch, Name) \ 2512f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke) { \ 2522f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2532f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2542f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2552f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ 2562f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2572f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2582f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 2594a4610a438ff2b836f6fe07839a0689ce618863aOrion Hodson#define UNREACHABLE_INTRINSICS(Arch) \ 2604a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ 2614a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ 2624a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ 2634a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ 2644a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ 2654a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ 2664a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ 2674a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ 2684a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ 2694a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, LongCompare) \ 2704a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ 2714a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, LongSignum) \ 2724a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, StringCharAt) \ 2734a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ 2744a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, StringLength) \ 2754a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ 2764a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ 2774a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) \ 2784a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleFullFence) \ 2794a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence) \ 2804a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence) \ 2814a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence) \ 2824a4610a438ff2b836f6fe07839a0689ce618863aOrion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence) 2832f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 28468c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markotemplate <typename IntrinsicLocationsBuilder, typename Codegenerator> 28568c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markobool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { 28668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko if (invoke->GetIntrinsic() != Intrinsics::kNone) { 28768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This invoke may have intrinsic code generation defined. However, we must 28868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // now also determine if this code generation is truly there and call-free 28968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // (not unimplemented, no bail on instruction features, or call on slow path). 29068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This is done by actually calling the locations builder on the instruction 29168c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // and clearing out the locations once result is known. We assume this 29268c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // call only has creating locations as side effects! 29368c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // TODO: Avoid wasting Arena memory. 29468c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko IntrinsicLocationsBuilder builder(codegen); 29568c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall(); 29668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko invoke->SetLocations(nullptr); 29768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return success; 29868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko } 29968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return false; 30068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko} 30168c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko 30271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} // namespace art 30371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 30471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 305