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 FPRPartialMapping{0, 32, FPRRegBank}; 37 38 RegisterBankInfo::ValueMapping ValueMappings[] = { 39 {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, 40 {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}, {&FPRPartialMapping, 1}}; 41 } // end namespace arm 42 } // end namespace llvm 43 44 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 45 : ARMGenRegisterBankInfo() { 46 static bool AlreadyInit = false; 47 // We have only one set of register banks, whatever the subtarget 48 // is. Therefore, the initialization of the RegBanks table should be 49 // done only once. Indeed the table of all register banks 50 // (ARM::RegBanks) is unique in the compiler. At some point, it 51 // will get tablegen'ed and the whole constructor becomes empty. 52 if (AlreadyInit) 53 return; 54 AlreadyInit = true; 55 56 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 57 (void)RBGPR; 58 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 59 60 // Initialize the GPR bank. 61 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 62 "Subclass not added?"); 63 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 64 "Subclass not added?"); 65 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 66 "Subclass not added?"); 67 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 68 "Subclass not added?"); 69 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 70 "Subclass not added?"); 71 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 72 "Subclass not added?"); 73 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 74 "Subclass not added?"); 75 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 76 } 77 78 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 79 const TargetRegisterClass &RC) const { 80 using namespace ARM; 81 82 switch (RC.getID()) { 83 case GPRRegClassID: 84 case GPRnopcRegClassID: 85 case tGPR_and_tcGPRRegClassID: 86 return getRegBank(ARM::GPRRegBankID); 87 case SPR_8RegClassID: 88 case SPRRegClassID: 89 return getRegBank(ARM::FPRRegBankID); 90 default: 91 llvm_unreachable("Unsupported register kind"); 92 } 93 94 llvm_unreachable("Switch should handle all register classes"); 95 } 96 97 RegisterBankInfo::InstructionMapping 98 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 99 auto Opc = MI.getOpcode(); 100 101 // Try the default logic for non-generic instructions that are either copies 102 // or already have some operands assigned to banks. 103 if (!isPreISelGenericOpcode(Opc)) { 104 InstructionMapping Mapping = getInstrMappingImpl(MI); 105 if (Mapping.isValid()) 106 return Mapping; 107 } 108 109 using namespace TargetOpcode; 110 111 unsigned NumOperands = MI.getNumOperands(); 112 const ValueMapping *OperandsMapping = &ARM::ValueMappings[0]; 113 114 switch (Opc) { 115 case G_ADD: 116 case G_LOAD: 117 case G_SEXT: 118 case G_ZEXT: 119 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 120 // the real world we would use different mappings. 121 OperandsMapping = &ARM::ValueMappings[0]; 122 break; 123 case G_FADD: 124 OperandsMapping = &ARM::ValueMappings[3]; 125 break; 126 case G_FRAME_INDEX: 127 OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr}); 128 break; 129 default: 130 return InstructionMapping{}; 131 } 132 133 return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping, 134 NumOperands}; 135 } 136