diff --git a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h index 63bb8b27586..9077758d453 100644 --- a/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h +++ b/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h @@ -16,6 +16,7 @@ #define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H #include "llvm/ADT/APInt.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/GlobalISel/RegisterBank.h" #include "llvm/CodeGen/GlobalISel/Types.h" #include "llvm/Support/ErrorHandling.h" @@ -123,6 +124,11 @@ public: void verify(const MachineInstr &MI) const; }; + /// Convenient type to represent the alternatives for mapping an + /// instruction. + /// \todo When we move to TableGen this should be an array ref. + typedef SmallVector InstructionMappings; + protected: /// Hold the set of supported register banks. std::unique_ptr RegBanks; @@ -213,6 +219,53 @@ public: return 0; } + /// Identifier used when the related instruction mapping instance + /// is generated by target independent code. + /// Make sure not to use that identifier to avoid possible collision. + static const unsigned DefaultMappingID; + + /// Get the mapping of the different operands of \p MI + /// on the register bank. + /// This mapping should be the direct translation of \p MI. + /// The target independent implementation gives a mapping based on + /// the register classes for the target specific opcode. + /// It uses the ID RegisterBankInfo::DefaultMappingID for that mapping. + /// Make sure you do not use that ID for the alternative mapping + /// for MI. See getInstrAlternativeMappings for the alternative + /// mappings. + /// + /// For instance, if \p MI is a vector add, the mapping should + /// not be a scalarization of the add. + /// + /// \post returnedVal.verify(MI). + /// + /// \note If returnedVal does not verify MI, this would probably mean + /// that the target does not support that instruction. + virtual InstructionMapping getInstrMapping(const MachineInstr &MI) const; + + /// Get the alternative mappings for \p MI. + /// Alternative in the sense different from getInstrMapping. + virtual InstructionMappings + getInstrAlternativeMappings(const MachineInstr &MI) const; + + /// Get the possible mapping for \p MI. + /// A mapping defines where the different operands may live and at what cost. + /// For instance, let us consider: + /// v0(16) = G_ADD <2 x i8> v1, v2 + /// The possible mapping could be: + /// + /// {/*ID*/VectorAdd, /*Cost*/1, /*v0*/{(0xFFFF, VPR)}, /*v1*/{(0xFFFF, VPR)}, + /// /*v2*/{(0xFFFF, VPR)}} + /// {/*ID*/ScalarAddx2, /*Cost*/2, /*v0*/{(0x00FF, GPR),(0xFF00, GPR)}, + /// /*v1*/{(0x00FF, GPR),(0xFF00, GPR)}, + /// /*v2*/{(0x00FF, GPR),(0xFF00, GPR)}} + /// + /// \note The first alternative of the returned mapping should be the + /// direct translation of \p MI current form. + /// + /// \post !returnedVal.empty(). + InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const; + void verify(const TargetRegisterInfo &TRI) const; }; diff --git a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 6e8307917c7..4c7a74a0b66 100644 --- a/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -19,6 +19,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetOpcodes.h" #include "llvm/Target/TargetRegisterInfo.h" #include // For std::max. @@ -27,6 +28,8 @@ using namespace llvm; +const unsigned RegisterBankInfo::DefaultMappingID = UINT_MAX; + RegisterBankInfo::RegisterBankInfo(unsigned NumRegBanks) : NumRegBanks(NumRegBanks) { RegBanks.reset(new RegisterBank[NumRegBanks]); @@ -176,6 +179,36 @@ void RegisterBankInfo::addRegBankCoverage(unsigned ID, unsigned RCId, } while (!WorkList.empty()); } +RegisterBankInfo::InstructionMapping +RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + if (MI.getOpcode() > TargetOpcode::GENERIC_OP_END) { + // TODO. + } + llvm_unreachable("The target must implement this"); +} + +RegisterBankInfo::InstructionMappings +RegisterBankInfo::getInstrPossibleMappings(const MachineInstr &MI) const { + InstructionMappings PossibleMappings; + // Put the default mapping first. + PossibleMappings.push_back(getInstrMapping(MI)); + // Then the alternative mapping, if any. + InstructionMappings AltMappings = getInstrAlternativeMappings(MI); + for (InstructionMapping &AltMapping : AltMappings) + PossibleMappings.emplace_back(std::move(AltMapping)); +#ifndef NDEBUG + for (const InstructionMapping &Mapping : PossibleMappings) + Mapping.verify(MI); +#endif + return PossibleMappings; +} + +RegisterBankInfo::InstructionMappings +RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { + // No alternative for MI. + return InstructionMappings(); +} + //------------------------------------------------------------------------------ // Helper classes implementation. //------------------------------------------------------------------------------