//===- AArch64RegisterBankInfo.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 /// AArch64. /// \todo This should be generated by TableGen. //===----------------------------------------------------------------------===// #include "AArch64RegisterBankInfo.h" #include "AArch64InstrInfo.h" // For XXXRegClassID. #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" using namespace llvm; #ifndef LLVM_BUILD_GLOBAL_ISEL #error "You shouldn't build this" #endif AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI) : RegisterBankInfo(AArch64::NumRegisterBanks) { // Initialize the GPR bank. createRegisterBank(AArch64::GPRRegBankID, "GPR"); // The GPR register bank is fully defined by all the registers in // GR64all + its subclasses. addRegBankCoverage(AArch64::GPRRegBankID, AArch64::GPR64allRegClassID, TRI); const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID); (void)RBGPR; assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) && "Subclass not added?"); assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit"); // Initialize the FPR bank. createRegisterBank(AArch64::FPRRegBankID, "FPR"); // The FPR register bank is fully defined by all the registers in // GR64all + its subclasses. addRegBankCoverage(AArch64::FPRRegBankID, AArch64::QQQQRegClassID, TRI); const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID); (void)RBFPR; assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) && "Subclass not added?"); assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) && "Subclass not added?"); assert(RBFPR.getSize() == 512 && "FPRs should hold up to 512-bit via QQQQ sequence"); // Initialize the CCR bank. createRegisterBank(AArch64::CCRRegBankID, "CCR"); addRegBankCoverage(AArch64::CCRRegBankID, AArch64::CCRRegClassID, TRI); const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID); (void)RBCCR; assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) && "Class not added?"); assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit"); assert(verify(TRI) && "Invalid register bank information"); } unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A, const RegisterBank &B, unsigned Size) const { // What do we do with different size? // copy are same size. // Will introduce other hooks for different size: // * extract cost. // * build_sequence cost. // TODO: Add more accurate cost for FPR to/from GPR. return RegisterBankInfo::copyCost(A, B, Size); } const RegisterBank &AArch64RegisterBankInfo::getRegBankFromRegClass( const TargetRegisterClass &RC) const { switch (RC.getID()) { case AArch64::FPR8RegClassID: case AArch64::FPR16RegClassID: case AArch64::FPR32RegClassID: case AArch64::FPR64RegClassID: case AArch64::FPR128RegClassID: case AArch64::FPR128_loRegClassID: case AArch64::DDRegClassID: case AArch64::DDDRegClassID: case AArch64::DDDDRegClassID: case AArch64::QQRegClassID: case AArch64::QQQRegClassID: case AArch64::QQQQRegClassID: return getRegBank(AArch64::FPRRegBankID); case AArch64::GPR32commonRegClassID: case AArch64::GPR32RegClassID: case AArch64::GPR32spRegClassID: case AArch64::GPR32sponlyRegClassID: case AArch64::GPR32allRegClassID: case AArch64::GPR64commonRegClassID: case AArch64::GPR64RegClassID: case AArch64::GPR64spRegClassID: case AArch64::GPR64sponlyRegClassID: case AArch64::GPR64allRegClassID: case AArch64::tcGPR64RegClassID: case AArch64::WSeqPairsClassRegClassID: case AArch64::XSeqPairsClassRegClassID: return getRegBank(AArch64::GPRRegBankID); case AArch64::CCRRegClassID: return getRegBank(AArch64::CCRRegBankID); default: llvm_unreachable("Register class not supported"); } } RegisterBankInfo::InstructionMappings AArch64RegisterBankInfo::getInstrAlternativeMappings( const MachineInstr &MI) const { switch (MI.getOpcode()) { case TargetOpcode::G_OR: { // 32 and 64-bit or can be mapped on either FPR or // GPR for the same cost. const MachineFunction &MF = *MI.getParent()->getParent(); const TargetSubtargetInfo &STI = MF.getSubtarget(); const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); const MachineRegisterInfo &MRI = MF.getRegInfo(); unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI); if (Size != 32 && Size != 64) break; // If the instruction has any implicit-defs or uses, // do not mess with it. if (MI.getNumOperands() != 3) break; InstructionMappings AltMappings; InstructionMapping GPRMapping(/*ID*/ 1, /*Cost*/ 1, /*NumOperands*/ 3); InstructionMapping FPRMapping(/*ID*/ 2, /*Cost*/ 1, /*NumOperands*/ 3); for (unsigned Idx = 0; Idx != 3; ++Idx) { GPRMapping.setOperandMapping(Idx, Size, getRegBank(AArch64::GPRRegBankID)); FPRMapping.setOperandMapping(Idx, Size, getRegBank(AArch64::FPRRegBankID)); } AltMappings.emplace_back(std::move(GPRMapping)); AltMappings.emplace_back(std::move(FPRMapping)); return AltMappings; } default: break; } return RegisterBankInfo::getInstrAlternativeMappings(MI); } void AArch64RegisterBankInfo::applyMappingImpl( const OperandsMapper &OpdMapper) const { switch (OpdMapper.getMI().getOpcode()) { case TargetOpcode::G_OR: { // Those ID must match getInstrAlternativeMappings. assert((OpdMapper.getInstrMapping().getID() == 1 || OpdMapper.getInstrMapping().getID() == 2) && "Don't know how to handle that ID"); return applyDefaultMapping(OpdMapper); } default: llvm_unreachable("Don't know how to handle that operation"); } }