1 //===- ARMRegisterBankInfo.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 RegisterBankInfo class for ARM. 11 /// \todo This should be generated by TableGen. 12 //===----------------------------------------------------------------------===// 13 14 #include "ARMRegisterBankInfo.h" 15 #include "ARMInstrInfo.h" // For the register classes 16 #include "llvm/CodeGen/GlobalISel/RegisterBank.h" 17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" 18 #include "llvm/CodeGen/MachineRegisterInfo.h" 19 #include "llvm/Target/TargetRegisterInfo.h" 20 21 #define GET_TARGET_REGBANK_IMPL 22 #include "ARMGenRegisterBank.inc" 23 24 using namespace llvm; 25 26 #ifndef LLVM_BUILD_GLOBAL_ISEL 27 #error "You shouldn't build this" 28 #endif 29 30 // FIXME: TableGen this. 31 // If it grows too much and TableGen still isn't ready to do the job, extract it 32 // into an ARMGenRegisterBankInfo.def (similar to AArch64). 33 namespace llvm { 34 namespace ARM { 35 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank}; 36 RegisterBankInfo::PartialMapping SPRPartialMapping{0, 32, FPRRegBank}; 37 RegisterBankInfo::PartialMapping DPRPartialMapping{0, 64, FPRRegBank}; 38 39 // FIXME: Add the mapping for S(2n+1) as {32, 64, FPRRegBank} 40 RegisterBankInfo::ValueMapping ValueMappings[] = { 41 {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, 42 {&SPRPartialMapping, 1}, {&SPRPartialMapping, 1}, {&SPRPartialMapping, 1}, 43 {&DPRPartialMapping, 1}, {&DPRPartialMapping, 1}, {&DPRPartialMapping, 1}}; 44 } // end namespace arm 45 } // end namespace llvm 46 47 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 48 : ARMGenRegisterBankInfo() { 49 static bool AlreadyInit = false; 50 // We have only one set of register banks, whatever the subtarget 51 // is. Therefore, the initialization of the RegBanks table should be 52 // done only once. Indeed the table of all register banks 53 // (ARM::RegBanks) is unique in the compiler. At some point, it 54 // will get tablegen'ed and the whole constructor becomes empty. 55 if (AlreadyInit) 56 return; 57 AlreadyInit = true; 58 59 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 60 (void)RBGPR; 61 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 62 63 // Initialize the GPR bank. 64 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 65 "Subclass not added?"); 66 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 67 "Subclass not added?"); 68 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 69 "Subclass not added?"); 70 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 71 "Subclass not added?"); 72 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 73 "Subclass not added?"); 74 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 75 "Subclass not added?"); 76 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 77 "Subclass not added?"); 78 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 79 } 80 81 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 82 const TargetRegisterClass &RC) const { 83 using namespace ARM; 84 85 switch (RC.getID()) { 86 case GPRRegClassID: 87 case GPRnopcRegClassID: 88 case tGPR_and_tcGPRRegClassID: 89 return getRegBank(ARM::GPRRegBankID); 90 case SPR_8RegClassID: 91 case SPRRegClassID: 92 case DPR_8RegClassID: 93 case DPRRegClassID: 94 return getRegBank(ARM::FPRRegBankID); 95 default: 96 llvm_unreachable("Unsupported register kind"); 97 } 98 99 llvm_unreachable("Switch should handle all register classes"); 100 } 101 102 RegisterBankInfo::InstructionMapping 103 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 104 auto Opc = MI.getOpcode(); 105 106 // Try the default logic for non-generic instructions that are either copies 107 // or already have some operands assigned to banks. 108 if (!isPreISelGenericOpcode(Opc)) { 109 InstructionMapping Mapping = getInstrMappingImpl(MI); 110 if (Mapping.isValid()) 111 return Mapping; 112 } 113 114 using namespace TargetOpcode; 115 116 const MachineFunction &MF = *MI.getParent()->getParent(); 117 const MachineRegisterInfo &MRI = MF.getRegInfo(); 118 LLT Ty = MRI.getType(MI.getOperand(0).getReg()); 119 120 unsigned NumOperands = MI.getNumOperands(); 121 const ValueMapping *OperandsMapping = &ARM::ValueMappings[0]; 122 123 switch (Opc) { 124 case G_ADD: 125 case G_SEXT: 126 case G_ZEXT: 127 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 128 // the real world we would use different mappings. 129 OperandsMapping = &ARM::ValueMappings[0]; 130 break; 131 case G_LOAD: 132 OperandsMapping = Ty.getSizeInBits() == 64 133 ? getOperandsMapping({&ARM::ValueMappings[6], 134 &ARM::ValueMappings[0]}) 135 : &ARM::ValueMappings[0]; 136 break; 137 case G_FADD: 138 assert((Ty.getSizeInBits() == 32 || Ty.getSizeInBits() == 64) && 139 "Unsupported size for G_FADD"); 140 OperandsMapping = Ty.getSizeInBits() == 64 ? &ARM::ValueMappings[6] 141 : &ARM::ValueMappings[3]; 142 break; 143 case G_FRAME_INDEX: 144 OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr}); 145 break; 146 case G_SEQUENCE: { 147 // We only support G_SEQUENCE for creating a double precision floating point 148 // value out of two GPRs. 149 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 150 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg()); 151 if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 || 152 Ty2.getSizeInBits() != 32) 153 return InstructionMapping{}; 154 OperandsMapping = 155 getOperandsMapping({&ARM::ValueMappings[6], &ARM::ValueMappings[0], 156 nullptr, &ARM::ValueMappings[0], nullptr}); 157 break; 158 } 159 case G_EXTRACT: { 160 // We only support G_EXTRACT for splitting a double precision floating point 161 // value into two GPRs. 162 LLT Ty1 = MRI.getType(MI.getOperand(1).getReg()); 163 LLT Ty2 = MRI.getType(MI.getOperand(2).getReg()); 164 if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 || 165 Ty2.getSizeInBits() != 64) 166 return InstructionMapping{}; 167 OperandsMapping = 168 getOperandsMapping({&ARM::ValueMappings[0], &ARM::ValueMappings[0], 169 &ARM::ValueMappings[6], nullptr, nullptr}); 170 break; 171 } 172 default: 173 return InstructionMapping{}; 174 } 175 176 return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping, 177 NumOperands}; 178 } 179