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