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