LCOV - code coverage report
Current view: top level - lib/Target/ARM - ARMLegalizerInfo.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 149 153 97.4 %
Date: 2018-10-20 13:21:21 Functions: 8 8 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- ARMLegalizerInfo.cpp --------------------------------------*- C++ -*-==//
       2             : //
       3             : //                     The LLVM Compiler Infrastructure
       4             : //
       5             : // This file is distributed under the University of Illinois Open Source
       6             : // License. See LICENSE.TXT for details.
       7             : //
       8             : //===----------------------------------------------------------------------===//
       9             : /// \file
      10             : /// This file implements the targeting of the Machinelegalizer class for ARM.
      11             : /// \todo This should be generated by TableGen.
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #include "ARMLegalizerInfo.h"
      15             : #include "ARMCallLowering.h"
      16             : #include "ARMSubtarget.h"
      17             : #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
      18             : #include "llvm/CodeGen/LowLevelType.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             : 
      25             : using namespace llvm;
      26             : using namespace LegalizeActions;
      27             : 
      28             : /// FIXME: The following static functions are SizeChangeStrategy functions
      29             : /// that are meant to temporarily mimic the behaviour of the old legalization
      30             : /// based on doubling/halving non-legal types as closely as possible. This is
      31             : /// not entirly possible as only legalizing the types that are exactly a power
      32             : /// of 2 times the size of the legal types would require specifying all those
      33             : /// sizes explicitly.
      34             : /// In practice, not specifying those isn't a problem, and the below functions
      35             : /// should disappear quickly as we add support for legalizing non-power-of-2
      36             : /// sized types further.
      37             : static void
      38       10100 : addAndInterleaveWithUnsupported(LegalizerInfo::SizeAndActionsVec &result,
      39             :                                 const LegalizerInfo::SizeAndActionsVec &v) {
      40       40400 :   for (unsigned i = 0; i < v.size(); ++i) {
      41       10100 :     result.push_back(v[i]);
      42       20200 :     if (i + 1 < v[i].first && i + 1 < v.size() &&
      43           0 :         v[i + 1].first != v[i].first + 1)
      44           0 :       result.push_back({v[i].first + 1, Unsupported});
      45             :   }
      46       10100 : }
      47             : 
      48             : static LegalizerInfo::SizeAndActionsVec
      49       10100 : widen_8_16(const LegalizerInfo::SizeAndActionsVec &v) {
      50             :   assert(v.size() >= 1);
      51             :   assert(v[0].first > 17);
      52             :   LegalizerInfo::SizeAndActionsVec result = {{1, Unsupported},
      53             :                                              {8, WidenScalar},
      54             :                                              {9, Unsupported},
      55             :                                              {16, WidenScalar},
      56             :                                              {17, Unsupported}};
      57       10100 :   addAndInterleaveWithUnsupported(result, v);
      58       10100 :   auto Largest = result.back().first;
      59       10100 :   result.push_back({Largest + 1, Unsupported});
      60       10100 :   return result;
      61             : }
      62             : 
      63       10820 : static bool AEABI(const ARMSubtarget &ST) {
      64       10820 :   return ST.isTargetAEABI() || ST.isTargetGNUAEABI() || ST.isTargetMuslAEABI();
      65             : }
      66             : 
      67        5050 : ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) {
      68             :   using namespace TargetOpcode;
      69             : 
      70             :   const LLT p0 = LLT::pointer(0, 32);
      71             : 
      72             :   const LLT s1 = LLT::scalar(1);
      73             :   const LLT s8 = LLT::scalar(8);
      74             :   const LLT s16 = LLT::scalar(16);
      75        5050 :   const LLT s32 = LLT::scalar(32);
      76             :   const LLT s64 = LLT::scalar(64);
      77             : 
      78        5050 :   getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
      79        5050 :   getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
      80             : 
      81        5050 :   getActionDefinitionsBuilder({G_ADD, G_SUB, G_MUL, G_AND, G_OR, G_XOR})
      82        5050 :       .legalFor({s32})
      83        5050 :       .minScalar(0, s32);
      84             : 
      85        5050 :   if (ST.hasDivideInARMMode())
      86         651 :     getActionDefinitionsBuilder({G_SDIV, G_UDIV})
      87         651 :         .legalFor({s32})
      88         651 :         .clampScalar(0, s32, s32);
      89             :   else
      90        4399 :     getActionDefinitionsBuilder({G_SDIV, G_UDIV})
      91        4399 :         .libcallFor({s32})
      92        4399 :         .clampScalar(0, s32, s32);
      93             : 
      94       15150 :   for (unsigned Op : {G_SREM, G_UREM}) {
      95       10100 :     setLegalizeScalarToDifferentSizeStrategy(Op, 0, widen_8_16);
      96       10100 :     if (ST.hasDivideInARMMode())
      97        1302 :       setAction({Op, s32}, Lower);
      98        8798 :     else if (AEABI(ST))
      99        5660 :       setAction({Op, s32}, Custom);
     100             :     else
     101        3138 :       setAction({Op, s32}, Libcall);
     102             :   }
     103             : 
     104        5050 :   getActionDefinitionsBuilder({G_SEXT, G_ZEXT, G_ANYEXT})
     105        5050 :       .legalForCartesianProduct({s32}, {s1, s8, s16});
     106             : 
     107        5050 :   getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, s32}});
     108        5050 :   getActionDefinitionsBuilder(G_PTRTOINT).legalFor({{s32, p0}});
     109             : 
     110        5050 :   getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL}).legalFor({s32});
     111             : 
     112        5050 :   getActionDefinitionsBuilder(G_GEP).legalFor({{p0, s32}});
     113             : 
     114        5050 :   getActionDefinitionsBuilder(G_SELECT).legalForCartesianProduct({s32, p0},
     115        5050 :                                                                  {s1});
     116             : 
     117        5050 :   getActionDefinitionsBuilder(G_BRCOND).legalFor({s1});
     118             : 
     119        5050 :   getActionDefinitionsBuilder(G_CONSTANT)
     120        5050 :       .legalFor({s32, p0})
     121        5050 :       .clampScalar(0, s32, s32);
     122             : 
     123        5050 :   getActionDefinitionsBuilder(G_ICMP)
     124        5050 :       .legalForCartesianProduct({s1}, {s32, p0})
     125        5050 :       .minScalar(1, s32);
     126             : 
     127             :   // We're keeping these builders around because we'll want to add support for
     128             :   // floating point to them.
     129             :   auto &LoadStoreBuilder =
     130        5050 :       getActionDefinitionsBuilder({G_LOAD, G_STORE})
     131        5050 :           .legalForCartesianProduct({s1, s8, s16, s32, p0}, {p0});
     132             : 
     133             :   auto &PhiBuilder =
     134        5050 :       getActionDefinitionsBuilder(G_PHI).legalFor({s32, p0}).minScalar(0, s32);
     135             : 
     136        5050 :   if (!ST.useSoftFloat() && ST.hasVFP2()) {
     137             :     getActionDefinitionsBuilder(
     138        3028 :         {G_FADD, G_FSUB, G_FMUL, G_FDIV, G_FCONSTANT, G_FNEG})
     139        3028 :         .legalFor({s32, s64});
     140             : 
     141        3028 :     LoadStoreBuilder.legalFor({{s64, p0}});
     142        3028 :     PhiBuilder.legalFor({s64});
     143             : 
     144        3028 :     getActionDefinitionsBuilder(G_FCMP).legalForCartesianProduct({s1},
     145        3028 :                                                                  {s32, s64});
     146             : 
     147        3028 :     getActionDefinitionsBuilder(G_MERGE_VALUES).legalFor({{s64, s32}});
     148        3028 :     getActionDefinitionsBuilder(G_UNMERGE_VALUES).legalFor({{s32, s64}});
     149             : 
     150        3028 :     getActionDefinitionsBuilder(G_FPEXT).legalFor({{s64, s32}});
     151        3028 :     getActionDefinitionsBuilder(G_FPTRUNC).legalFor({{s32, s64}});
     152             : 
     153        3028 :     getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
     154        3028 :         .legalForCartesianProduct({s32}, {s32, s64});
     155        3028 :     getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
     156        3028 :         .legalForCartesianProduct({s32, s64}, {s32});
     157             :   } else {
     158        2022 :     getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FMUL, G_FDIV})
     159        2022 :         .libcallFor({s32, s64});
     160             : 
     161        2022 :     LoadStoreBuilder.maxScalar(0, s32);
     162             : 
     163        6066 :     for (auto Ty : {s32, s64})
     164        4044 :       setAction({G_FNEG, Ty}, Lower);
     165             : 
     166        2022 :     getActionDefinitionsBuilder(G_FCONSTANT).customFor({s32, s64});
     167             : 
     168        2022 :     getActionDefinitionsBuilder(G_FCMP).customForCartesianProduct({s1},
     169        2022 :                                                                   {s32, s64});
     170             : 
     171        2022 :     if (AEABI(ST))
     172        1428 :       setFCmpLibcallsAEABI();
     173             :     else
     174         594 :       setFCmpLibcallsGNU();
     175             : 
     176        2022 :     getActionDefinitionsBuilder(G_FPEXT).libcallFor({{s64, s32}});
     177        2022 :     getActionDefinitionsBuilder(G_FPTRUNC).libcallFor({{s32, s64}});
     178             : 
     179        2022 :     getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
     180        2022 :         .libcallForCartesianProduct({s32}, {s32, s64});
     181        2022 :     getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
     182        2022 :         .libcallForCartesianProduct({s32, s64}, {s32});
     183             :   }
     184             : 
     185        5050 :   if (!ST.useSoftFloat() && ST.hasVFP4())
     186         839 :     getActionDefinitionsBuilder(G_FMA).legalFor({s32, s64});
     187             :   else
     188        4211 :     getActionDefinitionsBuilder(G_FMA).libcallFor({s32, s64});
     189             : 
     190        5050 :   getActionDefinitionsBuilder({G_FREM, G_FPOW}).libcallFor({s32, s64});
     191             : 
     192        5050 :   computeTables();
     193        5050 :   verify(*ST.getInstrInfo());
     194        5050 : }
     195             : 
     196        1428 : void ARMLegalizerInfo::setFCmpLibcallsAEABI() {
     197             :   // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
     198             :   // default-initialized.
     199             :   FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
     200             :   FCmp32Libcalls[CmpInst::FCMP_OEQ] = {
     201             :       {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE}};
     202             :   FCmp32Libcalls[CmpInst::FCMP_OGE] = {
     203             :       {RTLIB::OGE_F32, CmpInst::BAD_ICMP_PREDICATE}};
     204             :   FCmp32Libcalls[CmpInst::FCMP_OGT] = {
     205             :       {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE}};
     206             :   FCmp32Libcalls[CmpInst::FCMP_OLE] = {
     207             :       {RTLIB::OLE_F32, CmpInst::BAD_ICMP_PREDICATE}};
     208             :   FCmp32Libcalls[CmpInst::FCMP_OLT] = {
     209             :       {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
     210             :   FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
     211             :   FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_EQ}};
     212             :   FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_EQ}};
     213             :   FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_EQ}};
     214             :   FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_EQ}};
     215             :   FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_EQ}};
     216             :   FCmp32Libcalls[CmpInst::FCMP_UNO] = {
     217             :       {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
     218             :   FCmp32Libcalls[CmpInst::FCMP_ONE] = {
     219             :       {RTLIB::OGT_F32, CmpInst::BAD_ICMP_PREDICATE},
     220             :       {RTLIB::OLT_F32, CmpInst::BAD_ICMP_PREDICATE}};
     221             :   FCmp32Libcalls[CmpInst::FCMP_UEQ] = {
     222             :       {RTLIB::OEQ_F32, CmpInst::BAD_ICMP_PREDICATE},
     223             :       {RTLIB::UO_F32, CmpInst::BAD_ICMP_PREDICATE}};
     224             : 
     225             :   FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
     226             :   FCmp64Libcalls[CmpInst::FCMP_OEQ] = {
     227             :       {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE}};
     228             :   FCmp64Libcalls[CmpInst::FCMP_OGE] = {
     229             :       {RTLIB::OGE_F64, CmpInst::BAD_ICMP_PREDICATE}};
     230             :   FCmp64Libcalls[CmpInst::FCMP_OGT] = {
     231             :       {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE}};
     232             :   FCmp64Libcalls[CmpInst::FCMP_OLE] = {
     233             :       {RTLIB::OLE_F64, CmpInst::BAD_ICMP_PREDICATE}};
     234             :   FCmp64Libcalls[CmpInst::FCMP_OLT] = {
     235             :       {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
     236             :   FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
     237             :   FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_EQ}};
     238             :   FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_EQ}};
     239             :   FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_EQ}};
     240             :   FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_EQ}};
     241             :   FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_EQ}};
     242             :   FCmp64Libcalls[CmpInst::FCMP_UNO] = {
     243             :       {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
     244             :   FCmp64Libcalls[CmpInst::FCMP_ONE] = {
     245             :       {RTLIB::OGT_F64, CmpInst::BAD_ICMP_PREDICATE},
     246             :       {RTLIB::OLT_F64, CmpInst::BAD_ICMP_PREDICATE}};
     247             :   FCmp64Libcalls[CmpInst::FCMP_UEQ] = {
     248             :       {RTLIB::OEQ_F64, CmpInst::BAD_ICMP_PREDICATE},
     249             :       {RTLIB::UO_F64, CmpInst::BAD_ICMP_PREDICATE}};
     250        1428 : }
     251             : 
     252         594 : void ARMLegalizerInfo::setFCmpLibcallsGNU() {
     253             :   // FCMP_TRUE and FCMP_FALSE don't need libcalls, they should be
     254             :   // default-initialized.
     255             :   FCmp32Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
     256             :   FCmp32Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ}};
     257             :   FCmp32Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F32, CmpInst::ICMP_SGE}};
     258             :   FCmp32Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT}};
     259             :   FCmp32Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F32, CmpInst::ICMP_SLE}};
     260             :   FCmp32Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
     261             :   FCmp32Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F32, CmpInst::ICMP_EQ}};
     262             :   FCmp32Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F32, CmpInst::ICMP_SGE}};
     263             :   FCmp32Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F32, CmpInst::ICMP_SGT}};
     264             :   FCmp32Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SLE}};
     265             :   FCmp32Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F32, CmpInst::ICMP_SLT}};
     266             :   FCmp32Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F32, CmpInst::ICMP_NE}};
     267             :   FCmp32Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F32, CmpInst::ICMP_NE}};
     268             :   FCmp32Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F32, CmpInst::ICMP_SGT},
     269             :                                        {RTLIB::OLT_F32, CmpInst::ICMP_SLT}};
     270             :   FCmp32Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F32, CmpInst::ICMP_EQ},
     271             :                                        {RTLIB::UO_F32, CmpInst::ICMP_NE}};
     272             : 
     273             :   FCmp64Libcalls.resize(CmpInst::LAST_FCMP_PREDICATE + 1);
     274             :   FCmp64Libcalls[CmpInst::FCMP_OEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ}};
     275             :   FCmp64Libcalls[CmpInst::FCMP_OGE] = {{RTLIB::OGE_F64, CmpInst::ICMP_SGE}};
     276             :   FCmp64Libcalls[CmpInst::FCMP_OGT] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT}};
     277             :   FCmp64Libcalls[CmpInst::FCMP_OLE] = {{RTLIB::OLE_F64, CmpInst::ICMP_SLE}};
     278             :   FCmp64Libcalls[CmpInst::FCMP_OLT] = {{RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
     279             :   FCmp64Libcalls[CmpInst::FCMP_ORD] = {{RTLIB::O_F64, CmpInst::ICMP_EQ}};
     280             :   FCmp64Libcalls[CmpInst::FCMP_UGE] = {{RTLIB::OLT_F64, CmpInst::ICMP_SGE}};
     281             :   FCmp64Libcalls[CmpInst::FCMP_UGT] = {{RTLIB::OLE_F64, CmpInst::ICMP_SGT}};
     282             :   FCmp64Libcalls[CmpInst::FCMP_ULE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SLE}};
     283             :   FCmp64Libcalls[CmpInst::FCMP_ULT] = {{RTLIB::OGE_F64, CmpInst::ICMP_SLT}};
     284             :   FCmp64Libcalls[CmpInst::FCMP_UNE] = {{RTLIB::UNE_F64, CmpInst::ICMP_NE}};
     285             :   FCmp64Libcalls[CmpInst::FCMP_UNO] = {{RTLIB::UO_F64, CmpInst::ICMP_NE}};
     286             :   FCmp64Libcalls[CmpInst::FCMP_ONE] = {{RTLIB::OGT_F64, CmpInst::ICMP_SGT},
     287             :                                        {RTLIB::OLT_F64, CmpInst::ICMP_SLT}};
     288             :   FCmp64Libcalls[CmpInst::FCMP_UEQ] = {{RTLIB::OEQ_F64, CmpInst::ICMP_EQ},
     289             :                                        {RTLIB::UO_F64, CmpInst::ICMP_NE}};
     290         594 : }
     291             : 
     292             : ARMLegalizerInfo::FCmpLibcallsList
     293          68 : ARMLegalizerInfo::getFCmpLibcalls(CmpInst::Predicate Predicate,
     294             :                                   unsigned Size) const {
     295             :   assert(CmpInst::isFPPredicate(Predicate) && "Unsupported FCmp predicate");
     296          68 :   if (Size == 32)
     297             :     return FCmp32Libcalls[Predicate];
     298          32 :   if (Size == 64)
     299             :     return FCmp64Libcalls[Predicate];
     300           0 :   llvm_unreachable("Unsupported size for FCmp predicate");
     301             : }
     302             : 
     303          88 : bool ARMLegalizerInfo::legalizeCustom(MachineInstr &MI,
     304             :                                       MachineRegisterInfo &MRI,
     305             :                                       MachineIRBuilder &MIRBuilder) const {
     306             :   using namespace TargetOpcode;
     307             : 
     308          88 :   MIRBuilder.setInstr(MI);
     309          88 :   LLVMContext &Ctx = MIRBuilder.getMF().getFunction().getContext();
     310             : 
     311         176 :   switch (MI.getOpcode()) {
     312             :   default:
     313             :     return false;
     314          12 :   case G_SREM:
     315             :   case G_UREM: {
     316          12 :     unsigned OriginalResult = MI.getOperand(0).getReg();
     317          12 :     auto Size = MRI.getType(OriginalResult).getSizeInBits();
     318          12 :     if (Size != 32)
     319             :       return false;
     320             : 
     321             :     auto Libcall =
     322          12 :         MI.getOpcode() == G_SREM ? RTLIB::SDIVREM_I32 : RTLIB::UDIVREM_I32;
     323             : 
     324             :     // Our divmod libcalls return a struct containing the quotient and the
     325             :     // remainder. We need to create a virtual register for it.
     326          12 :     Type *ArgTy = Type::getInt32Ty(Ctx);
     327          24 :     StructType *RetTy = StructType::get(Ctx, {ArgTy, ArgTy}, /* Packed */ true);
     328          12 :     auto RetVal = MRI.createGenericVirtualRegister(
     329          12 :         getLLTForType(*RetTy, MIRBuilder.getMF().getDataLayout()));
     330             : 
     331          36 :     auto Status = createLibcall(MIRBuilder, Libcall, {RetVal, RetTy},
     332          12 :                                 {{MI.getOperand(1).getReg(), ArgTy},
     333             :                                  {MI.getOperand(2).getReg(), ArgTy}});
     334          12 :     if (Status != LegalizerHelper::Legalized)
     335             :       return false;
     336             : 
     337             :     // The remainder is the second result of divmod. Split the return value into
     338             :     // a new, unused register for the quotient and the destination of the
     339             :     // original instruction for the remainder.
     340             :     MIRBuilder.buildUnmerge(
     341          12 :         {MRI.createGenericVirtualRegister(LLT::scalar(32)), OriginalResult},
     342          24 :         RetVal);
     343          12 :     break;
     344             :   }
     345          68 :   case G_FCMP: {
     346             :     assert(MRI.getType(MI.getOperand(2).getReg()) ==
     347             :                MRI.getType(MI.getOperand(3).getReg()) &&
     348             :            "Mismatched operands for G_FCMP");
     349          68 :     auto OpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
     350             : 
     351          68 :     auto OriginalResult = MI.getOperand(0).getReg();
     352             :     auto Predicate =
     353          68 :         static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
     354          68 :     auto Libcalls = getFCmpLibcalls(Predicate, OpSize);
     355             : 
     356          68 :     if (Libcalls.empty()) {
     357             :       assert((Predicate == CmpInst::FCMP_TRUE ||
     358             :               Predicate == CmpInst::FCMP_FALSE) &&
     359             :              "Predicate needs libcalls, but none specified");
     360             :       MIRBuilder.buildConstant(OriginalResult,
     361          12 :                                Predicate == CmpInst::FCMP_TRUE ? 1 : 0);
     362           8 :       MI.eraseFromParent();
     363           8 :       return true;
     364             :     }
     365             : 
     366             :     assert((OpSize == 32 || OpSize == 64) && "Unsupported operand size");
     367          60 :     auto *ArgTy = OpSize == 32 ? Type::getFloatTy(Ctx) : Type::getDoubleTy(Ctx);
     368          60 :     auto *RetTy = Type::getInt32Ty(Ctx);
     369             : 
     370             :     SmallVector<unsigned, 2> Results;
     371         130 :     for (auto Libcall : Libcalls) {
     372          70 :       auto LibcallResult = MRI.createGenericVirtualRegister(LLT::scalar(32));
     373             :       auto Status =
     374         210 :           createLibcall(MIRBuilder, Libcall.LibcallID, {LibcallResult, RetTy},
     375          70 :                         {{MI.getOperand(2).getReg(), ArgTy},
     376             :                          {MI.getOperand(3).getReg(), ArgTy}});
     377             : 
     378          70 :       if (Status != LegalizerHelper::Legalized)
     379           0 :         return false;
     380             : 
     381             :       auto ProcessedResult =
     382          70 :           Libcalls.size() == 1
     383          70 :               ? OriginalResult
     384          20 :               : MRI.createGenericVirtualRegister(MRI.getType(OriginalResult));
     385             : 
     386             :       // We have a result, but we need to transform it into a proper 1-bit 0 or
     387             :       // 1, taking into account the different peculiarities of the values
     388             :       // returned by the comparison functions.
     389             :       CmpInst::Predicate ResultPred = Libcall.Predicate;
     390          70 :       if (ResultPred == CmpInst::BAD_ICMP_PREDICATE) {
     391             :         // We have a nice 0 or 1, and we just need to truncate it back to 1 bit
     392             :         // to keep the types consistent.
     393          23 :         MIRBuilder.buildTrunc(ProcessedResult, LibcallResult);
     394             :       } else {
     395             :         // We need to compare against 0.
     396             :         assert(CmpInst::isIntPredicate(ResultPred) && "Unsupported predicate");
     397          47 :         auto Zero = MRI.createGenericVirtualRegister(LLT::scalar(32));
     398          47 :         MIRBuilder.buildConstant(Zero, 0);
     399          47 :         MIRBuilder.buildICmp(ResultPred, ProcessedResult, LibcallResult, Zero);
     400             :       }
     401          70 :       Results.push_back(ProcessedResult);
     402             :     }
     403             : 
     404          60 :     if (Results.size() != 1) {
     405             :       assert(Results.size() == 2 && "Unexpected number of results");
     406          20 :       MIRBuilder.buildOr(OriginalResult, Results[0], Results[1]);
     407             :     }
     408             :     break;
     409             :   }
     410           8 :   case G_FCONSTANT: {
     411             :     // Convert to integer constants, while preserving the binary representation.
     412             :     auto AsInteger =
     413          16 :         MI.getOperand(1).getFPImm()->getValueAPF().bitcastToAPInt();
     414           8 :     MIRBuilder.buildConstant(MI.getOperand(0).getReg(),
     415           8 :                              *ConstantInt::get(Ctx, AsInteger));
     416             :     break;
     417             :   }
     418             :   }
     419             : 
     420          80 :   MI.eraseFromParent();
     421          80 :   return true;
     422             : }

Generated by: LCOV version 1.13