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 using namespace llvm; 22 23 #ifndef LLVM_BUILD_GLOBAL_ISEL 24 #error "You shouldn't build this" 25 #endif 26 27 // FIXME: TableGen this. 28 // If it grows too much and TableGen still isn't ready to do the job, extract it 29 // into an ARMGenRegisterBankInfo.def (similar to AArch64). 30 namespace llvm { 31 namespace ARM { 32 const uint32_t GPRCoverageData[] = { 33 // Classes 0-31 34 (1u << ARM::GPRRegClassID) | (1u << ARM::GPRwithAPSRRegClassID) | 35 (1u << ARM::GPRnopcRegClassID) | (1u << ARM::rGPRRegClassID) | 36 (1u << ARM::hGPRRegClassID) | (1u << ARM::tGPRRegClassID) | 37 (1u << ARM::GPRnopc_and_hGPRRegClassID) | 38 (1u << ARM::hGPR_and_rGPRRegClassID) | (1u << ARM::tcGPRRegClassID) | 39 (1u << ARM::tGPR_and_tcGPRRegClassID) | (1u << ARM::GPRspRegClassID) | 40 (1u << ARM::hGPR_and_tcGPRRegClassID), 41 // Classes 32-63 42 0, 43 // Classes 64-96 44 0, 45 // FIXME: Some of the entries below this point can be safely removed once 46 // this is tablegenerated. It's only needed because of the hardcoded 47 // register class limit. 48 // Classes 97-128 49 0, 50 // Classes 129-160 51 0, 52 // Classes 161-192 53 0, 54 // Classes 193-224 55 0, 56 }; 57 58 RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData); 59 RegisterBank *RegBanks[] = {&GPRRegBank}; 60 61 RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank}; 62 63 RegisterBankInfo::ValueMapping ValueMappings[] = { 64 {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}}; 65 } // end namespace arm 66 } // end namespace llvm 67 68 ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) 69 : RegisterBankInfo(ARM::RegBanks, ARM::NumRegisterBanks) { 70 static bool AlreadyInit = false; 71 // We have only one set of register banks, whatever the subtarget 72 // is. Therefore, the initialization of the RegBanks table should be 73 // done only once. Indeed the table of all register banks 74 // (ARM::RegBanks) is unique in the compiler. At some point, it 75 // will get tablegen'ed and the whole constructor becomes empty. 76 if (AlreadyInit) 77 return; 78 AlreadyInit = true; 79 80 const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); 81 (void)RBGPR; 82 assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); 83 84 // Initialize the GPR bank. 85 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && 86 "Subclass not added?"); 87 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && 88 "Subclass not added?"); 89 assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && 90 "Subclass not added?"); 91 assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && 92 "Subclass not added?"); 93 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && 94 "Subclass not added?"); 95 assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && 96 "Subclass not added?"); 97 assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && 98 "Subclass not added?"); 99 assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); 100 } 101 102 const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( 103 const TargetRegisterClass &RC) const { 104 using namespace ARM; 105 106 switch (RC.getID()) { 107 case GPRRegClassID: 108 case tGPR_and_tcGPRRegClassID: 109 return getRegBank(ARM::GPRRegBankID); 110 default: 111 llvm_unreachable("Unsupported register kind"); 112 } 113 114 llvm_unreachable("Switch should handle all register classes"); 115 } 116 117 RegisterBankInfo::InstructionMapping 118 ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 119 auto Opc = MI.getOpcode(); 120 121 // Try the default logic for non-generic instructions that are either copies 122 // or already have some operands assigned to banks. 123 if (!isPreISelGenericOpcode(Opc)) { 124 InstructionMapping Mapping = getInstrMappingImpl(MI); 125 if (Mapping.isValid()) 126 return Mapping; 127 } 128 129 using namespace TargetOpcode; 130 131 unsigned NumOperands = MI.getNumOperands(); 132 const ValueMapping *OperandsMapping = &ARM::ValueMappings[0]; 133 134 switch (Opc) { 135 case G_ADD: 136 case G_LOAD: 137 // FIXME: We're abusing the fact that everything lives in a GPR for now; in 138 // the real world we would use different mappings. 139 OperandsMapping = &ARM::ValueMappings[0]; 140 break; 141 case G_FRAME_INDEX: 142 OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr}); 143 break; 144 default: 145 return InstructionMapping{}; 146 } 147 148 return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping, 149 NumOperands}; 150 } 151