1d88c1a5aSDimitry Andric //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
2d88c1a5aSDimitry Andric //
3d88c1a5aSDimitry Andric //                     The LLVM Compiler Infrastructure
4d88c1a5aSDimitry Andric //
5d88c1a5aSDimitry Andric // This file is distributed under the University of Illinois Open Source
6d88c1a5aSDimitry Andric // License. See LICENSE.TXT for details.
7d88c1a5aSDimitry Andric //
8d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
9d88c1a5aSDimitry Andric /// \file
10d88c1a5aSDimitry Andric /// This file implements the targeting of the RegisterBankInfo class for ARM.
11d88c1a5aSDimitry Andric /// \todo This should be generated by TableGen.
12d88c1a5aSDimitry Andric //===----------------------------------------------------------------------===//
13d88c1a5aSDimitry Andric 
14d88c1a5aSDimitry Andric #include "ARMRegisterBankInfo.h"
15d88c1a5aSDimitry Andric #include "ARMInstrInfo.h" // For the register classes
167a7e6055SDimitry Andric #include "ARMSubtarget.h"
17d88c1a5aSDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
18d88c1a5aSDimitry Andric #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
19d88c1a5aSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
202cab237bSDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
21d88c1a5aSDimitry Andric 
227a7e6055SDimitry Andric #define GET_TARGET_REGBANK_IMPL
237a7e6055SDimitry Andric #include "ARMGenRegisterBank.inc"
247a7e6055SDimitry Andric 
25d88c1a5aSDimitry Andric using namespace llvm;
26d88c1a5aSDimitry Andric 
27d88c1a5aSDimitry Andric // FIXME: TableGen this.
28d88c1a5aSDimitry Andric // If it grows too much and TableGen still isn't ready to do the job, extract it
29d88c1a5aSDimitry Andric // into an ARMGenRegisterBankInfo.def (similar to AArch64).
30d88c1a5aSDimitry Andric namespace llvm {
31d88c1a5aSDimitry Andric namespace ARM {
327a7e6055SDimitry Andric enum PartialMappingIdx {
337a7e6055SDimitry Andric   PMI_GPR,
347a7e6055SDimitry Andric   PMI_SPR,
357a7e6055SDimitry Andric   PMI_DPR,
367a7e6055SDimitry Andric   PMI_Min = PMI_GPR,
37f1a29dd3SDimitry Andric };
38f1a29dd3SDimitry Andric 
397a7e6055SDimitry Andric RegisterBankInfo::PartialMapping PartMappings[]{
407a7e6055SDimitry Andric     // GPR Partial Mapping
417a7e6055SDimitry Andric     {0, 32, GPRRegBank},
427a7e6055SDimitry Andric     // SPR Partial Mapping
437a7e6055SDimitry Andric     {0, 32, FPRRegBank},
447a7e6055SDimitry Andric     // DPR Partial Mapping
457a7e6055SDimitry Andric     {0, 64, FPRRegBank},
467a7e6055SDimitry Andric };
47d88c1a5aSDimitry Andric 
487a7e6055SDimitry Andric #ifndef NDEBUG
checkPartMapping(const RegisterBankInfo::PartialMapping & PM,unsigned Start,unsigned Length,unsigned RegBankID)497a7e6055SDimitry Andric static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM,
507a7e6055SDimitry Andric                              unsigned Start, unsigned Length,
517a7e6055SDimitry Andric                              unsigned RegBankID) {
527a7e6055SDimitry Andric   return PM.StartIdx == Start && PM.Length == Length &&
537a7e6055SDimitry Andric          PM.RegBank->getID() == RegBankID;
547a7e6055SDimitry Andric }
557a7e6055SDimitry Andric 
checkPartialMappings()567a7e6055SDimitry Andric static void checkPartialMappings() {
577a7e6055SDimitry Andric   assert(
587a7e6055SDimitry Andric       checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
597a7e6055SDimitry Andric       "Wrong mapping for GPR");
607a7e6055SDimitry Andric   assert(
617a7e6055SDimitry Andric       checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
627a7e6055SDimitry Andric       "Wrong mapping for SPR");
637a7e6055SDimitry Andric   assert(
647a7e6055SDimitry Andric       checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
657a7e6055SDimitry Andric       "Wrong mapping for DPR");
667a7e6055SDimitry Andric }
677a7e6055SDimitry Andric #endif
687a7e6055SDimitry Andric 
697a7e6055SDimitry Andric enum ValueMappingIdx {
707a7e6055SDimitry Andric   InvalidIdx = 0,
717a7e6055SDimitry Andric   GPR3OpsIdx = 1,
727a7e6055SDimitry Andric   SPR3OpsIdx = 4,
737a7e6055SDimitry Andric   DPR3OpsIdx = 7,
747a7e6055SDimitry Andric };
75d88c1a5aSDimitry Andric 
76d88c1a5aSDimitry Andric RegisterBankInfo::ValueMapping ValueMappings[] = {
777a7e6055SDimitry Andric     // invalid
787a7e6055SDimitry Andric     {nullptr, 0},
797a7e6055SDimitry Andric     // 3 ops in GPRs
807a7e6055SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
817a7e6055SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
827a7e6055SDimitry Andric     {&PartMappings[PMI_GPR - PMI_Min], 1},
837a7e6055SDimitry Andric     // 3 ops in SPRs
847a7e6055SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
857a7e6055SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
867a7e6055SDimitry Andric     {&PartMappings[PMI_SPR - PMI_Min], 1},
877a7e6055SDimitry Andric     // 3 ops in DPRs
887a7e6055SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
897a7e6055SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1},
907a7e6055SDimitry Andric     {&PartMappings[PMI_DPR - PMI_Min], 1}};
917a7e6055SDimitry Andric 
927a7e6055SDimitry Andric #ifndef NDEBUG
checkValueMapping(const RegisterBankInfo::ValueMapping & VM,RegisterBankInfo::PartialMapping * BreakDown)937a7e6055SDimitry Andric static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM,
947a7e6055SDimitry Andric                               RegisterBankInfo::PartialMapping *BreakDown) {
957a7e6055SDimitry Andric   return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
967a7e6055SDimitry Andric }
977a7e6055SDimitry Andric 
checkValueMappings()987a7e6055SDimitry Andric static void checkValueMappings() {
997a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
1007a7e6055SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1017a7e6055SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1027a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
1037a7e6055SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1047a7e6055SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1057a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
1067a7e6055SDimitry Andric                            &PartMappings[PMI_GPR - PMI_Min]) &&
1077a7e6055SDimitry Andric          "Wrong value mapping for 3 GPR ops instruction");
1087a7e6055SDimitry Andric 
1097a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
1107a7e6055SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1117a7e6055SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1127a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
1137a7e6055SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1147a7e6055SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1157a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
1167a7e6055SDimitry Andric                            &PartMappings[PMI_SPR - PMI_Min]) &&
1177a7e6055SDimitry Andric          "Wrong value mapping for 3 SPR ops instruction");
1187a7e6055SDimitry Andric 
1197a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
1207a7e6055SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1217a7e6055SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1227a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
1237a7e6055SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1247a7e6055SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1257a7e6055SDimitry Andric   assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
1267a7e6055SDimitry Andric                            &PartMappings[PMI_DPR - PMI_Min]) &&
1277a7e6055SDimitry Andric          "Wrong value mapping for 3 DPR ops instruction");
1287a7e6055SDimitry Andric }
1297a7e6055SDimitry Andric #endif
130d88c1a5aSDimitry Andric } // end namespace arm
131d88c1a5aSDimitry Andric } // end namespace llvm
132d88c1a5aSDimitry Andric 
ARMRegisterBankInfo(const TargetRegisterInfo & TRI)133d88c1a5aSDimitry Andric ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
1347a7e6055SDimitry Andric     : ARMGenRegisterBankInfo() {
135d88c1a5aSDimitry Andric   static bool AlreadyInit = false;
136d88c1a5aSDimitry Andric   // We have only one set of register banks, whatever the subtarget
137d88c1a5aSDimitry Andric   // is. Therefore, the initialization of the RegBanks table should be
138d88c1a5aSDimitry Andric   // done only once. Indeed the table of all register banks
139d88c1a5aSDimitry Andric   // (ARM::RegBanks) is unique in the compiler. At some point, it
140d88c1a5aSDimitry Andric   // will get tablegen'ed and the whole constructor becomes empty.
141d88c1a5aSDimitry Andric   if (AlreadyInit)
142d88c1a5aSDimitry Andric     return;
143d88c1a5aSDimitry Andric   AlreadyInit = true;
144d88c1a5aSDimitry Andric 
145d88c1a5aSDimitry Andric   const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
146d88c1a5aSDimitry Andric   (void)RBGPR;
147d88c1a5aSDimitry Andric   assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
148f1a29dd3SDimitry Andric 
149f1a29dd3SDimitry Andric   // Initialize the GPR bank.
150d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
151d88c1a5aSDimitry Andric          "Subclass not added?");
152d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
153d88c1a5aSDimitry Andric          "Subclass not added?");
154d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
155d88c1a5aSDimitry Andric          "Subclass not added?");
156d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
157d88c1a5aSDimitry Andric          "Subclass not added?");
158d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
159d88c1a5aSDimitry Andric          "Subclass not added?");
160d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
161d88c1a5aSDimitry Andric          "Subclass not added?");
162d88c1a5aSDimitry Andric   assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
163d88c1a5aSDimitry Andric          "Subclass not added?");
164d88c1a5aSDimitry Andric   assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
1657a7e6055SDimitry Andric 
1667a7e6055SDimitry Andric #ifndef NDEBUG
1677a7e6055SDimitry Andric   ARM::checkPartialMappings();
1687a7e6055SDimitry Andric   ARM::checkValueMappings();
1697a7e6055SDimitry Andric #endif
170d88c1a5aSDimitry Andric }
171d88c1a5aSDimitry Andric 
getRegBankFromRegClass(const TargetRegisterClass & RC) const172d88c1a5aSDimitry Andric const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass(
173d88c1a5aSDimitry Andric     const TargetRegisterClass &RC) const {
174d88c1a5aSDimitry Andric   using namespace ARM;
175d88c1a5aSDimitry Andric 
176d88c1a5aSDimitry Andric   switch (RC.getID()) {
177d88c1a5aSDimitry Andric   case GPRRegClassID:
1784ba319b5SDimitry Andric   case GPRwithAPSRRegClassID:
1797a7e6055SDimitry Andric   case GPRnopcRegClassID:
1804ba319b5SDimitry Andric   case rGPRRegClassID:
1817a7e6055SDimitry Andric   case GPRspRegClassID:
182d88c1a5aSDimitry Andric   case tGPR_and_tcGPRRegClassID:
1834ba319b5SDimitry Andric   case tcGPRRegClassID:
1847a7e6055SDimitry Andric   case tGPRRegClassID:
185d88c1a5aSDimitry Andric     return getRegBank(ARM::GPRRegBankID);
1864ba319b5SDimitry Andric   case HPRRegClassID:
1877a7e6055SDimitry Andric   case SPR_8RegClassID:
1887a7e6055SDimitry Andric   case SPRRegClassID:
1897a7e6055SDimitry Andric   case DPR_8RegClassID:
1907a7e6055SDimitry Andric   case DPRRegClassID:
1914ba319b5SDimitry Andric   case QPRRegClassID:
1927a7e6055SDimitry Andric     return getRegBank(ARM::FPRRegBankID);
193d88c1a5aSDimitry Andric   default:
194d88c1a5aSDimitry Andric     llvm_unreachable("Unsupported register kind");
195d88c1a5aSDimitry Andric   }
196d88c1a5aSDimitry Andric 
197d88c1a5aSDimitry Andric   llvm_unreachable("Switch should handle all register classes");
198d88c1a5aSDimitry Andric }
199d88c1a5aSDimitry Andric 
2000f5676f4SDimitry Andric const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const201d88c1a5aSDimitry Andric ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
202d88c1a5aSDimitry Andric   auto Opc = MI.getOpcode();
203d88c1a5aSDimitry Andric 
204d88c1a5aSDimitry Andric   // Try the default logic for non-generic instructions that are either copies
205d88c1a5aSDimitry Andric   // or already have some operands assigned to banks.
2062cab237bSDimitry Andric   if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
2070f5676f4SDimitry Andric     const InstructionMapping &Mapping = getInstrMappingImpl(MI);
208d88c1a5aSDimitry Andric     if (Mapping.isValid())
209d88c1a5aSDimitry Andric       return Mapping;
210d88c1a5aSDimitry Andric   }
211d88c1a5aSDimitry Andric 
212d88c1a5aSDimitry Andric   using namespace TargetOpcode;
213d88c1a5aSDimitry Andric 
2147a7e6055SDimitry Andric   const MachineFunction &MF = *MI.getParent()->getParent();
2157a7e6055SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
216d88c1a5aSDimitry Andric   unsigned NumOperands = MI.getNumOperands();
2177a7e6055SDimitry Andric   const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
218d88c1a5aSDimitry Andric 
219d88c1a5aSDimitry Andric   switch (Opc) {
220d88c1a5aSDimitry Andric   case G_ADD:
2216bc11b14SDimitry Andric   case G_SUB:
2226bc11b14SDimitry Andric   case G_MUL:
223db17bf38SDimitry Andric   case G_AND:
224db17bf38SDimitry Andric   case G_OR:
225db17bf38SDimitry Andric   case G_XOR:
2262cab237bSDimitry Andric   case G_LSHR:
2272cab237bSDimitry Andric   case G_ASHR:
2282cab237bSDimitry Andric   case G_SHL:
22951690af2SDimitry Andric   case G_SDIV:
23051690af2SDimitry Andric   case G_UDIV:
2317a7e6055SDimitry Andric   case G_SEXT:
2327a7e6055SDimitry Andric   case G_ZEXT:
2335517e702SDimitry Andric   case G_ANYEXT:
2347a7e6055SDimitry Andric   case G_GEP:
235da09e106SDimitry Andric   case G_INTTOPTR:
236da09e106SDimitry Andric   case G_PTRTOINT:
237*b5893f02SDimitry Andric   case G_CTLZ:
238d88c1a5aSDimitry Andric     // FIXME: We're abusing the fact that everything lives in a GPR for now; in
239d88c1a5aSDimitry Andric     // the real world we would use different mappings.
2407a7e6055SDimitry Andric     OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
241d88c1a5aSDimitry Andric     break;
242da09e106SDimitry Andric   case G_TRUNC: {
243da09e106SDimitry Andric     // In some cases we may end up with a G_TRUNC from a 64-bit value to a
244da09e106SDimitry Andric     // 32-bit value. This isn't a real floating point trunc (that would be a
245da09e106SDimitry Andric     // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
246da09e106SDimitry Andric     // because the legalizer doesn't distinguish between integer and floating
247da09e106SDimitry Andric     // point values so it may leave some 64-bit integers un-narrowed. Until we
248da09e106SDimitry Andric     // have a more principled solution that doesn't let such things sneak all
249da09e106SDimitry Andric     // the way to this point, just map the source to a DPR and the destination
250da09e106SDimitry Andric     // to a GPR.
251da09e106SDimitry Andric     LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
252da09e106SDimitry Andric     OperandsMapping =
253da09e106SDimitry Andric         LargeTy.getSizeInBits() <= 32
254da09e106SDimitry Andric             ? &ARM::ValueMappings[ARM::GPR3OpsIdx]
255da09e106SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
256da09e106SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]});
257da09e106SDimitry Andric     break;
258da09e106SDimitry Andric   }
2597a7e6055SDimitry Andric   case G_LOAD:
260c4394386SDimitry Andric   case G_STORE: {
261c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2627a7e6055SDimitry Andric     OperandsMapping =
2637a7e6055SDimitry Andric         Ty.getSizeInBits() == 64
2647a7e6055SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
2657a7e6055SDimitry Andric                                   &ARM::ValueMappings[ARM::GPR3OpsIdx]})
2667a7e6055SDimitry Andric             : &ARM::ValueMappings[ARM::GPR3OpsIdx];
2677a7e6055SDimitry Andric     break;
268c4394386SDimitry Andric   }
2692cab237bSDimitry Andric   case G_FADD:
2702cab237bSDimitry Andric   case G_FSUB:
2712cab237bSDimitry Andric   case G_FMUL:
2724ba319b5SDimitry Andric   case G_FDIV:
2734ba319b5SDimitry Andric   case G_FNEG: {
274c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2757a7e6055SDimitry Andric     OperandsMapping =Ty.getSizeInBits() == 64
2767a7e6055SDimitry Andric                           ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
2777a7e6055SDimitry Andric                           : &ARM::ValueMappings[ARM::SPR3OpsIdx];
2787a7e6055SDimitry Andric     break;
279c4394386SDimitry Andric   }
2804ba319b5SDimitry Andric   case G_FMA: {
2814ba319b5SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
2824ba319b5SDimitry Andric     OperandsMapping =
2834ba319b5SDimitry Andric         Ty.getSizeInBits() == 64
2844ba319b5SDimitry Andric             ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
2854ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
2864ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx],
2874ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::DPR3OpsIdx]})
2884ba319b5SDimitry Andric             : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
2894ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
2904ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx],
2914ba319b5SDimitry Andric                                   &ARM::ValueMappings[ARM::SPR3OpsIdx]});
2924ba319b5SDimitry Andric     break;
2934ba319b5SDimitry Andric   }
2944ba319b5SDimitry Andric   case G_FPEXT: {
2954ba319b5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
2964ba319b5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
2974ba319b5SDimitry Andric     if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
2984ba319b5SDimitry Andric       OperandsMapping =
2994ba319b5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3004ba319b5SDimitry Andric                               &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3014ba319b5SDimitry Andric     break;
3024ba319b5SDimitry Andric   }
3034ba319b5SDimitry Andric   case G_FPTRUNC: {
3044ba319b5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3054ba319b5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3064ba319b5SDimitry Andric     if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
3074ba319b5SDimitry Andric       OperandsMapping =
3084ba319b5SDimitry Andric           getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3094ba319b5SDimitry Andric                               &ARM::ValueMappings[ARM::DPR3OpsIdx]});
3104ba319b5SDimitry Andric     break;
3114ba319b5SDimitry Andric   }
3124ba319b5SDimitry Andric   case G_FPTOSI:
3134ba319b5SDimitry Andric   case G_FPTOUI: {
3144ba319b5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3154ba319b5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3164ba319b5SDimitry Andric     if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
3174ba319b5SDimitry Andric         ToTy.getSizeInBits() == 32)
3184ba319b5SDimitry Andric       OperandsMapping =
3194ba319b5SDimitry Andric           FromTy.getSizeInBits() == 64
3204ba319b5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3214ba319b5SDimitry Andric                                     &ARM::ValueMappings[ARM::DPR3OpsIdx]})
3224ba319b5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
3234ba319b5SDimitry Andric                                     &ARM::ValueMappings[ARM::SPR3OpsIdx]});
3244ba319b5SDimitry Andric     break;
3254ba319b5SDimitry Andric   }
3264ba319b5SDimitry Andric   case G_SITOFP:
3274ba319b5SDimitry Andric   case G_UITOFP: {
3284ba319b5SDimitry Andric     LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
3294ba319b5SDimitry Andric     LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
3304ba319b5SDimitry Andric     if (FromTy.getSizeInBits() == 32 &&
3314ba319b5SDimitry Andric         (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
3324ba319b5SDimitry Andric       OperandsMapping =
3334ba319b5SDimitry Andric           ToTy.getSizeInBits() == 64
3344ba319b5SDimitry Andric               ? getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
3354ba319b5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]})
3364ba319b5SDimitry Andric               : getOperandsMapping({&ARM::ValueMappings[ARM::SPR3OpsIdx],
3374ba319b5SDimitry Andric                                     &ARM::ValueMappings[ARM::GPR3OpsIdx]});
3384ba319b5SDimitry Andric     break;
3394ba319b5SDimitry Andric   }
3407a7e6055SDimitry Andric   case G_CONSTANT:
341d88c1a5aSDimitry Andric   case G_FRAME_INDEX:
3422cab237bSDimitry Andric   case G_GLOBAL_VALUE:
3437a7e6055SDimitry Andric     OperandsMapping =
3447a7e6055SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
345d88c1a5aSDimitry Andric     break;
346a580b014SDimitry Andric   case G_SELECT: {
347c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
348b40b48b8SDimitry Andric     (void)Ty;
349a580b014SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
350a580b014SDimitry Andric     (void)Ty2;
351a580b014SDimitry Andric     assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
352a580b014SDimitry Andric     assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
353a580b014SDimitry Andric     OperandsMapping =
354a580b014SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
355a580b014SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
356a580b014SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
357a580b014SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
358a580b014SDimitry Andric     break;
359a580b014SDimitry Andric   }
360edd7eaddSDimitry Andric   case G_ICMP: {
361edd7eaddSDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
362edd7eaddSDimitry Andric     (void)Ty2;
363edd7eaddSDimitry Andric     assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
364edd7eaddSDimitry Andric     OperandsMapping =
365edd7eaddSDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
366edd7eaddSDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
367edd7eaddSDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
368edd7eaddSDimitry Andric     break;
369edd7eaddSDimitry Andric   }
370c4394386SDimitry Andric   case G_FCMP: {
371c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
372b40b48b8SDimitry Andric     (void)Ty;
373c4394386SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
374c4394386SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
375c4394386SDimitry Andric     (void)Ty2;
376c4394386SDimitry Andric     assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
377c4394386SDimitry Andric     assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
378c4394386SDimitry Andric            "Mismatched operand sizes for G_FCMP");
379c4394386SDimitry Andric 
380c4394386SDimitry Andric     unsigned Size = Ty1.getSizeInBits();
381c4394386SDimitry Andric     assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
382c4394386SDimitry Andric 
383c4394386SDimitry Andric     auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
384c4394386SDimitry Andric                                       : &ARM::ValueMappings[ARM::DPR3OpsIdx];
385c4394386SDimitry Andric     OperandsMapping =
386c4394386SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr,
387c4394386SDimitry Andric                             FPRValueMapping, FPRValueMapping});
388c4394386SDimitry Andric     break;
389c4394386SDimitry Andric   }
390db17bf38SDimitry Andric   case G_MERGE_VALUES: {
391db17bf38SDimitry Andric     // We only support G_MERGE_VALUES for creating a double precision floating
392db17bf38SDimitry Andric     // point value out of two GPRs.
393c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
3947a7e6055SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
395db17bf38SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
3967a7e6055SDimitry Andric     if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
3977a7e6055SDimitry Andric         Ty2.getSizeInBits() != 32)
3980f5676f4SDimitry Andric       return getInvalidInstructionMapping();
3997a7e6055SDimitry Andric     OperandsMapping =
4007a7e6055SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::DPR3OpsIdx],
401db17bf38SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
402db17bf38SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx]});
4037a7e6055SDimitry Andric     break;
4047a7e6055SDimitry Andric   }
405db17bf38SDimitry Andric   case G_UNMERGE_VALUES: {
406db17bf38SDimitry Andric     // We only support G_UNMERGE_VALUES for splitting a double precision
407db17bf38SDimitry Andric     // floating point value into two GPRs.
408c4394386SDimitry Andric     LLT Ty = MRI.getType(MI.getOperand(0).getReg());
4097a7e6055SDimitry Andric     LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
410db17bf38SDimitry Andric     LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
411db17bf38SDimitry Andric     if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
412db17bf38SDimitry Andric         Ty2.getSizeInBits() != 64)
4130f5676f4SDimitry Andric       return getInvalidInstructionMapping();
414db17bf38SDimitry Andric     OperandsMapping =
415db17bf38SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx],
416db17bf38SDimitry Andric                             &ARM::ValueMappings[ARM::GPR3OpsIdx],
417db17bf38SDimitry Andric                             &ARM::ValueMappings[ARM::DPR3OpsIdx]});
4187a7e6055SDimitry Andric     break;
4197a7e6055SDimitry Andric   }
420b40b48b8SDimitry Andric   case G_BR:
421b40b48b8SDimitry Andric     OperandsMapping = getOperandsMapping({nullptr});
422b40b48b8SDimitry Andric     break;
423b40b48b8SDimitry Andric   case G_BRCOND:
424b40b48b8SDimitry Andric     OperandsMapping =
425b40b48b8SDimitry Andric         getOperandsMapping({&ARM::ValueMappings[ARM::GPR3OpsIdx], nullptr});
426b40b48b8SDimitry Andric     break;
427d88c1a5aSDimitry Andric   default:
4280f5676f4SDimitry Andric     return getInvalidInstructionMapping();
429d88c1a5aSDimitry Andric   }
430d88c1a5aSDimitry Andric 
4317a7e6055SDimitry Andric #ifndef NDEBUG
4327a7e6055SDimitry Andric   for (unsigned i = 0; i < NumOperands; i++) {
4337a7e6055SDimitry Andric     for (const auto &Mapping : OperandsMapping[i]) {
4347a7e6055SDimitry Andric       assert(
4357a7e6055SDimitry Andric           (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
4367a7e6055SDimitry Andric            MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
4377a7e6055SDimitry Andric           "Trying to use floating point register bank on target without vfp");
4387a7e6055SDimitry Andric     }
4397a7e6055SDimitry Andric   }
4407a7e6055SDimitry Andric #endif
4417a7e6055SDimitry Andric 
4420f5676f4SDimitry Andric   return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
4430f5676f4SDimitry Andric                                NumOperands);
444d88c1a5aSDimitry Andric }
445