intrinsics.h revision 762869dee6e0eadab5be1c606792d6693bbabf4e
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 3471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe// Recognize intrinsics from HInvoke nodes. 3571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicsRecognizer : public HOptimization { 3671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 37762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray IntrinsicsRecognizer(HGraph* graph, OptimizingCompilerStats* stats) 38762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray : HOptimization(graph, kIntrinsicsRecognizerPassName, stats) {} 3971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Run() OVERRIDE; 4171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 427c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe static constexpr const char* kIntrinsicsRecognizerPassName = "intrinsics_recognition"; 437c3952f423b8213083d60596a5f0bf4237ca3f7bAndreas Gampe 4471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 4571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicsRecognizer); 4671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 4771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 4871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampeclass IntrinsicVisitor : public ValueObject { 4971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe public: 5071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual ~IntrinsicVisitor() {} 5171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Dispatch logic. 5371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 5471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe void Dispatch(HInvoke* invoke) { 5571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe switch (invoke->GetIntrinsic()) { 5671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe case Intrinsics::kNone: 5771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 58762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 595d75afe333f57546786686d9bee16b52f1bbe971Aart Bik case Intrinsics::k ## Name: \ 605d75afe333f57546786686d9bee16b52f1bbe971Aart Bik Visit ## Name(invoke); \ 6171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe return; 6271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 6371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 6471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 6571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 6671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 6771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Do not put a default case. That way the compiler will complain if we missed a case. 6871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 6971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 7171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe // Define visitor methods. 7271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 73762869dee6e0eadab5be1c606792d6693bbabf4eNicolas Geoffray#define OPTIMIZING_INTRINSICS(Name, ...) \ 7471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe virtual void Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 7571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe } 7671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#include "intrinsics_list.h" 7771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas GampeINTRINSICS_LIST(OPTIMIZING_INTRINSICS) 7871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef INTRINSICS_LIST 7971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#undef OPTIMIZING_INTRINSICS 8071fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 81ec525fc30848189051b888da53ba051bc0878b78Roland Levillain static void MoveArguments(HInvoke* invoke, 82ec525fc30848189051b888da53ba051bc0878b78Roland Levillain CodeGenerator* codegen, 83ec525fc30848189051b888da53ba051bc0878b78Roland Levillain InvokeDexCallingConventionVisitor* calling_convention_visitor) { 84ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (kIsDebugBuild && invoke->IsInvokeStaticOrDirect()) { 85ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect(); 8658282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // Explicit clinit checks triggered by static invokes must have been 8758282f4510961317b8d5a364a6f740a78926716fDavid Brazdil // pruned by art::PrepareForRegisterAllocation. 8858282f4510961317b8d5a364a6f740a78926716fDavid Brazdil DCHECK(!invoke_static_or_direct->IsStaticWithExplicitClinitCheck()); 89ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 90ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 91ec525fc30848189051b888da53ba051bc0878b78Roland Levillain if (invoke->GetNumberOfArguments() == 0) { 92ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // No argument to move. 93ec525fc30848189051b888da53ba051bc0878b78Roland Levillain return; 94ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 95ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 96ec525fc30848189051b888da53ba051bc0878b78Roland Levillain LocationSummary* locations = invoke->GetLocations(); 97ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 98ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // We're moving potentially two or more locations to locations that could overlap, so we need 99ec525fc30848189051b888da53ba051bc0878b78Roland Levillain // a parallel move resolver. 100ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HParallelMove parallel_move(codegen->GetGraph()->GetArena()); 101ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 102ec525fc30848189051b888da53ba051bc0878b78Roland Levillain for (size_t i = 0; i < invoke->GetNumberOfArguments(); i++) { 103ec525fc30848189051b888da53ba051bc0878b78Roland Levillain HInstruction* input = invoke->InputAt(i); 104ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location cc_loc = calling_convention_visitor->GetNextLocation(input->GetType()); 105ec525fc30848189051b888da53ba051bc0878b78Roland Levillain Location actual_loc = locations->InAt(i); 106ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 107ec525fc30848189051b888da53ba051bc0878b78Roland Levillain parallel_move.AddMove(actual_loc, cc_loc, input->GetType(), nullptr); 108ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 109ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 110ec525fc30848189051b888da53ba051bc0878b78Roland Levillain codegen->GetMoveResolver()->EmitNativeCode(¶llel_move); 111ec525fc30848189051b888da53ba051bc0878b78Roland Levillain } 112ec525fc30848189051b888da53ba051bc0878b78Roland Levillain 11371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe protected: 11471fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe IntrinsicVisitor() {} 11571fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 11671fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe private: 11771fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe DISALLOW_COPY_AND_ASSIGN(IntrinsicVisitor); 11871fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe}; 11971fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 120a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define GENERIC_OPTIMIZATION(name, bit) \ 12112be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 12212be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 12312be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 12412be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 125ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillainstatic constexpr size_t k##name = bit 126a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 127a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass IntrinsicOptimizations : public ValueObject { 128a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 129ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain explicit IntrinsicOptimizations(HInvoke* invoke) 130ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain : value_(invoke->GetIntrinsicOptimizations()) {} 13112be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit IntrinsicOptimizations(const HInvoke& invoke) 13212be662a580278edc37a52087255d87935660869Nicolas Geoffray : value_(invoke.GetIntrinsicOptimizations()) {} 133a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 134a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray static constexpr int kNumberOfGenericOptimizations = 2; 135a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedDexCache, 0); 136a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray GENERIC_OPTIMIZATION(DoesNotNeedEnvironment, 1); 137a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 138a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray protected: 139a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray bool IsBitSet(uint32_t bit) const { 140ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 141a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray return (*value_ & (1 << bit)) != 0u; 142a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 143a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 144a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray void SetBit(uint32_t bit) { 145ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain DCHECK_LT(bit, sizeof(uint32_t) * kBitsPerByte); 146ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain *(const_cast<uint32_t* const>(value_)) |= (1 << bit); 147a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray } 148a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 149a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 150ebea3d2cce6aa34216502bb6b83d155d4c92e4ffRoland Levillain const uint32_t* const value_; 151a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 152a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(IntrinsicOptimizations); 153a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 154a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 155a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef GENERIC_OPTIMIZATION 156a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 157a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#define INTRINSIC_OPTIMIZATION(name, bit) \ 15812be662a580278edc37a52087255d87935660869Nicolas Geoffraypublic: \ 15912be662a580278edc37a52087255d87935660869Nicolas Geoffrayvoid Set##name() { SetBit(k##name); } \ 16012be662a580278edc37a52087255d87935660869Nicolas Geoffraybool Get##name() const { return IsBitSet(k##name); } \ 16112be662a580278edc37a52087255d87935660869Nicolas Geoffrayprivate: \ 162fba39972d99701c80bf3beb7451aca508d67593cChih-Hung Hsiehstatic constexpr size_t k##name = (bit) + kNumberOfGenericOptimizations 163a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 164a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffrayclass StringEqualsOptimizations : public IntrinsicOptimizations { 165a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray public: 16612be662a580278edc37a52087255d87935660869Nicolas Geoffray explicit StringEqualsOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 167a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 168a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentNotNull, 0); 169a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray INTRINSIC_OPTIMIZATION(ArgumentIsString, 1); 170a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 171a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray private: 172a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray DISALLOW_COPY_AND_ASSIGN(StringEqualsOptimizations); 173a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray}; 174a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 175ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffrayclass SystemArrayCopyOptimizations : public IntrinsicOptimizations { 176ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray public: 177ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray explicit SystemArrayCopyOptimizations(HInvoke* invoke) : IntrinsicOptimizations(invoke) {} 178ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 179ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNotNull, 0); 180ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNotNull, 1); 181ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsSource, 2); 182ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsSourceLength, 3); 183ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(CountIsDestinationLength, 4); 184ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DoesNotNeedTypeCheck, 5); 185ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsTypedObjectArray, 6); 186ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsNonPrimitiveArray, 7); 187ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(DestinationIsPrimitiveArray, 8); 188ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsNonPrimitiveArray, 9); 189ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray INTRINSIC_OPTIMIZATION(SourceIsPrimitiveArray, 10); 190ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 191ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray private: 192ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray DISALLOW_COPY_AND_ASSIGN(SystemArrayCopyOptimizations); 193ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray}; 194ee3cf0731d0ef0787bc2947c8e3ca432b513956bNicolas Geoffray 195a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray#undef INTRISIC_OPTIMIZATION 196a83a54d7f2322060f08480f8aabac5eb07268912Nicolas Geoffray 1972f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 1982f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Macros for use in the intrinsics code generators. 1992f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// 2002f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2012f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines an unimplemented intrinsic: that is, a method call that is recognized as an 2022f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// intrinsic to exploit e.g. no side-effects or exceptions, but otherwise not handled 2032f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// by this architecture-specific intrinsics code generator. Eventually it is implemented 2042f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// as a true method call. 2052f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNIMPLEMENTED_INTRINSIC(Arch, Name) \ 2062f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2072f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2082f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke ATTRIBUTE_UNUSED) { \ 2092f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 2102f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 2112f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// Defines a list of unreached intrinsics: that is, method calls that are recognized as 2122f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// an intrinsic, and then always converted into HIR instructions before they reach any 2132f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik// architecture-specific intrinsics code generator. 2142f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNREACHABLE_INTRINSIC(Arch, Name) \ 2152f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicLocationsBuilder ## Arch::Visit ## Name(HInvoke* invoke) { \ 2162f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2172f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2182f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} \ 2192f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bikvoid IntrinsicCodeGenerator ## Arch::Visit ## Name(HInvoke* invoke) { \ 2202f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik LOG(FATAL) << "Unreachable: intrinsic " << invoke->GetIntrinsic() \ 2212f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik << " should have been converted to HIR"; \ 2222f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik} 2232f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik#define UNREACHABLE_INTRINSICS(Arch) \ 2242f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, FloatFloatToIntBits) \ 2252f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, DoubleDoubleToLongBits) \ 2262f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, FloatIsNaN) \ 2272f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, DoubleIsNaN) \ 2282f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, IntegerRotateLeft) \ 2292f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, LongRotateLeft) \ 2302f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, IntegerRotateRight) \ 2312f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, LongRotateRight) \ 2322f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, IntegerCompare) \ 2332f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, LongCompare) \ 2342f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart BikUNREACHABLE_INTRINSIC(Arch, IntegerSignum) \ 2351193259cb37c9763a111825aa04718a409d07145Aart BikUNREACHABLE_INTRINSIC(Arch, LongSignum) \ 23687f3fcbd0db352157fc59148e94647ef21b73bceVladimir MarkoUNREACHABLE_INTRINSIC(Arch, StringCharAt) \ 237dce016eab87302f02b0bd903dd2cd86ae512df2dVladimir MarkoUNREACHABLE_INTRINSIC(Arch, StringIsEmpty) \ 238dce016eab87302f02b0bd903dd2cd86ae512df2dVladimir MarkoUNREACHABLE_INTRINSIC(Arch, StringLength) \ 2391193259cb37c9763a111825aa04718a409d07145Aart BikUNREACHABLE_INTRINSIC(Arch, UnsafeLoadFence) \ 2401193259cb37c9763a111825aa04718a409d07145Aart BikUNREACHABLE_INTRINSIC(Arch, UnsafeStoreFence) \ 2411193259cb37c9763a111825aa04718a409d07145Aart BikUNREACHABLE_INTRINSIC(Arch, UnsafeFullFence) 2422f9fcc999fab4ba6cd86c30e664325b47b9618e5Aart Bik 24368c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markotemplate <typename IntrinsicLocationsBuilder, typename Codegenerator> 24468c981fad87720fae9c799b240141ce3c12cd5bfVladimir Markobool IsCallFreeIntrinsic(HInvoke* invoke, Codegenerator* codegen) { 24568c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko if (invoke->GetIntrinsic() != Intrinsics::kNone) { 24668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This invoke may have intrinsic code generation defined. However, we must 24768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // now also determine if this code generation is truly there and call-free 24868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // (not unimplemented, no bail on instruction features, or call on slow path). 24968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // This is done by actually calling the locations builder on the instruction 25068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // and clearing out the locations once result is known. We assume this 25168c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // call only has creating locations as side effects! 25268c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko // TODO: Avoid wasting Arena memory. 25368c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko IntrinsicLocationsBuilder builder(codegen); 25468c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall(); 25568c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko invoke->SetLocations(nullptr); 25668c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return success; 25768c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko } 25868c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko return false; 25968c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko} 26068c981fad87720fae9c799b240141ce3c12cd5bfVladimir Marko 26171fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe} // namespace art 26271fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe 26371fb52fee246b7d511f520febbd73dc7a9bbca79Andreas Gampe#endif // ART_COMPILER_OPTIMIZING_INTRINSICS_H_ 264