xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/X86/GISel/X86RegisterBankInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15f757f3fSDimitry Andric //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
25f757f3fSDimitry Andric //
35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f757f3fSDimitry Andric //
75f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
85f757f3fSDimitry Andric /// \file
95f757f3fSDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for X86.
105f757f3fSDimitry Andric /// \todo This should be generated by TableGen.
115f757f3fSDimitry Andric //===----------------------------------------------------------------------===//
125f757f3fSDimitry Andric 
135f757f3fSDimitry Andric #include "X86RegisterBankInfo.h"
145f757f3fSDimitry Andric #include "X86InstrInfo.h"
15*0fca6ea1SDimitry Andric #include "X86Subtarget.h"
16*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
17*0fca6ea1SDimitry Andric #include "llvm/CodeGen/GlobalISel/Utils.h"
185f757f3fSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
195f757f3fSDimitry Andric #include "llvm/CodeGen/RegisterBank.h"
205f757f3fSDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h"
215f757f3fSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
22*0fca6ea1SDimitry Andric #include "llvm/IR/IntrinsicsX86.h"
235f757f3fSDimitry Andric 
245f757f3fSDimitry Andric #define GET_TARGET_REGBANK_IMPL
255f757f3fSDimitry Andric #include "X86GenRegisterBank.inc"
265f757f3fSDimitry Andric 
275f757f3fSDimitry Andric using namespace llvm;
285f757f3fSDimitry Andric // This file will be TableGen'ed at some point.
295f757f3fSDimitry Andric #define GET_TARGET_REGBANK_INFO_IMPL
305f757f3fSDimitry Andric #include "X86GenRegisterBankInfo.def"
315f757f3fSDimitry Andric 
325f757f3fSDimitry Andric X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo &TRI) {
335f757f3fSDimitry Andric 
345f757f3fSDimitry Andric   // validate RegBank initialization.
355f757f3fSDimitry Andric   const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
365f757f3fSDimitry Andric   (void)RBGPR;
375f757f3fSDimitry Andric   assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
385f757f3fSDimitry Andric 
395f757f3fSDimitry Andric   // The GPR register bank is fully defined by all the registers in
405f757f3fSDimitry Andric   // GR64 + its subclasses.
415f757f3fSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
425f757f3fSDimitry Andric          "Subclass not added?");
435f757f3fSDimitry Andric   assert(getMaximumSize(RBGPR.getID()) == 64 &&
445f757f3fSDimitry Andric          "GPRs should hold up to 64-bit");
455f757f3fSDimitry Andric }
465f757f3fSDimitry Andric 
475f757f3fSDimitry Andric const RegisterBank &
485f757f3fSDimitry Andric X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
495f757f3fSDimitry Andric                                             LLT) const {
505f757f3fSDimitry Andric 
515f757f3fSDimitry Andric   if (X86::GR8RegClass.hasSubClassEq(&RC) ||
525f757f3fSDimitry Andric       X86::GR16RegClass.hasSubClassEq(&RC) ||
535f757f3fSDimitry Andric       X86::GR32RegClass.hasSubClassEq(&RC) ||
545f757f3fSDimitry Andric       X86::GR64RegClass.hasSubClassEq(&RC) ||
555f757f3fSDimitry Andric       X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) ||
565f757f3fSDimitry Andric       X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC))
575f757f3fSDimitry Andric     return getRegBank(X86::GPRRegBankID);
585f757f3fSDimitry Andric 
595f757f3fSDimitry Andric   if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
605f757f3fSDimitry Andric       X86::FR64XRegClass.hasSubClassEq(&RC) ||
615f757f3fSDimitry Andric       X86::VR128XRegClass.hasSubClassEq(&RC) ||
625f757f3fSDimitry Andric       X86::VR256XRegClass.hasSubClassEq(&RC) ||
635f757f3fSDimitry Andric       X86::VR512RegClass.hasSubClassEq(&RC))
645f757f3fSDimitry Andric     return getRegBank(X86::VECRRegBankID);
655f757f3fSDimitry Andric 
66*0fca6ea1SDimitry Andric   if (X86::RFP80RegClass.hasSubClassEq(&RC) ||
67*0fca6ea1SDimitry Andric       X86::RFP32RegClass.hasSubClassEq(&RC) ||
68*0fca6ea1SDimitry Andric       X86::RFP64RegClass.hasSubClassEq(&RC))
69*0fca6ea1SDimitry Andric     return getRegBank(X86::PSRRegBankID);
70*0fca6ea1SDimitry Andric 
715f757f3fSDimitry Andric   llvm_unreachable("Unsupported register kind yet.");
725f757f3fSDimitry Andric }
735f757f3fSDimitry Andric 
74*0fca6ea1SDimitry Andric // \returns true if a given intrinsic only uses and defines FPRs.
75*0fca6ea1SDimitry Andric static bool isFPIntrinsic(const MachineRegisterInfo &MRI,
76*0fca6ea1SDimitry Andric                           const MachineInstr &MI) {
77*0fca6ea1SDimitry Andric   // TODO: Add more intrinsics.
78*0fca6ea1SDimitry Andric   switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
79*0fca6ea1SDimitry Andric   default:
80*0fca6ea1SDimitry Andric     return false;
81*0fca6ea1SDimitry Andric   // SSE1
82*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_rcp_ss:
83*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_rcp_ps:
84*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_rsqrt_ss:
85*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_rsqrt_ps:
86*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_min_ss:
87*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_min_ps:
88*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_max_ss:
89*0fca6ea1SDimitry Andric   case Intrinsic::x86_sse_max_ps:
90*0fca6ea1SDimitry Andric     return true;
91*0fca6ea1SDimitry Andric   }
92*0fca6ea1SDimitry Andric   return false;
93*0fca6ea1SDimitry Andric }
94*0fca6ea1SDimitry Andric 
95*0fca6ea1SDimitry Andric bool X86RegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
96*0fca6ea1SDimitry Andric                                            const MachineRegisterInfo &MRI,
97*0fca6ea1SDimitry Andric                                            const TargetRegisterInfo &TRI,
98*0fca6ea1SDimitry Andric                                            unsigned Depth) const {
99*0fca6ea1SDimitry Andric   unsigned Op = MI.getOpcode();
100*0fca6ea1SDimitry Andric   if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI))
101*0fca6ea1SDimitry Andric     return true;
102*0fca6ea1SDimitry Andric 
103*0fca6ea1SDimitry Andric   // Do we have an explicit floating point instruction?
104*0fca6ea1SDimitry Andric   if (isPreISelGenericFloatingPointOpcode(Op))
105*0fca6ea1SDimitry Andric     return true;
106*0fca6ea1SDimitry Andric 
107*0fca6ea1SDimitry Andric   // No. Check if we have a copy-like instruction. If we do, then we could
108*0fca6ea1SDimitry Andric   // still be fed by floating point instructions.
109*0fca6ea1SDimitry Andric   if (Op != TargetOpcode::COPY && !MI.isPHI() &&
110*0fca6ea1SDimitry Andric       !isPreISelGenericOptimizationHint(Op))
111*0fca6ea1SDimitry Andric     return false;
112*0fca6ea1SDimitry Andric 
113*0fca6ea1SDimitry Andric   // Check if we already know the register bank.
114*0fca6ea1SDimitry Andric   auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
115*0fca6ea1SDimitry Andric   if (RB == &getRegBank(X86::PSRRegBankID))
116*0fca6ea1SDimitry Andric     return true;
117*0fca6ea1SDimitry Andric   if (RB == &getRegBank(X86::GPRRegBankID))
118*0fca6ea1SDimitry Andric     return false;
119*0fca6ea1SDimitry Andric 
120*0fca6ea1SDimitry Andric   // We don't know anything.
121*0fca6ea1SDimitry Andric   //
122*0fca6ea1SDimitry Andric   // If we have a phi, we may be able to infer that it will be assigned a fp
123*0fca6ea1SDimitry Andric   // type based off of its inputs.
124*0fca6ea1SDimitry Andric   if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
125*0fca6ea1SDimitry Andric     return false;
126*0fca6ea1SDimitry Andric 
127*0fca6ea1SDimitry Andric   return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
128*0fca6ea1SDimitry Andric     return Op.isReg() &&
129*0fca6ea1SDimitry Andric            onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
130*0fca6ea1SDimitry Andric   });
131*0fca6ea1SDimitry Andric }
132*0fca6ea1SDimitry Andric 
133*0fca6ea1SDimitry Andric bool X86RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
134*0fca6ea1SDimitry Andric                                      const MachineRegisterInfo &MRI,
135*0fca6ea1SDimitry Andric                                      const TargetRegisterInfo &TRI,
136*0fca6ea1SDimitry Andric                                      unsigned Depth) const {
137*0fca6ea1SDimitry Andric   switch (MI.getOpcode()) {
138*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPTOSI:
139*0fca6ea1SDimitry Andric   case TargetOpcode::G_FPTOUI:
140*0fca6ea1SDimitry Andric   case TargetOpcode::G_FCMP:
141*0fca6ea1SDimitry Andric   case TargetOpcode::G_LROUND:
142*0fca6ea1SDimitry Andric   case TargetOpcode::G_LLROUND:
143*0fca6ea1SDimitry Andric   case TargetOpcode::G_INTRINSIC_TRUNC:
144*0fca6ea1SDimitry Andric   case TargetOpcode::G_INTRINSIC_ROUND:
145*0fca6ea1SDimitry Andric     return true;
146*0fca6ea1SDimitry Andric   default:
147*0fca6ea1SDimitry Andric     break;
148*0fca6ea1SDimitry Andric   }
149*0fca6ea1SDimitry Andric   return hasFPConstraints(MI, MRI, TRI, Depth);
150*0fca6ea1SDimitry Andric }
151*0fca6ea1SDimitry Andric 
152*0fca6ea1SDimitry Andric bool X86RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
153*0fca6ea1SDimitry Andric                                         const MachineRegisterInfo &MRI,
154*0fca6ea1SDimitry Andric                                         const TargetRegisterInfo &TRI,
155*0fca6ea1SDimitry Andric                                         unsigned Depth) const {
156*0fca6ea1SDimitry Andric   switch (MI.getOpcode()) {
157*0fca6ea1SDimitry Andric   case TargetOpcode::G_SITOFP:
158*0fca6ea1SDimitry Andric   case TargetOpcode::G_UITOFP:
159*0fca6ea1SDimitry Andric     return true;
160*0fca6ea1SDimitry Andric   default:
161*0fca6ea1SDimitry Andric     break;
162*0fca6ea1SDimitry Andric   }
163*0fca6ea1SDimitry Andric   return hasFPConstraints(MI, MRI, TRI, Depth);
164*0fca6ea1SDimitry Andric }
165*0fca6ea1SDimitry Andric 
1665f757f3fSDimitry Andric X86GenRegisterBankInfo::PartialMappingIdx
167*0fca6ea1SDimitry Andric X86GenRegisterBankInfo::getPartialMappingIdx(const MachineInstr &MI,
168*0fca6ea1SDimitry Andric                                              const LLT &Ty, bool isFP) {
169*0fca6ea1SDimitry Andric   const MachineFunction *MF = MI.getMF();
170*0fca6ea1SDimitry Andric   const X86Subtarget *ST = &MF->getSubtarget<X86Subtarget>();
171*0fca6ea1SDimitry Andric   bool HasSSE1 = ST->hasSSE1();
172*0fca6ea1SDimitry Andric   bool HasSSE2 = ST->hasSSE2();
173*0fca6ea1SDimitry Andric   // 80 bits is only generated for X87 floating points.
174*0fca6ea1SDimitry Andric   if (Ty.getSizeInBits() == 80)
175*0fca6ea1SDimitry Andric     isFP = true;
1765f757f3fSDimitry Andric   if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
1775f757f3fSDimitry Andric     switch (Ty.getSizeInBits()) {
1785f757f3fSDimitry Andric     case 1:
1795f757f3fSDimitry Andric     case 8:
1805f757f3fSDimitry Andric       return PMI_GPR8;
1815f757f3fSDimitry Andric     case 16:
1825f757f3fSDimitry Andric       return PMI_GPR16;
1835f757f3fSDimitry Andric     case 32:
1845f757f3fSDimitry Andric       return PMI_GPR32;
1855f757f3fSDimitry Andric     case 64:
1865f757f3fSDimitry Andric       return PMI_GPR64;
1875f757f3fSDimitry Andric     case 128:
1885f757f3fSDimitry Andric       return PMI_VEC128;
1895f757f3fSDimitry Andric       break;
1905f757f3fSDimitry Andric     default:
1915f757f3fSDimitry Andric       llvm_unreachable("Unsupported register size.");
1925f757f3fSDimitry Andric     }
1935f757f3fSDimitry Andric   } else if (Ty.isScalar()) {
1945f757f3fSDimitry Andric     switch (Ty.getSizeInBits()) {
1955f757f3fSDimitry Andric     case 32:
196*0fca6ea1SDimitry Andric       return HasSSE1 ? PMI_FP32 : PMI_PSR32;
1975f757f3fSDimitry Andric     case 64:
198*0fca6ea1SDimitry Andric       return HasSSE2 ? PMI_FP64 : PMI_PSR64;
1995f757f3fSDimitry Andric     case 128:
2005f757f3fSDimitry Andric       return PMI_VEC128;
201*0fca6ea1SDimitry Andric     case 80:
202*0fca6ea1SDimitry Andric       return PMI_PSR80;
2035f757f3fSDimitry Andric     default:
2045f757f3fSDimitry Andric       llvm_unreachable("Unsupported register size.");
2055f757f3fSDimitry Andric     }
2065f757f3fSDimitry Andric   } else {
2075f757f3fSDimitry Andric     switch (Ty.getSizeInBits()) {
2085f757f3fSDimitry Andric     case 128:
2095f757f3fSDimitry Andric       return PMI_VEC128;
2105f757f3fSDimitry Andric     case 256:
2115f757f3fSDimitry Andric       return PMI_VEC256;
2125f757f3fSDimitry Andric     case 512:
2135f757f3fSDimitry Andric       return PMI_VEC512;
2145f757f3fSDimitry Andric     default:
2155f757f3fSDimitry Andric       llvm_unreachable("Unsupported register size.");
2165f757f3fSDimitry Andric     }
2175f757f3fSDimitry Andric   }
2185f757f3fSDimitry Andric 
2195f757f3fSDimitry Andric   return PMI_None;
2205f757f3fSDimitry Andric }
2215f757f3fSDimitry Andric 
2225f757f3fSDimitry Andric void X86RegisterBankInfo::getInstrPartialMappingIdxs(
2235f757f3fSDimitry Andric     const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
2245f757f3fSDimitry Andric     SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
2255f757f3fSDimitry Andric 
2265f757f3fSDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2275f757f3fSDimitry Andric   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
2285f757f3fSDimitry Andric     auto &MO = MI.getOperand(Idx);
2295f757f3fSDimitry Andric     if (!MO.isReg() || !MO.getReg())
2305f757f3fSDimitry Andric       OpRegBankIdx[Idx] = PMI_None;
2315f757f3fSDimitry Andric     else
232*0fca6ea1SDimitry Andric       OpRegBankIdx[Idx] =
233*0fca6ea1SDimitry Andric           getPartialMappingIdx(MI, MRI.getType(MO.getReg()), isFP);
2345f757f3fSDimitry Andric   }
2355f757f3fSDimitry Andric }
2365f757f3fSDimitry Andric 
2375f757f3fSDimitry Andric bool X86RegisterBankInfo::getInstrValueMapping(
2385f757f3fSDimitry Andric     const MachineInstr &MI,
2395f757f3fSDimitry Andric     const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
2405f757f3fSDimitry Andric     SmallVectorImpl<const ValueMapping *> &OpdsMapping) {
2415f757f3fSDimitry Andric 
2425f757f3fSDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2435f757f3fSDimitry Andric   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
2445f757f3fSDimitry Andric     if (!MI.getOperand(Idx).isReg())
2455f757f3fSDimitry Andric       continue;
2465f757f3fSDimitry Andric     if (!MI.getOperand(Idx).getReg())
2475f757f3fSDimitry Andric       continue;
2485f757f3fSDimitry Andric 
2495f757f3fSDimitry Andric     auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
2505f757f3fSDimitry Andric     if (!Mapping->isValid())
2515f757f3fSDimitry Andric       return false;
2525f757f3fSDimitry Andric 
2535f757f3fSDimitry Andric     OpdsMapping[Idx] = Mapping;
2545f757f3fSDimitry Andric   }
2555f757f3fSDimitry Andric   return true;
2565f757f3fSDimitry Andric }
2575f757f3fSDimitry Andric 
2585f757f3fSDimitry Andric const RegisterBankInfo::InstructionMapping &
2595f757f3fSDimitry Andric X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
2605f757f3fSDimitry Andric                                             bool isFP) const {
2615f757f3fSDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
2625f757f3fSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2635f757f3fSDimitry Andric 
2645f757f3fSDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2655f757f3fSDimitry Andric   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2665f757f3fSDimitry Andric 
2675f757f3fSDimitry Andric   if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
2685f757f3fSDimitry Andric       (Ty != MRI.getType(MI.getOperand(2).getReg())))
2695f757f3fSDimitry Andric     llvm_unreachable("Unsupported operand mapping yet.");
2705f757f3fSDimitry Andric 
271*0fca6ea1SDimitry Andric   auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, isFP), 3);
2725f757f3fSDimitry Andric   return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
2735f757f3fSDimitry Andric }
2745f757f3fSDimitry Andric 
2755f757f3fSDimitry Andric const RegisterBankInfo::InstructionMapping &
2765f757f3fSDimitry Andric X86RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
2775f757f3fSDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
278*0fca6ea1SDimitry Andric   const TargetSubtargetInfo &STI = MF.getSubtarget();
279*0fca6ea1SDimitry Andric   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
2805f757f3fSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
2815f757f3fSDimitry Andric   unsigned Opc = MI.getOpcode();
2825f757f3fSDimitry Andric 
283*0fca6ea1SDimitry Andric   // Try the default logic for non-generic instructions that are either
284*0fca6ea1SDimitry Andric   // copies or already have some operands assigned to banks.
2855f757f3fSDimitry Andric   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
2865f757f3fSDimitry Andric     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
2875f757f3fSDimitry Andric     if (Mapping.isValid())
2885f757f3fSDimitry Andric       return Mapping;
2895f757f3fSDimitry Andric   }
2905f757f3fSDimitry Andric 
2915f757f3fSDimitry Andric   switch (Opc) {
2925f757f3fSDimitry Andric   case TargetOpcode::G_ADD:
2935f757f3fSDimitry Andric   case TargetOpcode::G_SUB:
2945f757f3fSDimitry Andric   case TargetOpcode::G_MUL:
2955f757f3fSDimitry Andric     return getSameOperandsMapping(MI, false);
2965f757f3fSDimitry Andric   case TargetOpcode::G_FADD:
2975f757f3fSDimitry Andric   case TargetOpcode::G_FSUB:
2985f757f3fSDimitry Andric   case TargetOpcode::G_FMUL:
2995f757f3fSDimitry Andric   case TargetOpcode::G_FDIV:
3005f757f3fSDimitry Andric     return getSameOperandsMapping(MI, true);
3015f757f3fSDimitry Andric   case TargetOpcode::G_SHL:
3025f757f3fSDimitry Andric   case TargetOpcode::G_LSHR:
3035f757f3fSDimitry Andric   case TargetOpcode::G_ASHR: {
3045f757f3fSDimitry Andric     unsigned NumOperands = MI.getNumOperands();
3055f757f3fSDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3065f757f3fSDimitry Andric 
307*0fca6ea1SDimitry Andric     auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, false), 3);
3085f757f3fSDimitry Andric     return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
3095f757f3fSDimitry Andric   }
3105f757f3fSDimitry Andric   default:
3115f757f3fSDimitry Andric     break;
3125f757f3fSDimitry Andric   }
3135f757f3fSDimitry Andric 
3145f757f3fSDimitry Andric   unsigned NumOperands = MI.getNumOperands();
3155f757f3fSDimitry Andric   SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
3165f757f3fSDimitry Andric 
3175f757f3fSDimitry Andric   switch (Opc) {
3185f757f3fSDimitry Andric   case TargetOpcode::G_FPEXT:
3195f757f3fSDimitry Andric   case TargetOpcode::G_FPTRUNC:
3205f757f3fSDimitry Andric   case TargetOpcode::G_FCONSTANT:
321*0fca6ea1SDimitry Andric     // Instruction having only floating-point operands (all scalars in
322*0fca6ea1SDimitry Andric     // VECRReg)
323*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
3245f757f3fSDimitry Andric     break;
3255f757f3fSDimitry Andric   case TargetOpcode::G_SITOFP:
3265f757f3fSDimitry Andric   case TargetOpcode::G_FPTOSI: {
327*0fca6ea1SDimitry Andric     // Some of the floating-point instructions have mixed GPR and FP
328*0fca6ea1SDimitry Andric     // operands: fine-tune the computed mapping.
3295f757f3fSDimitry Andric     auto &Op0 = MI.getOperand(0);
3305f757f3fSDimitry Andric     auto &Op1 = MI.getOperand(1);
3315f757f3fSDimitry Andric     const LLT Ty0 = MRI.getType(Op0.getReg());
3325f757f3fSDimitry Andric     const LLT Ty1 = MRI.getType(Op1.getReg());
3335f757f3fSDimitry Andric 
3345f757f3fSDimitry Andric     bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
3355f757f3fSDimitry Andric     bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
336*0fca6ea1SDimitry Andric     OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);
337*0fca6ea1SDimitry Andric     OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ SecondArgIsFP);
3385f757f3fSDimitry Andric     break;
3395f757f3fSDimitry Andric   }
3405f757f3fSDimitry Andric   case TargetOpcode::G_FCMP: {
3415f757f3fSDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
3425f757f3fSDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
3435f757f3fSDimitry Andric     (void)Ty2;
3445f757f3fSDimitry Andric     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
3455f757f3fSDimitry Andric            "Mismatched operand sizes for G_FCMP");
3465f757f3fSDimitry Andric 
3475f757f3fSDimitry Andric     unsigned Size = Ty1.getSizeInBits();
3485f757f3fSDimitry Andric     (void)Size;
3495f757f3fSDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
3505f757f3fSDimitry Andric 
351*0fca6ea1SDimitry Andric     auto FpRegBank = getPartialMappingIdx(MI, Ty1, /* isFP= */ true);
3525f757f3fSDimitry Andric     OpRegBankIdx = {PMI_GPR8,
3535f757f3fSDimitry Andric                     /* Predicate */ PMI_None, FpRegBank, FpRegBank};
3545f757f3fSDimitry Andric     break;
3555f757f3fSDimitry Andric   }
3565f757f3fSDimitry Andric   case TargetOpcode::G_TRUNC:
3575f757f3fSDimitry Andric   case TargetOpcode::G_ANYEXT: {
3585f757f3fSDimitry Andric     auto &Op0 = MI.getOperand(0);
3595f757f3fSDimitry Andric     auto &Op1 = MI.getOperand(1);
3605f757f3fSDimitry Andric     const LLT Ty0 = MRI.getType(Op0.getReg());
3615f757f3fSDimitry Andric     const LLT Ty1 = MRI.getType(Op1.getReg());
3625f757f3fSDimitry Andric 
3635f757f3fSDimitry Andric     bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
3645f757f3fSDimitry Andric                      Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
3655f757f3fSDimitry Andric     bool isFPAnyExt =
3665f757f3fSDimitry Andric         Ty0.getSizeInBits() == 128 &&
3675f757f3fSDimitry Andric         (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
3685f757f3fSDimitry Andric         Opc == TargetOpcode::G_ANYEXT;
3695f757f3fSDimitry Andric 
370*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ isFPTrunc || isFPAnyExt,
3715f757f3fSDimitry Andric                                OpRegBankIdx);
372*0fca6ea1SDimitry Andric     break;
373*0fca6ea1SDimitry Andric   }
374*0fca6ea1SDimitry Andric   case TargetOpcode::G_LOAD: {
375*0fca6ea1SDimitry Andric     // Check if that load feeds fp instructions.
376*0fca6ea1SDimitry Andric     // In that case, we want the default mapping to be on FPR
377*0fca6ea1SDimitry Andric     // instead of blind map every scalar to GPR.
378*0fca6ea1SDimitry Andric     bool IsFP = any_of(MRI.use_nodbg_instructions(cast<GLoad>(MI).getDstReg()),
379*0fca6ea1SDimitry Andric                        [&](const MachineInstr &UseMI) {
380*0fca6ea1SDimitry Andric                          // If we have at least one direct use in a FP
381*0fca6ea1SDimitry Andric                          // instruction, assume this was a floating point load
382*0fca6ea1SDimitry Andric                          // in the IR. If it was not, we would have had a
383*0fca6ea1SDimitry Andric                          // bitcast before reaching that instruction.
384*0fca6ea1SDimitry Andric                          return onlyUsesFP(UseMI, MRI, TRI);
385*0fca6ea1SDimitry Andric                        });
386*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, IsFP, OpRegBankIdx);
387*0fca6ea1SDimitry Andric     break;
388*0fca6ea1SDimitry Andric   }
389*0fca6ea1SDimitry Andric   case TargetOpcode::G_STORE: {
390*0fca6ea1SDimitry Andric     // Check if that store is fed by fp instructions.
391*0fca6ea1SDimitry Andric     Register VReg = cast<GStore>(MI).getValueReg();
392*0fca6ea1SDimitry Andric     if (!VReg)
393*0fca6ea1SDimitry Andric       break;
394*0fca6ea1SDimitry Andric     MachineInstr *DefMI = MRI.getVRegDef(VReg);
395*0fca6ea1SDimitry Andric     bool IsFP = onlyDefinesFP(*DefMI, MRI, TRI);
396*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, IsFP, OpRegBankIdx);
397*0fca6ea1SDimitry Andric     break;
398*0fca6ea1SDimitry Andric   }
3995f757f3fSDimitry Andric   default:
400*0fca6ea1SDimitry Andric     // Track the bank of each register, use NotFP mapping (all scalars in
401*0fca6ea1SDimitry Andric     // GPRs)
402*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ false, OpRegBankIdx);
4035f757f3fSDimitry Andric     break;
4045f757f3fSDimitry Andric   }
4055f757f3fSDimitry Andric 
4065f757f3fSDimitry Andric   // Finally construct the computed mapping.
4075f757f3fSDimitry Andric   SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
4085f757f3fSDimitry Andric   if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
4095f757f3fSDimitry Andric     return getInvalidInstructionMapping();
4105f757f3fSDimitry Andric 
4115f757f3fSDimitry Andric   return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
4125f757f3fSDimitry Andric                                getOperandsMapping(OpdsMapping), NumOperands);
4135f757f3fSDimitry Andric }
4145f757f3fSDimitry Andric 
4155f757f3fSDimitry Andric void X86RegisterBankInfo::applyMappingImpl(
4165f757f3fSDimitry Andric     MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
4175f757f3fSDimitry Andric   return applyDefaultMapping(OpdMapper);
4185f757f3fSDimitry Andric }
4195f757f3fSDimitry Andric 
4205f757f3fSDimitry Andric RegisterBankInfo::InstructionMappings
4215f757f3fSDimitry Andric X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
4225f757f3fSDimitry Andric 
4235f757f3fSDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
4245f757f3fSDimitry Andric   const TargetSubtargetInfo &STI = MF.getSubtarget();
4255f757f3fSDimitry Andric   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
4265f757f3fSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
4275f757f3fSDimitry Andric 
4285f757f3fSDimitry Andric   switch (MI.getOpcode()) {
4295f757f3fSDimitry Andric   case TargetOpcode::G_LOAD:
4305f757f3fSDimitry Andric   case TargetOpcode::G_STORE:
4315f757f3fSDimitry Andric   case TargetOpcode::G_IMPLICIT_DEF: {
432*0fca6ea1SDimitry Andric     // we going to try to map 32/64/80 bit to PMI_FP32/PMI_FP64/PMI_FP80
4335f757f3fSDimitry Andric     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
434*0fca6ea1SDimitry Andric     if (Size != 32 && Size != 64 && Size != 80)
4355f757f3fSDimitry Andric       break;
4365f757f3fSDimitry Andric 
4375f757f3fSDimitry Andric     unsigned NumOperands = MI.getNumOperands();
4385f757f3fSDimitry Andric 
4395f757f3fSDimitry Andric     // Track the bank of each register, use FP mapping (all scalars in VEC)
4405f757f3fSDimitry Andric     SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
441*0fca6ea1SDimitry Andric     getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
4425f757f3fSDimitry Andric 
4435f757f3fSDimitry Andric     // Finally construct the computed mapping.
4445f757f3fSDimitry Andric     SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
4455f757f3fSDimitry Andric     if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
4465f757f3fSDimitry Andric       break;
4475f757f3fSDimitry Andric 
4485f757f3fSDimitry Andric     const RegisterBankInfo::InstructionMapping &Mapping = getInstructionMapping(
4495f757f3fSDimitry Andric         /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
4505f757f3fSDimitry Andric     InstructionMappings AltMappings;
4515f757f3fSDimitry Andric     AltMappings.push_back(&Mapping);
4525f757f3fSDimitry Andric     return AltMappings;
4535f757f3fSDimitry Andric   }
4545f757f3fSDimitry Andric   default:
4555f757f3fSDimitry Andric     break;
4565f757f3fSDimitry Andric   }
4575f757f3fSDimitry Andric   return RegisterBankInfo::getInstrAlternativeMappings(MI);
4585f757f3fSDimitry Andric }
459