487 lines · cpp
1//===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// This file implements the targeting of the Machinelegalizer class for ARM.10/// \todo This should be generated by TableGen.11//===----------------------------------------------------------------------===//12 13#include "ARMLegalizerInfo.h"14#include "ARMCallLowering.h"15#include "ARMSubtarget.h"16#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"17#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"18#include "llvm/CodeGen/LowLevelTypeUtils.h"19#include "llvm/CodeGen/MachineRegisterInfo.h"20#include "llvm/CodeGen/TargetOpcodes.h"21#include "llvm/CodeGen/ValueTypes.h"22#include "llvm/IR/DerivedTypes.h"23#include "llvm/IR/Type.h"24 25using namespace llvm;26using namespace LegalizeActions;27 28static bool AEABI(const ARMSubtarget &ST) {29 return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();30}31 32ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) : ST(ST) {33 using namespace TargetOpcode;34 35 const LLT p0 = LLT::pointer(0, 32);36 37 const LLT s1 = LLT::scalar(1);38 const LLT s8 = LLT::scalar(8);39 const LLT s16 = LLT::scalar(16);40 const LLT s32 = LLT::scalar(32);41 const LLT s64 = LLT::scalar(64);42 43 auto &LegacyInfo = getLegacyLegalizerInfo();44 if (ST.isThumb1Only()) {45 // Thumb1 is not supported yet.46 LegacyInfo.computeTables();47 verify(*ST.getInstrInfo());48 return;49 }50 51 getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})52 .legalForCartesianProduct({s8, s16, s32}, {s1, s8, s16});53 54 getActionDefinitionsBuilder(G_SEXT_INREG).lower();55 56 getActionDefinitionsBuilder({G_MUL, G_AND, G_OR, G_XOR})57 .legalFor({s32})58 .clampScalar(0, s32, s32);59 60 if (ST.hasNEON())61 getActionDefinitionsBuilder({G_ADD, G_SUB})62 .legalFor({s32, s64})63 .minScalar(0, s32);64 else65 getActionDefinitionsBuilder({G_ADD, G_SUB})66 .legalFor({s32})67 .minScalar(0, s32);68 69 getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL})70 .legalFor({{s32, s32}})71 .minScalar(0, s32)72 .clampScalar(1, s32, s32);73 74 bool HasHWDivide = (!ST.isThumb() && ST.hasDivideInARMMode()) ||75 (ST.isThumb() && ST.hasDivideInThumbMode());76 if (HasHWDivide)77 getActionDefinitionsBuilder({G_SDIV, G_UDIV})78 .legalFor({s32})79 .clampScalar(0, s32, s32);80 else81 getActionDefinitionsBuilder({G_SDIV, G_UDIV})82 .libcallFor({s32})83 .clampScalar(0, s32, s32);84 85 auto &REMBuilder =86 getActionDefinitionsBuilder({G_SREM, G_UREM}).minScalar(0, s32);87 if (HasHWDivide)88 REMBuilder.lowerFor({s32});89 else if (AEABI(ST))90 REMBuilder.customFor({s32});91 else92 REMBuilder.libcallFor({s32});93 94 getActionDefinitionsBuilder(G_INTTOPTR)95 .legalFor({{p0, s32}})96 .minScalar(1, s32);97 getActionDefinitionsBuilder(G_PTRTOINT)98 .legalFor({{s32, p0}})99 .minScalar(0, s32);100 101 getActionDefinitionsBuilder(G_CONSTANT)102 .customFor({s32, p0})103 .clampScalar(0, s32, s32);104 105 getActionDefinitionsBuilder(G_CONSTANT_POOL).legalFor({p0});106 107 getActionDefinitionsBuilder(G_ICMP)108 .legalForCartesianProduct({s1}, {s32, p0})109 .minScalar(1, s32);110 111 getActionDefinitionsBuilder(G_SELECT)112 .legalForCartesianProduct({s32, p0}, {s1})113 .minScalar(0, s32);114 115 // We're keeping these builders around because we'll want to add support for116 // floating point to them.117 auto &LoadStoreBuilder = getActionDefinitionsBuilder({G_LOAD, G_STORE})118 .legalForTypesWithMemDesc({{s8, p0, s8, 8},119 {s16, p0, s16, 8},120 {s32, p0, s32, 8},121 {p0, p0, p0, 8}})122 .unsupportedIfMemSizeNotPow2();123 124 getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});125 getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});126 127 auto &PhiBuilder =128 getActionDefinitionsBuilder(G_PHI)129 .legalFor({s32, p0})130 .minScalar(0, s32);131 132 getActionDefinitionsBuilder(G_PTR_ADD)133 .legalFor({{p0, s32}})134 .minScalar(1, s32);135 136 getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});137 138 if (!ST.useSoftFloat() && ST.hasVFP2Base()) {139 getActionDefinitionsBuilder(140 {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})141 .legalFor({s32, s64});142 143 LoadStoreBuilder144 .legalForTypesWithMemDesc({{s64, p0, s64, 32}})145 .maxScalar(0, s32);146 PhiBuilder.legalFor({s64});147 148 getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct({s1},149 {s32, s64});150 151 getActionDefinitionsBuilder(G_MERGE_VALUES).legalFor({{s64, s32}});152 getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});153 154 getActionDefinitionsBuilder(G_FPEXT).legalFor({{s64, s32}});155 getActionDefinitionsBuilder(G_FPTRUNC).legalFor({{s32, s64}});156 157 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})158 .legalForCartesianProduct({s32}, {s32, s64});159 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})160 .legalForCartesianProduct({s32, s64}, {s32});161 162 getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_GET_FPMODE})163 .legalFor({s32});164 getActionDefinitionsBuilder(G_RESET_FPENV).alwaysLegal();165 getActionDefinitionsBuilder(G_SET_FPMODE).customFor({s32});166 getActionDefinitionsBuilder(G_RESET_FPMODE).custom();167 } else {168 getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})169 .libcallFor({s32, s64});170 171 LoadStoreBuilder.maxScalar(0, s32);172 173 getActionDefinitionsBuilder(G_FNEG).lowerFor({s32, s64});174 175 getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});176 177 getActionDefinitionsBuilder(G_FCMP).customForCartesianProduct({s1},178 {s32, s64});179 180 if (AEABI(ST))181 setFCmpLibcallsAEABI();182 else183 setFCmpLibcallsGNU();184 185 getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s64, s32}});186 getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s32, s64}});187 188 getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})189 .libcallForCartesianProduct({s32}, {s32, s64});190 getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})191 .libcallForCartesianProduct({s32, s64}, {s32});192 193 getActionDefinitionsBuilder({G_GET_FPENV, G_SET_FPENV, G_RESET_FPENV})194 .libcall();195 getActionDefinitionsBuilder({G_GET_FPMODE, G_SET_FPMODE, G_RESET_FPMODE})196 .libcall();197 }198 199 // Just expand whatever loads and stores are left.200 LoadStoreBuilder.lower();201 202 if (!ST.useSoftFloat() && ST.hasVFP4Base())203 getActionDefinitionsBuilder(G_FMA).legalFor({s32, s64});204 else205 getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64});206 207 getActionDefinitionsBuilder({G_FREM, G_FPOW}).libcallFor({s32, s64});208 209 if (ST.hasV5TOps() && !ST.isThumb1Only()) {210 getActionDefinitionsBuilder(G_CTLZ)211 .legalFor({s32, s32})212 .clampScalar(1, s32, s32)213 .clampScalar(0, s32, s32);214 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)215 .lowerFor({s32, s32})216 .clampScalar(1, s32, s32)217 .clampScalar(0, s32, s32);218 } else {219 getActionDefinitionsBuilder(G_CTLZ_ZERO_UNDEF)220 .libcallFor({s32, s32})221 .clampScalar(1, s32, s32)222 .clampScalar(0, s32, s32);223 getActionDefinitionsBuilder(G_CTLZ)224 .lowerFor({s32, s32})225 .clampScalar(1, s32, s32)226 .clampScalar(0, s32, s32);227 }228 229 LegacyInfo.computeTables();230 verify(*ST.getInstrInfo());231}232 233void ARMLegalizerInfo::setFCmpLibcallsAEABI() {234 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be235 // default-initialized.236 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);237 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {238 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};239 FCmp32Libcalls[CmpInst::FCMP_OGE] = {240 {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};241 FCmp32Libcalls[CmpInst::FCMP_OGT] = {242 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};243 FCmp32Libcalls[CmpInst::FCMP_OLE] = {244 {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};245 FCmp32Libcalls[CmpInst::FCMP_OLT] = {246 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};247 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F32, CmpInst::ICMP_EQ}};248 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};249 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};250 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};251 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};252 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};253 FCmp32Libcalls[CmpInst::FCMP_UNO] = {254 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};255 FCmp32Libcalls[CmpInst::FCMP_ONE] = {256 {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},257 {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};258 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {259 {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},260 {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};261 262 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);263 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {264 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};265 FCmp64Libcalls[CmpInst::FCMP_OGE] = {266 {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};267 FCmp64Libcalls[CmpInst::FCMP_OGT] = {268 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};269 FCmp64Libcalls[CmpInst::FCMP_OLE] = {270 {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};271 FCmp64Libcalls[CmpInst::FCMP_OLT] = {272 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};273 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F64, CmpInst::ICMP_EQ}};274 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};275 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};276 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};277 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};278 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};279 FCmp64Libcalls[CmpInst::FCMP_UNO] = {280 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};281 FCmp64Libcalls[CmpInst::FCMP_ONE] = {282 {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},283 {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};284 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {285 {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},286 {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};287}288 289void ARMLegalizerInfo::setFCmpLibcallsGNU() {290 // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be291 // default-initialized.292 FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);293 FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};294 FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};295 FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};296 FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};297 FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};298 FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F32, CmpInst::ICMP_EQ}};299 FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};300 FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};301 FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};302 FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};303 FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};304 FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};305 FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},306 {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};307 FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},308 {RTLIB::UO_F32, CmpInst::ICMP_NE}};309 310 FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);311 FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};312 FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};313 FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};314 FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};315 FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};316 FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::UO_F64, CmpInst::ICMP_EQ}};317 FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};318 FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};319 FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};320 FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};321 FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};322 FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};323 FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},324 {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};325 FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},326 {RTLIB::UO_F64, CmpInst::ICMP_NE}};327}328 329ARMLegalizerInfo::FCmpLibcallsList330ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,331 unsigned Size) const {332 assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");333 if (Size == 32)334 return FCmp32Libcalls[Predicate];335 if (Size == 64)336 return FCmp64Libcalls[Predicate];337 llvm_unreachable("Unsupported size for FCmp predicate");338}339 340bool ARMLegalizerInfo::legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,341 LostDebugLocObserver &LocObserver) const {342 using namespace TargetOpcode;343 344 MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;345 MachineRegisterInfo &MRI = *MIRBuilder.getMRI();346 LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();347 348 switch (MI.getOpcode()) {349 default:350 return false;351 case G_SREM:352 case G_UREM: {353 Register OriginalResult = MI.getOperand(0).getReg();354 auto Size = MRI.getType(OriginalResult).getSizeInBits();355 if (Size != 32)356 return false;357 358 auto Libcall =359 MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;360 361 // Our divmod libcalls return a struct containing the quotient and the362 // remainder. Create a new, unused register for the quotient and use the363 // destination of the original instruction for the remainder.364 Type *ArgTy = Type::getInt32Ty(Ctx);365 StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);366 Register RetRegs[] = {MRI.createGenericVirtualRegister(LLT::scalar(32)),367 OriginalResult};368 auto Status = createLibcall(MIRBuilder, Libcall, {RetRegs, RetTy, 0},369 {{MI.getOperand(1).getReg(), ArgTy, 0},370 {MI.getOperand(2).getReg(), ArgTy, 0}},371 LocObserver, &MI);372 if (Status != LegalizerHelper::Legalized)373 return false;374 break;375 }376 case G_FCMP: {377 assert(MRI.getType(MI.getOperand(2).getReg()) ==378 MRI.getType(MI.getOperand(3).getReg()) &&379 "Mismatched operands for G_FCMP");380 auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();381 382 auto OriginalResult = MI.getOperand(0).getReg();383 auto Predicate =384 static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());385 auto Libcalls = getFCmpLibcalls(Predicate, OpSize);386 387 if (Libcalls.empty()) {388 assert((Predicate == CmpInst::FCMP_TRUE ||389 Predicate == CmpInst::FCMP_FALSE) &&390 "Predicate needs libcalls, but none specified");391 MIRBuilder.buildConstant(OriginalResult,392 Predicate == CmpInst::FCMP_TRUE ? 1 : 0);393 MI.eraseFromParent();394 return true;395 }396 397 assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");398 auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);399 auto *RetTy = Type::getInt32Ty(Ctx);400 401 SmallVector<Register, 2> Results;402 for (auto Libcall : Libcalls) {403 auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));404 auto Status = createLibcall(MIRBuilder, Libcall.LibcallID,405 {LibcallResult, RetTy, 0},406 {{MI.getOperand(2).getReg(), ArgTy, 0},407 {MI.getOperand(3).getReg(), ArgTy, 0}},408 LocObserver, &MI);409 410 if (Status != LegalizerHelper::Legalized)411 return false;412 413 auto ProcessedResult =414 Libcalls.size() == 1415 ? OriginalResult416 : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));417 418 // We have a result, but we need to transform it into a proper 1-bit 0 or419 // 1, taking into account the different peculiarities of the values420 // returned by the comparison functions.421 CmpInst::Predicate ResultPred = Libcall.Predicate;422 if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {423 // We have a nice 0 or 1, and we just need to truncate it back to 1 bit424 // to keep the types consistent.425 MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);426 } else {427 // We need to compare against 0.428 assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");429 auto Zero = MIRBuilder.buildConstant(LLT::scalar(32), 0);430 MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);431 }432 Results.push_back(ProcessedResult);433 }434 435 if (Results.size() != 1) {436 assert(Results.size() == 2 && "Unexpected number of results");437 MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);438 }439 break;440 }441 case G_CONSTANT: {442 const ConstantInt *ConstVal = MI.getOperand(1).getCImm();443 uint64_t ImmVal = ConstVal->getZExtValue();444 if (ConstantMaterializationCost(ImmVal, &ST) > 2 && !ST.genExecuteOnly())445 return Helper.lowerConstant(MI) == LegalizerHelper::Legalized;446 return true;447 }448 case G_FCONSTANT: {449 // Convert to integer constants, while preserving the binary representation.450 auto AsInteger =451 MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();452 MIRBuilder.buildConstant(MI.getOperand(0),453 *ConstantInt::get(Ctx, AsInteger));454 break;455 }456 case G_SET_FPMODE: {457 // New FPSCR = (FPSCR & FPStatusBits) | (Modes & ~FPStatusBits)458 LLT FPEnvTy = LLT::scalar(32);459 auto FPEnv = MRI.createGenericVirtualRegister(FPEnvTy);460 Register Modes = MI.getOperand(0).getReg();461 MIRBuilder.buildGetFPEnv(FPEnv);462 auto StatusBitMask = MIRBuilder.buildConstant(FPEnvTy, ARM::FPStatusBits);463 auto StatusBits = MIRBuilder.buildAnd(FPEnvTy, FPEnv, StatusBitMask);464 auto NotStatusBitMask =465 MIRBuilder.buildConstant(FPEnvTy, ~ARM::FPStatusBits);466 auto FPModeBits = MIRBuilder.buildAnd(FPEnvTy, Modes, NotStatusBitMask);467 auto NewFPSCR = MIRBuilder.buildOr(FPEnvTy, StatusBits, FPModeBits);468 MIRBuilder.buildSetFPEnv(NewFPSCR);469 break;470 }471 case G_RESET_FPMODE: {472 // To get the default FP mode all control bits are cleared:473 // FPSCR = FPSCR & (FPStatusBits | FPReservedBits)474 LLT FPEnvTy = LLT::scalar(32);475 auto FPEnv = MIRBuilder.buildGetFPEnv(FPEnvTy);476 auto NotModeBitMask = MIRBuilder.buildConstant(477 FPEnvTy, ARM::FPStatusBits | ARM::FPReservedBits);478 auto NewFPSCR = MIRBuilder.buildAnd(FPEnvTy, FPEnv, NotModeBitMask);479 MIRBuilder.buildSetFPEnv(NewFPSCR);480 break;481 }482 }483 484 MI.eraseFromParent();485 return true;486}487