//===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// /// \file /// This file implements the targeting of the RegisterBankInfo class for ARM. /// \todo This should be generated by TableGen. //===----------------------------------------------------------------------===// #include "ARMRegisterBankInfo.h" #include "ARMInstrInfo.h" // For the register classes #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetRegisterInfo.h" using namespace llvm; #ifndef LLVM_BUILD_GLOBAL_ISEL #error "You shouldn't build this" #endif // FIXME: TableGen this. // If it grows too much and TableGen still isn't ready to do the job, extract it // into an ARMGenRegisterBankInfo.def (similar to AArch64). namespace llvm { namespace ARM { const uint32_t GPRCoverageData[] = { // Classes 0-31 (1u << ARM::GPRRegClassID) | (1u << ARM::GPRwithAPSRRegClassID) | (1u << ARM::GPRnopcRegClassID) | (1u << ARM::rGPRRegClassID) | (1u << ARM::hGPRRegClassID) | (1u << ARM::tGPRRegClassID) | (1u << ARM::GPRnopc_and_hGPRRegClassID) | (1u << ARM::hGPR_and_rGPRRegClassID) | (1u << ARM::tcGPRRegClassID) | (1u << ARM::tGPR_and_tcGPRRegClassID) | (1u << ARM::GPRspRegClassID) | (1u << ARM::hGPR_and_tcGPRRegClassID), // Classes 32-63 0, // Classes 64-96 0, // FIXME: Some of the entries below this point can be safely removed once // this is tablegenerated. It's only needed because of the hardcoded // register class limit. // Classes 97-128 0, // Classes 129-160 0, // Classes 161-192 0, // Classes 193-224 0, }; RegisterBank GPRRegBank(ARM::GPRRegBankID, "GPRB", 32, ARM::GPRCoverageData); RegisterBank *RegBanks[] = {&GPRRegBank}; RegisterBankInfo::PartialMapping GPRPartialMapping{0, 32, GPRRegBank}; RegisterBankInfo::ValueMapping ValueMappings[] = { {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}, {&GPRPartialMapping, 1}}; } // end namespace arm } // end namespace llvm ARMRegisterBankInfo::ARMRegisterBankInfo(const TargetRegisterInfo &TRI) : RegisterBankInfo(ARM::RegBanks, ARM::NumRegisterBanks) { static bool AlreadyInit = false; // We have only one set of register banks, whatever the subtarget // is. Therefore, the initialization of the RegBanks table should be // done only once. Indeed the table of all register banks // (ARM::RegBanks) is unique in the compiler. At some point, it // will get tablegen'ed and the whole constructor becomes empty. if (AlreadyInit) return; AlreadyInit = true; const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID); (void)RBGPR; assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up"); // Initialize the GPR bank. assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) && "Subclass not added?"); assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) && "Subclass not added?"); assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit"); } const RegisterBank &ARMRegisterBankInfo::getRegBankFromRegClass( const TargetRegisterClass &RC) const { using namespace ARM; switch (RC.getID()) { case GPRRegClassID: case tGPR_and_tcGPRRegClassID: return getRegBank(ARM::GPRRegBankID); default: llvm_unreachable("Unsupported register kind"); } llvm_unreachable("Switch should handle all register classes"); } RegisterBankInfo::InstructionMapping ARMRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { auto Opc = MI.getOpcode(); // Try the default logic for non-generic instructions that are either copies // or already have some operands assigned to banks. if (!isPreISelGenericOpcode(Opc)) { InstructionMapping Mapping = getInstrMappingImpl(MI); if (Mapping.isValid()) return Mapping; } using namespace TargetOpcode; unsigned NumOperands = MI.getNumOperands(); const ValueMapping *OperandsMapping = &ARM::ValueMappings[0]; switch (Opc) { case G_ADD: case G_LOAD: // FIXME: We're abusing the fact that everything lives in a GPR for now; in // the real world we would use different mappings. OperandsMapping = &ARM::ValueMappings[0]; break; case G_FRAME_INDEX: OperandsMapping = getOperandsMapping({&ARM::ValueMappings[0], nullptr}); break; default: return InstructionMapping{}; } return InstructionMapping{DefaultMappingID, /*Cost=*/1, OperandsMapping, NumOperands}; }