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