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(&parallel_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