194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell/*
294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * Copyright (C) 2015 The Android Open Source Project
394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell *
494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * Licensed under the Apache License, Version 2.0 (the "License");
594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * you may not use this file except in compliance with the License.
694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * You may obtain a copy of the License at
794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell *
894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell *      http://www.apache.org/licenses/LICENSE-2.0
994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell *
1094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * Unless required by applicable law or agreed to in writing, software
1194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * distributed under the License is distributed on an "AS IS" BASIS,
1294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * See the License for the specific language governing permissions and
1494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * limitations under the License.
1594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell */
1694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
170f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko#include "pc_relative_fixups_x86.h"
18f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko#include "code_generator_x86.h"
19d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik#include "intrinsics_x86.h"
2094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
2194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendellnamespace art {
2294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendellnamespace x86 {
2394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
2494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell/**
2594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell * Finds instructions that need the constant area base as an input.
2694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell */
270f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Markoclass PCRelativeHandlerVisitor : public HGraphVisitor {
2894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell public:
29d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik  PCRelativeHandlerVisitor(HGraph* graph, CodeGenerator* codegen)
30d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      : HGraphVisitor(graph),
31d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik        codegen_(down_cast<CodeGeneratorX86*>(codegen)),
32d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik        base_(nullptr) {}
3394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
34fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  void MoveBaseIfNeeded() {
35fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    if (base_ != nullptr) {
36fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      // Bring the base closer to the first use (previously, it was in the
37fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      // entry block) and relieve some pressure on the register allocator
38fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      // while avoiding recalculation of the base in a loop.
39fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      base_->MoveBeforeFirstUserAndOutOfLoops();
40fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    }
41fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  }
42fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko
4394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell private:
4494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitAdd(HAdd* add) OVERRIDE {
4594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    BinaryFP(add);
4694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
4794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
4894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitSub(HSub* sub) OVERRIDE {
4994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    BinaryFP(sub);
5094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
5194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
5294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitMul(HMul* mul) OVERRIDE {
5394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    BinaryFP(mul);
5494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
5594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
5694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitDiv(HDiv* div) OVERRIDE {
5794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    BinaryFP(div);
5894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
5994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
602f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitCompare(HCompare* compare) OVERRIDE {
612f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(compare);
622f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
632f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
6494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitReturn(HReturn* ret) OVERRIDE {
6594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HConstant* value = ret->InputAt(0)->AsConstant();
6694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    if ((value != nullptr && Primitive::IsFloatingPointType(value->GetType()))) {
6794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      ReplaceInput(ret, value, 0, true);
6894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    }
6994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
7094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
7194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE {
7294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HandleInvoke(invoke);
7394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
7494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
7594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitInvokeVirtual(HInvokeVirtual* invoke) OVERRIDE {
7694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HandleInvoke(invoke);
7794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
7894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
7994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitInvokeInterface(HInvokeInterface* invoke) OVERRIDE {
8094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HandleInvoke(invoke);
8194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
8294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
83cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  void VisitLoadString(HLoadString* load_string) OVERRIDE {
84cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    HLoadString::LoadKind load_kind = load_string->GetLoadKind();
85cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    if (load_kind == HLoadString::LoadKind::kBootImageLinkTimePcRelative ||
86cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko        load_kind == HLoadString::LoadKind::kDexCachePcRelative) {
87cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      InitializePCRelativeBasePointer();
88cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko      load_string->AddSpecialInput(base_);
89cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko    }
90cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko  }
91cac5a7e871f1f346b317894359ad06fa7bd67fbaVladimir Marko
9294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void BinaryFP(HBinaryOperation* bin) {
9394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HConstant* rhs = bin->InputAt(1)->AsConstant();
942f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    if (rhs != nullptr && Primitive::IsFloatingPointType(rhs->GetType())) {
9594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      ReplaceInput(bin, rhs, 1, false);
9694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    }
9794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
9894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
992f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitEqual(HEqual* cond) OVERRIDE {
1002f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1012f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1022f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1032f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitNotEqual(HNotEqual* cond) OVERRIDE {
1042f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1052f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1062f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1072f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitLessThan(HLessThan* cond) OVERRIDE {
1082f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1092f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1102f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1112f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitLessThanOrEqual(HLessThanOrEqual* cond) OVERRIDE {
1122f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1132f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1142f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1152f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitGreaterThan(HGreaterThan* cond) OVERRIDE {
1162f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1172f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1182f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1192f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitGreaterThanOrEqual(HGreaterThanOrEqual* cond) OVERRIDE {
1202f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    BinaryFP(cond);
1212f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1222f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1232f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  void VisitNeg(HNeg* neg) OVERRIDE {
1242f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    if (Primitive::IsFloatingPointType(neg->GetType())) {
1252f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      // We need to replace the HNeg with a HX86FPNeg in order to address the constant area.
1262f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      InitializePCRelativeBasePointer();
1272f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      HGraph* graph = GetGraph();
1282f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      HBasicBlock* block = neg->GetBlock();
1292f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      HX86FPNeg* x86_fp_neg = new (graph->GetArena()) HX86FPNeg(
1302f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          neg->GetType(),
1312f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          neg->InputAt(0),
1322f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          base_,
1332f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          neg->GetDexPc());
1342f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      block->ReplaceAndRemoveInstructionWith(neg, x86_fp_neg);
1352f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    }
1362f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell  }
1372f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
13894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void VisitPackedSwitch(HPackedSwitch* switch_insn) OVERRIDE {
139f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko    if (switch_insn->GetNumEntries() <=
140f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko        InstructionCodeGeneratorX86::kPackedSwitchJumpTableThreshold) {
141f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko      return;
142f3e0ee27f46aa6434b900ab33f12cd3157578234Vladimir Marko    }
14394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    // We need to replace the HPackedSwitch with a HX86PackedSwitch in order to
14494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    // address the constant area.
145fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    InitializePCRelativeBasePointer();
14694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HGraph* graph = GetGraph();
14794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HBasicBlock* block = switch_insn->GetBlock();
14894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HX86PackedSwitch* x86_switch = new (graph->GetArena()) HX86PackedSwitch(
14994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        switch_insn->GetStartValue(),
15094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        switch_insn->GetNumEntries(),
15194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        switch_insn->InputAt(0),
15294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        base_,
15394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        switch_insn->GetDexPc());
15494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    block->ReplaceAndRemoveInstructionWith(switch_insn, x86_switch);
15594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
15694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
157fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  void InitializePCRelativeBasePointer() {
15894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    // Ensure we only initialize the pointer once.
15994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    if (base_ != nullptr) {
16094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      return;
16194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    }
162fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    // Insert the base at the start of the entry block, move it to a better
163fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    // position later in MoveBaseIfNeeded().
164fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    base_ = new (GetGraph()->GetArena()) HX86ComputeBaseMethodAddress();
165fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    HBasicBlock* entry_block = GetGraph()->GetEntryBlock();
166fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    entry_block->InsertInstructionBefore(base_, entry_block->GetFirstInstruction());
16794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    DCHECK(base_ != nullptr);
16894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
16994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
17094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void ReplaceInput(HInstruction* insn, HConstant* value, int input_index, bool materialize) {
171fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko    InitializePCRelativeBasePointer();
17294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    HX86LoadFromConstantTable* load_constant =
173b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil        new (GetGraph()->GetArena()) HX86LoadFromConstantTable(base_, value);
174b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil    if (!materialize) {
175b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil      load_constant->MarkEmittedAtUseSite();
176b3e773eea39a156b3eacf915ba84e3af1a5c14faDavid Brazdil    }
1770f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    insn->GetBlock()->InsertInstructionBefore(load_constant, insn);
17894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    insn->ReplaceInput(load_constant, input_index);
17994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
18094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
18194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  void HandleInvoke(HInvoke* invoke) {
1820f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    // If this is an invoke-static/-direct with PC-relative dex cache array
1830f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    // addressing, we need the PC-relative address base.
1840f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    HInvokeStaticOrDirect* invoke_static_or_direct = invoke->AsInvokeStaticOrDirect();
1852f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    // We can't add a pointer to the constant area if we already have a current
1862f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    // method pointer. This may arise when sharpening doesn't remove the current
1872f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    // method pointer from the invoke.
1882f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    if (invoke_static_or_direct != nullptr &&
1892f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell        invoke_static_or_direct->HasCurrentMethodInput()) {
1902f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      DCHECK(!invoke_static_or_direct->HasPcRelativeDexCache());
1912f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      return;
1922f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    }
1932f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
1942f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    bool base_added = false;
195d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik    if (invoke_static_or_direct != nullptr &&
196d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik        invoke_static_or_direct->HasPcRelativeDexCache() &&
197d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik        !WillHaveCallFreeIntrinsicsCodeGen(invoke)) {
198fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko      InitializePCRelativeBasePointer();
1990f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko      // Add the extra parameter base_.
200c53c0797a78a89d637e4230503cc1feb27e855a8Vladimir Marko      invoke_static_or_direct->AddSpecialInput(base_);
2012f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      base_added = true;
2020f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Marko    }
2032f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
20494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    // Ensure that we can load FP arguments from the constant area.
20594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    for (size_t i = 0, e = invoke->InputCount(); i < e; i++) {
20694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      HConstant* input = invoke->InputAt(i)->AsConstant();
20794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      if (input != nullptr && Primitive::IsFloatingPointType(input->GetType())) {
20894991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell        ReplaceInput(invoke, input, i, true);
20994991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell      }
21094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell    }
2112f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell
2122f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    // These intrinsics need the constant area.
2132f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    switch (invoke->GetIntrinsic()) {
2142f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathAbsDouble:
2152f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathAbsFloat:
2162f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathMaxDoubleDouble:
2172f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathMaxFloatFloat:
2182f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathMinDoubleDouble:
2192f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      case Intrinsics::kMathMinFloatFloat:
2202f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell        if (!base_added) {
2212f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          DCHECK(invoke_static_or_direct != nullptr);
2222f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          DCHECK(!invoke_static_or_direct->HasCurrentMethodInput());
2232f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          InitializePCRelativeBasePointer();
2242f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell          invoke_static_or_direct->AddSpecialInput(base_);
2252f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell        }
2262f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell        break;
2272f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell      default:
2282f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell        break;
2292f10a5fb8c236a6786928f0323bd312c3ee9a4ccMark P Mendell    }
23094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  }
23194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
232d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik  bool WillHaveCallFreeIntrinsicsCodeGen(HInvoke* invoke) {
233d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik    if (invoke->GetIntrinsic() != Intrinsics::kNone) {
234d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // This invoke may have intrinsic code generation defined. However, we must
235d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // now also determine if this code generation is truly there and call-free
236d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // (not unimplemented, no bail on instruction features, or call on slow path).
237d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // This is done by actually calling the locations builder on the instruction
238d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // and clearing out the locations once result is known. We assume this
239d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      // call only has creating locations as side effects!
240d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      IntrinsicLocationsBuilderX86 builder(codegen_);
241d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      bool success = builder.TryDispatch(invoke) && !invoke->GetLocations()->CanCall();
242d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      invoke->SetLocations(nullptr);
243d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik      return success;
244d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik    }
245d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik    return false;
246d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik  }
247d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik
248d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik  CodeGeneratorX86* codegen_;
249d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik
25094991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  // The generated HX86ComputeBaseMethodAddress in the entry block needed as an
25194991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  // input to the HX86LoadFromConstantTable instructions.
25294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  HX86ComputeBaseMethodAddress* base_;
25394991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell};
25494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
2550f7dca4ca0be8d2f8776794d35edf8b51b5bc997Vladimir Markovoid PcRelativeFixups::Run() {
25615bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  if (graph_->HasIrreducibleLoops()) {
25715bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // Do not run this optimization, as irreducible loops do not work with an instruction
25815bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    // that can be live-in at the irreducible loop header.
25915bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray    return;
26015bd22849ee6a1ffb3fb3630f686c2870bdf1bbcNicolas Geoffray  }
261d1c4045fb4d4703642f3f79985727b9a12cf5c49Aart Bik  PCRelativeHandlerVisitor visitor(graph_, codegen_);
26294991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell  visitor.VisitInsertionOrder();
263fb337ea53d1e6fe68b24217a9ea95e9f544ef697Vladimir Marko  visitor.MoveBaseIfNeeded();
26494991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell}
26594991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell
26694991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell}  // namespace x86
26794991077ed66e3c329e8bf6f594ad6d30992b092Mark Mendell}  // namespace art
268