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: 402ca10eb3f47ef3c2535c137853f7a63d10bb908bAart Bik IntrinsicsRecognizer(HGraph* graph, 412ca10eb3f47ef3c2535c137853f7a63d10bb908bAart Bik OptimizingCompilerStats* stats, 422ca10eb3f47ef3c2535c137853f7a63d10bb908bAart Bik const char* name = kIntrinsicsRecognizerPassName) 432ca10eb3f47ef3c2535c137853f7a63d10bb908bAart Bik : HOptimization(graph, name, stats) {} 4471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Run() OVERRIDE; 4671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 47f0010dd946b17490d2f792d845ea4f304a0bea28Aart Bik // Static helper that recognizes intrinsic call. Returns true on success. 48f0010dd946b17490d2f792d845ea4f304a0bea28Aart Bik // If it fails due to invoke type mismatch, wrong_invoke_type is set. 494c71d00f3bee9ae7a3e14ca6629e9e0cb4e25fd8Orion Hodson // Useful to recognize intrinsics on individual calls outside this full pass. 506b1aebe3612a6e87d7d1847ccca0d7a213cd22a2Mingyao Yang static bool Recognize(HInvoke* invoke, ArtMethod* method, /*out*/ bool* wrong_invoke_type) 514c71d00f3bee9ae7a3e14ca6629e9e0cb4e25fd8Orion Hodson REQUIRES_SHARED(Locks::mutator_lock_); 52f0010dd946b17490d2f792d845ea4f304a0bea28Aart Bik 537c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition"; 547c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe 5571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 5671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer); 5771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 5871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicVisitor : public ValueObject { 6071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 6171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual ~IntrinsicVisitor() {} 6271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 6371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Dispatch logic. 6471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 6571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Dispatch(HInvoke* invoke) { 6671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (invoke->GetIntrinsic()) { 6771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 6871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 69762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 705d75afe333f57546786686d9bee16b52f1bbe971Aart Bik case Intrinsics::k ## Name: \ 715d75afe333f57546786686d9bee16b52f1bbe971Aart Bik Visit ## Name(invoke); \ 7271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 7371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 748cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 7571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 7671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 7771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Do not put a default case. That way the compiler will complain if we missed a case. 7971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 8071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 8171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 8271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Define visitor methods. 8371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 84762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 8571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 8671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 8771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 888cf9cb386cd9286d67e879f1ee501ec00d72a4e1Andreas Gampe INTRINSICS_LIST(OPTIMIZING_INTRINSICS) 8971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 9071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 9171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 92ec525fc30848189051b888da53ba051bc0878b78Roland Levillain static void MoveArguments(HInvoke* invoke, 93ec525fc30848189051b888da53ba051bc0878b78Roland Levillain CodeGenerator* codegen, 94ec525fc30848189051b888da53ba051bc0878b78Roland Levillain InvokeDexCallingConventionVisitor* calling_convention_visitor) { 95ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect()) { 96ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect(); 9758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // Explicit clinit checks triggered by static invokes must have been 9858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // pruned by art::PrepareForRegisterAllocation. 9958282f4510961317b8d5a364a6f740a78926716fDavid Brazdil DCHECK(!invoke_static_or_direct->IsStaticWithExplicitClinitCheck()); 100ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 101ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 102ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (invoke->GetNumberOfArguments() == 0) { 103ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // No argument to move. 104ec525fc30848189051b888da53ba051bc0878b78Roland Levillain return; 105ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 106ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 107ec525fc30848189051b888da53ba051bc0878b78Roland Levillain LocationSummary* locations = invoke->GetLocations(); 108ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 109ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // We're moving potentially two or more locations to locations that could overlap, so we need 110ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // a parallel move resolver. 111ca6fff898afcb62491458ae8bcd428bfb3043da1Vladimir Marko HParallelMove parallel_move(codegen->GetGraph()->GetAllocator()); 112ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 113ec525fc30848189051b888da53ba051bc0878b78Roland Levillain for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) { 114ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInstruction* input = invoke->InputAt(i); 115ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location cc_loc = calling_convention_visitor->GetNextLocation(input->GetType()); 116ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location actual_loc = locations->InAt(i); 117ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 118ec525fc30848189051b888da53ba051bc0878b78Roland Levillain parallel_move.AddMove(actual_loc, cc_loc, input->GetType(), nullptr); 119ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 120ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 121ec525fc30848189051b888da53ba051bc0878b78Roland Levillain codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); 122ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 123ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 124331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray static void ComputeIntegerValueOfLocations(HInvoke* invoke, 125331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray CodeGenerator* codegen, 126331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray Location return_location, 127331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray Location first_argument_location); 128331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 129331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Temporary data structure for holding Integer.valueOf useful data. We only 130331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // use it if the mirror::Class* are in the boot image, so it is fine to keep raw 131331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // mirror::Class pointers in this structure. 132331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray struct IntegerValueOfInfo { 133331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray IntegerValueOfInfo() 134331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray : integer_cache(nullptr), 135331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray integer(nullptr), 136331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray cache(nullptr), 137331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray low(0), 138331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray high(0), 139331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray value_offset(0) {} 140331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 141331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The java.lang.IntegerCache class. 142331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::Class* integer_cache; 143331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The java.lang.Integer class. 144331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::Class* integer; 145331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#cache. 146331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray mirror::ObjectArray<mirror::Object>* cache; 147331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#low. 148331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t low; 149331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // Value of java.lang.IntegerCache#high. 150331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t high; 151331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray // The offset of java.lang.Integer.value. 152331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray int32_t value_offset; 153331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray }; 154331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 155331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray static IntegerValueOfInfo ComputeIntegerValueOfInfo(); 156331605a7ba842573b3876e14c933175382b923c8Nicolas Geoffray 15771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe protected: 15871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe IntrinsicVisitor() {} 15971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 16071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 16171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); 16271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 16371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 164a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define GENERIC_OPTIMIZATION(name, bit) \ 16512be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 16612be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 16712be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 16812be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 169ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillainstatic constexpr size_t k##name = bit 170a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 171a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass IntrinsicOptimizations : public ValueObject { 172a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 173ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain explicit IntrinsicOptimizations(HInvoke* invoke) 174ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain : value_(invoke->GetIntrinsicOptimizations()) {} 17512be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit IntrinsicOptimizations(const HInvoke& invoke) 17612be662a580278edc37a52087255d87935660869Nicolas Geoffray : value_(invoke.GetIntrinsicOptimizations()) {} 177a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 178a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray static constexpr int kNumberOfGenericOptimizations = 2; 179a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedDexCache, 0); 180a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 1); 181a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 182a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray protected: 183a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray bool IsBitSet(uint32_t bit) const { 184ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 185a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray return (*value_ & (1 << bit)) != 0u; 186a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 187a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 188a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray void SetBit(uint32_t bit) { 189ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 190ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain *(const_cast<uint32_t* const>(value_)) |= (1 << bit); 191a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 192a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 193a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 194ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain const uint32_t* const value_; 195a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 196a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(IntrinsicOptimizations); 197a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 198a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 199a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef GENERIC_OPTIMIZATION 200a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 201a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define INTRINSIC_OPTIMIZATION(name, bit) \ 20212be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 20312be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 20412be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 20512be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 206fba39972d99701c80bf3beb7451aca508d67593cChih-Hung Hsiehstatic constexpr size_t k##name = (bit) + kNumberOfGenericOptimizations 207a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 208a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass StringEqualsOptimizations : public IntrinsicOptimizations { 209a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 21012be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit StringEqualsOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 211a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 212a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); 213a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); 214da283050a1a3ddbb7cefae3f36e8c8c1a6acedb7Vladimir Marko INTRINSIC_OPTIMIZATION(NoReadBarrierForStringClass, 2); 215a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 216a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 217a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); 218a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 219a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 220ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayclass SystemArrayCopyOptimizations : public IntrinsicOptimizations { 221ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray public: 222ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray explicit SystemArrayCopyOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 223ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 224ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNotNull, 0); 225ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNotNull, 1); 226ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsSource, 2); 227ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsSourceLength, 3); 228ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsDestinationLength, 4); 229ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DoesNotNeedTypeCheck, 5); 230ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsTypedObjectArray, 6); 231ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNonPrimitiveArray, 7); 232ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsPrimitiveArray, 8); 233ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNonPrimitiveArray, 9); 234ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsPrimitiveArray, 10); 235ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 236ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray private: 237ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SystemArrayCopyOptimizations); 238ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray}; 239ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 240a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef INTRISIC_OPTIMIZATION 241a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 2422f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 2432f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Macros for use in the intrinsics code generators. 2442f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 2452f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2462f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines an unimplemented intrinsic: that is, a method call that is recognized as an 2472f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// intrinsic to exploit e.g. no side-effects or exceptions, but otherwise not handled 2482f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// by this architecture-specific intrinsics code generator. Eventually it is implemented 2492f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// as a true method call. 2502f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNIMPLEMENTED_INTRINSIC(Arch, Name) \ 2512f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2522f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2532f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2542f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 2552f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2562f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines a list of unreached intrinsics: that is, method calls that are recognized as 2572f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// an intrinsic, and then always converted into HIR instructions before they reach any 2582f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// architecture-specific intrinsics code generator. 2592f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNREACHABLE_INTRINSIC(Arch, Name) \ 2602f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke) { \ 2612f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2622f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2632f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2642f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ 2652f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2662f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2672f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 26843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion Hodson#define UNREACHABLE_INTRINSICS(Arch) \ 26943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ 27043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ 27143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ 27243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ 27343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ 27443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ 27543f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ 27643f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ 27743f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ 27843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, LongCompare) \ 27943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ 28043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, LongSignum) \ 28143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, StringCharAt) \ 28243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ 28343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, StringLength) \ 28443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ 28543f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ 28643f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) \ 28743f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleFullFence) \ 28843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleAcquireFence) \ 28943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleReleaseFence) \ 29043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleLoadLoadFence) \ 29143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleStoreStoreFence) \ 29243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, MethodHandleInvokeExact) \ 29343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, MethodHandleInvoke) \ 29443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchange) \ 29543f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchangeAcquire) \ 29643f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndExchangeRelease) \ 29743f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleCompareAndSet) \ 29843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGet) \ 29943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAcquire) \ 30043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAdd) \ 30143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAddAcquire) \ 30243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndAddRelease) \ 30343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAnd) \ 30443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAndAcquire) \ 30543f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseAndRelease) \ 30643f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOr) \ 30743f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOrAcquire) \ 30843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseOrRelease) \ 30943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXor) \ 31043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXorAcquire) \ 31143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndBitwiseXorRelease) \ 31243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSet) \ 31343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSetAcquire) \ 31443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetAndSetRelease) \ 31543f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetOpaque) \ 31643f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleGetVolatile) \ 31743f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleSet) \ 31843f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleSetOpaque) \ 31943f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleSetRelease) \ 32043f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleSetVolatile) \ 32143f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSet) \ 32243f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetAcquire) \ 32343f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetPlain) \ 32443f0cdbe3281cd5c9a33d5472b1538e5617f6691Orion HodsonUNREACHABLE_INTRINSIC(Arch, VarHandleWeakCompareAndSetRelease) 3252f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 32668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markotemplate <typename IntrinsicLocationsBuilder, typename Codegenerator> 32768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markobool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { 32868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko if (invoke->GetIntrinsic() != Intrinsics::kNone) { 32968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This invoke may have intrinsic code generation defined. However, we must 33068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // now also determine if this code generation is truly there and call-free 33168c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // (not unimplemented, no bail on instruction features, or call on slow path). 33268c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This is done by actually calling the locations builder on the instruction 33368c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // and clearing out the locations once result is known. We assume this 33468c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // call only has creating locations as side effects! 33568c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // TODO: Avoid wasting Arena memory. 33668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko IntrinsicLocationsBuilder builder(codegen); 33768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall(); 33868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko invoke->SetLocations(nullptr); 33968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return success; 34068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko } 34168c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return false; 34268c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko} 34368c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko 34471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} // namespace art 34571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 34671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 347