181ad6265SDimitry Andric //===- llvm/CodeGen/GlobalISel/RegisterBankInfo.cpp --------------*- C++ -*-==// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric /// \file 981ad6265SDimitry Andric /// This file implements the RegisterBankInfo class. 1081ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1181ad6265SDimitry Andric 1281ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h" 1306c3fb27SDimitry Andric #include "llvm/ADT/APInt.h" 1481ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 1581ad6265SDimitry Andric #include "llvm/ADT/Statistic.h" 1681ad6265SDimitry Andric #include "llvm/ADT/iterator_range.h" 1781ad6265SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 1881ad6265SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h" 1981ad6265SDimitry Andric #include "llvm/CodeGen/RegisterBank.h" 2081ad6265SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h" 2181ad6265SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h" 2281ad6265SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h" 2381ad6265SDimitry Andric #include "llvm/Config/llvm-config.h" 2481ad6265SDimitry Andric #include "llvm/Support/Debug.h" 2581ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h" 2681ad6265SDimitry Andric 2781ad6265SDimitry Andric #include <algorithm> // For std::max. 2881ad6265SDimitry Andric 2981ad6265SDimitry Andric #define DEBUG_TYPE "registerbankinfo" 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric using namespace llvm; 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric STATISTIC(NumPartialMappingsCreated, 3481ad6265SDimitry Andric "Number of partial mappings dynamically created"); 3581ad6265SDimitry Andric STATISTIC(NumPartialMappingsAccessed, 3681ad6265SDimitry Andric "Number of partial mappings dynamically accessed"); 3781ad6265SDimitry Andric STATISTIC(NumValueMappingsCreated, 3881ad6265SDimitry Andric "Number of value mappings dynamically created"); 3981ad6265SDimitry Andric STATISTIC(NumValueMappingsAccessed, 4081ad6265SDimitry Andric "Number of value mappings dynamically accessed"); 4181ad6265SDimitry Andric STATISTIC(NumOperandsMappingsCreated, 4281ad6265SDimitry Andric "Number of operands mappings dynamically created"); 4381ad6265SDimitry Andric STATISTIC(NumOperandsMappingsAccessed, 4481ad6265SDimitry Andric "Number of operands mappings dynamically accessed"); 4581ad6265SDimitry Andric STATISTIC(NumInstructionMappingsCreated, 4681ad6265SDimitry Andric "Number of instruction mappings dynamically created"); 4781ad6265SDimitry Andric STATISTIC(NumInstructionMappingsAccessed, 4881ad6265SDimitry Andric "Number of instruction mappings dynamically accessed"); 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric const unsigned RegisterBankInfo::DefaultMappingID = UINT_MAX; 5181ad6265SDimitry Andric const unsigned RegisterBankInfo::InvalidMappingID = UINT_MAX - 1; 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric //------------------------------------------------------------------------------ 5481ad6265SDimitry Andric // RegisterBankInfo implementation. 5581ad6265SDimitry Andric //------------------------------------------------------------------------------ 5606c3fb27SDimitry Andric RegisterBankInfo::RegisterBankInfo(const RegisterBank **RegBanks, 5706c3fb27SDimitry Andric unsigned NumRegBanks, const unsigned *Sizes, 5806c3fb27SDimitry Andric unsigned HwMode) 5906c3fb27SDimitry Andric : RegBanks(RegBanks), NumRegBanks(NumRegBanks), Sizes(Sizes), 6006c3fb27SDimitry Andric HwMode(HwMode) { 6181ad6265SDimitry Andric #ifndef NDEBUG 6281ad6265SDimitry Andric for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) { 6381ad6265SDimitry Andric assert(RegBanks[Idx] != nullptr && "Invalid RegisterBank"); 645f757f3fSDimitry Andric assert(RegBanks[Idx]->getID() == Idx && 655f757f3fSDimitry Andric "RegisterBank ID should match index"); 6681ad6265SDimitry Andric } 6781ad6265SDimitry Andric #endif // NDEBUG 6881ad6265SDimitry Andric } 6981ad6265SDimitry Andric 7081ad6265SDimitry Andric bool RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const { 7181ad6265SDimitry Andric #ifndef NDEBUG 7281ad6265SDimitry Andric for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) { 7381ad6265SDimitry Andric const RegisterBank &RegBank = getRegBank(Idx); 7481ad6265SDimitry Andric assert(Idx == RegBank.getID() && 7581ad6265SDimitry Andric "ID does not match the index in the array"); 7681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Verify " << RegBank << '\n'); 7706c3fb27SDimitry Andric assert(RegBank.verify(*this, TRI) && "RegBank is invalid"); 7881ad6265SDimitry Andric } 7981ad6265SDimitry Andric #endif // NDEBUG 8081ad6265SDimitry Andric return true; 8181ad6265SDimitry Andric } 8281ad6265SDimitry Andric 8381ad6265SDimitry Andric const RegisterBank * 8481ad6265SDimitry Andric RegisterBankInfo::getRegBank(Register Reg, const MachineRegisterInfo &MRI, 8581ad6265SDimitry Andric const TargetRegisterInfo &TRI) const { 8606c3fb27SDimitry Andric if (!Reg.isVirtual()) { 8781ad6265SDimitry Andric // FIXME: This was probably a copy to a virtual register that does have a 8881ad6265SDimitry Andric // type we could use. 8906c3fb27SDimitry Andric const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg, TRI); 9006c3fb27SDimitry Andric return RC ? &getRegBankFromRegClass(*RC, LLT()) : nullptr; 9181ad6265SDimitry Andric } 9281ad6265SDimitry Andric 9381ad6265SDimitry Andric const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg); 9406c3fb27SDimitry Andric if (auto *RB = dyn_cast_if_present<const RegisterBank *>(RegClassOrBank)) 9581ad6265SDimitry Andric return RB; 9606c3fb27SDimitry Andric if (auto *RC = 9706c3fb27SDimitry Andric dyn_cast_if_present<const TargetRegisterClass *>(RegClassOrBank)) 9881ad6265SDimitry Andric return &getRegBankFromRegClass(*RC, MRI.getType(Reg)); 9981ad6265SDimitry Andric return nullptr; 10081ad6265SDimitry Andric } 10181ad6265SDimitry Andric 10206c3fb27SDimitry Andric const TargetRegisterClass * 10381ad6265SDimitry Andric RegisterBankInfo::getMinimalPhysRegClass(Register Reg, 10481ad6265SDimitry Andric const TargetRegisterInfo &TRI) const { 105bdd1243dSDimitry Andric assert(Reg.isPhysical() && "Reg must be a physreg"); 10681ad6265SDimitry Andric const auto &RegRCIt = PhysRegMinimalRCs.find(Reg); 10781ad6265SDimitry Andric if (RegRCIt != PhysRegMinimalRCs.end()) 10806c3fb27SDimitry Andric return RegRCIt->second; 10906c3fb27SDimitry Andric const TargetRegisterClass *PhysRC = TRI.getMinimalPhysRegClassLLT(Reg, LLT()); 11081ad6265SDimitry Andric PhysRegMinimalRCs[Reg] = PhysRC; 11106c3fb27SDimitry Andric return PhysRC; 11281ad6265SDimitry Andric } 11381ad6265SDimitry Andric 11481ad6265SDimitry Andric const RegisterBank *RegisterBankInfo::getRegBankFromConstraints( 11581ad6265SDimitry Andric const MachineInstr &MI, unsigned OpIdx, const TargetInstrInfo &TII, 11681ad6265SDimitry Andric const MachineRegisterInfo &MRI) const { 11781ad6265SDimitry Andric const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo(); 11881ad6265SDimitry Andric 11981ad6265SDimitry Andric // The mapping of the registers may be available via the 12081ad6265SDimitry Andric // register class constraints. 12181ad6265SDimitry Andric const TargetRegisterClass *RC = MI.getRegClassConstraint(OpIdx, &TII, TRI); 12281ad6265SDimitry Andric 12381ad6265SDimitry Andric if (!RC) 12481ad6265SDimitry Andric return nullptr; 12581ad6265SDimitry Andric 12681ad6265SDimitry Andric Register Reg = MI.getOperand(OpIdx).getReg(); 12781ad6265SDimitry Andric const RegisterBank &RegBank = getRegBankFromRegClass(*RC, MRI.getType(Reg)); 12881ad6265SDimitry Andric // Check that the target properly implemented getRegBankFromRegClass. 12981ad6265SDimitry Andric assert(RegBank.covers(*RC) && 13081ad6265SDimitry Andric "The mapping of the register bank does not make sense"); 13181ad6265SDimitry Andric return &RegBank; 13281ad6265SDimitry Andric } 13381ad6265SDimitry Andric 13481ad6265SDimitry Andric const TargetRegisterClass *RegisterBankInfo::constrainGenericRegister( 13581ad6265SDimitry Andric Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI) { 13681ad6265SDimitry Andric 13781ad6265SDimitry Andric // If the register already has a class, fallback to MRI::constrainRegClass. 13881ad6265SDimitry Andric auto &RegClassOrBank = MRI.getRegClassOrRegBank(Reg); 13906c3fb27SDimitry Andric if (isa<const TargetRegisterClass *>(RegClassOrBank)) 14081ad6265SDimitry Andric return MRI.constrainRegClass(Reg, &RC); 14181ad6265SDimitry Andric 14206c3fb27SDimitry Andric const RegisterBank *RB = cast<const RegisterBank *>(RegClassOrBank); 14381ad6265SDimitry Andric // Otherwise, all we can do is ensure the bank covers the class, and set it. 14481ad6265SDimitry Andric if (RB && !RB->covers(RC)) 14581ad6265SDimitry Andric return nullptr; 14681ad6265SDimitry Andric 14781ad6265SDimitry Andric // If nothing was set or the class is simply compatible, set it. 14881ad6265SDimitry Andric MRI.setRegClass(Reg, &RC); 14981ad6265SDimitry Andric return &RC; 15081ad6265SDimitry Andric } 15181ad6265SDimitry Andric 15281ad6265SDimitry Andric /// Check whether or not \p MI should be treated like a copy 15381ad6265SDimitry Andric /// for the mappings. 15481ad6265SDimitry Andric /// Copy like instruction are special for mapping because 15581ad6265SDimitry Andric /// they don't have actual register constraints. Moreover, 15681ad6265SDimitry Andric /// they sometimes have register classes assigned and we can 15781ad6265SDimitry Andric /// just use that instead of failing to provide a generic mapping. 15881ad6265SDimitry Andric static bool isCopyLike(const MachineInstr &MI) { 15981ad6265SDimitry Andric return MI.isCopy() || MI.isPHI() || 16081ad6265SDimitry Andric MI.getOpcode() == TargetOpcode::REG_SEQUENCE; 16181ad6265SDimitry Andric } 16281ad6265SDimitry Andric 16381ad6265SDimitry Andric const RegisterBankInfo::InstructionMapping & 16481ad6265SDimitry Andric RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { 16581ad6265SDimitry Andric // For copies we want to walk over the operands and try to find one 16681ad6265SDimitry Andric // that has a register bank since the instruction itself will not get 16781ad6265SDimitry Andric // us any constraint. 16881ad6265SDimitry Andric bool IsCopyLike = isCopyLike(MI); 16981ad6265SDimitry Andric // For copy like instruction, only the mapping of the definition 17081ad6265SDimitry Andric // is important. The rest is not constrained. 17181ad6265SDimitry Andric unsigned NumOperandsForMapping = IsCopyLike ? 1 : MI.getNumOperands(); 17281ad6265SDimitry Andric 17381ad6265SDimitry Andric const MachineFunction &MF = *MI.getMF(); 17481ad6265SDimitry Andric const TargetSubtargetInfo &STI = MF.getSubtarget(); 17581ad6265SDimitry Andric const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); 17681ad6265SDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 17781ad6265SDimitry Andric // We may need to query the instruction encoding to guess the mapping. 17881ad6265SDimitry Andric const TargetInstrInfo &TII = *STI.getInstrInfo(); 17981ad6265SDimitry Andric 18081ad6265SDimitry Andric // Before doing anything complicated check if the mapping is not 18181ad6265SDimitry Andric // directly available. 18281ad6265SDimitry Andric bool CompleteMapping = true; 18381ad6265SDimitry Andric 18481ad6265SDimitry Andric SmallVector<const ValueMapping *, 8> OperandsMapping(NumOperandsForMapping); 18581ad6265SDimitry Andric for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx; 18681ad6265SDimitry Andric ++OpIdx) { 18781ad6265SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 18881ad6265SDimitry Andric if (!MO.isReg()) 18981ad6265SDimitry Andric continue; 19081ad6265SDimitry Andric Register Reg = MO.getReg(); 19181ad6265SDimitry Andric if (!Reg) 19281ad6265SDimitry Andric continue; 19381ad6265SDimitry Andric // The register bank of Reg is just a side effect of the current 19481ad6265SDimitry Andric // excution and in particular, there is no reason to believe this 19581ad6265SDimitry Andric // is the best default mapping for the current instruction. Keep 19681ad6265SDimitry Andric // it as an alternative register bank if we cannot figure out 19781ad6265SDimitry Andric // something. 19881ad6265SDimitry Andric const RegisterBank *AltRegBank = getRegBank(Reg, MRI, TRI); 19981ad6265SDimitry Andric // For copy-like instruction, we want to reuse the register bank 20081ad6265SDimitry Andric // that is already set on Reg, if any, since those instructions do 20181ad6265SDimitry Andric // not have any constraints. 20281ad6265SDimitry Andric const RegisterBank *CurRegBank = IsCopyLike ? AltRegBank : nullptr; 20381ad6265SDimitry Andric if (!CurRegBank) { 20481ad6265SDimitry Andric // If this is a target specific instruction, we can deduce 20581ad6265SDimitry Andric // the register bank from the encoding constraints. 20681ad6265SDimitry Andric CurRegBank = getRegBankFromConstraints(MI, OpIdx, TII, MRI); 20781ad6265SDimitry Andric if (!CurRegBank) { 20881ad6265SDimitry Andric // All our attempts failed, give up. 20981ad6265SDimitry Andric CompleteMapping = false; 21081ad6265SDimitry Andric 21181ad6265SDimitry Andric if (!IsCopyLike) 21281ad6265SDimitry Andric // MI does not carry enough information to guess the mapping. 21381ad6265SDimitry Andric return getInvalidInstructionMapping(); 21481ad6265SDimitry Andric continue; 21581ad6265SDimitry Andric } 21681ad6265SDimitry Andric } 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric unsigned Size = getSizeInBits(Reg, MRI, TRI); 21981ad6265SDimitry Andric const ValueMapping *ValMapping = &getValueMapping(0, Size, *CurRegBank); 22081ad6265SDimitry Andric if (IsCopyLike) { 22181ad6265SDimitry Andric if (!OperandsMapping[0]) { 22281ad6265SDimitry Andric if (MI.isRegSequence()) { 22381ad6265SDimitry Andric // For reg_sequence, the result size does not match the input. 22481ad6265SDimitry Andric unsigned ResultSize = getSizeInBits(MI.getOperand(0).getReg(), 22581ad6265SDimitry Andric MRI, TRI); 22681ad6265SDimitry Andric OperandsMapping[0] = &getValueMapping(0, ResultSize, *CurRegBank); 22781ad6265SDimitry Andric } else { 22881ad6265SDimitry Andric OperandsMapping[0] = ValMapping; 22981ad6265SDimitry Andric } 23081ad6265SDimitry Andric } 23181ad6265SDimitry Andric 23281ad6265SDimitry Andric // The default handling assumes any register bank can be copied to any 23381ad6265SDimitry Andric // other. If this isn't the case, the target should specially deal with 23481ad6265SDimitry Andric // reg_sequence/phi. There may also be unsatisfiable copies. 23581ad6265SDimitry Andric for (; OpIdx != EndIdx; ++OpIdx) { 23681ad6265SDimitry Andric const MachineOperand &MO = MI.getOperand(OpIdx); 23781ad6265SDimitry Andric if (!MO.isReg()) 23881ad6265SDimitry Andric continue; 23981ad6265SDimitry Andric Register Reg = MO.getReg(); 24081ad6265SDimitry Andric if (!Reg) 24181ad6265SDimitry Andric continue; 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric const RegisterBank *AltRegBank = getRegBank(Reg, MRI, TRI); 24481ad6265SDimitry Andric if (AltRegBank && 24581ad6265SDimitry Andric cannotCopy(*CurRegBank, *AltRegBank, getSizeInBits(Reg, MRI, TRI))) 24681ad6265SDimitry Andric return getInvalidInstructionMapping(); 24781ad6265SDimitry Andric } 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric CompleteMapping = true; 25081ad6265SDimitry Andric break; 25181ad6265SDimitry Andric } 25281ad6265SDimitry Andric 25381ad6265SDimitry Andric OperandsMapping[OpIdx] = ValMapping; 25481ad6265SDimitry Andric } 25581ad6265SDimitry Andric 25681ad6265SDimitry Andric if (IsCopyLike && !CompleteMapping) { 25781ad6265SDimitry Andric // No way to deduce the type from what we have. 25881ad6265SDimitry Andric return getInvalidInstructionMapping(); 25981ad6265SDimitry Andric } 26081ad6265SDimitry Andric 26181ad6265SDimitry Andric assert(CompleteMapping && "Setting an uncomplete mapping"); 26281ad6265SDimitry Andric return getInstructionMapping( 26381ad6265SDimitry Andric DefaultMappingID, /*Cost*/ 1, 26481ad6265SDimitry Andric /*OperandsMapping*/ getOperandsMapping(OperandsMapping), 26581ad6265SDimitry Andric NumOperandsForMapping); 26681ad6265SDimitry Andric } 26781ad6265SDimitry Andric 26881ad6265SDimitry Andric /// Hashing function for PartialMapping. 26981ad6265SDimitry Andric static hash_code hashPartialMapping(unsigned StartIdx, unsigned Length, 27081ad6265SDimitry Andric const RegisterBank *RegBank) { 27181ad6265SDimitry Andric return hash_combine(StartIdx, Length, RegBank ? RegBank->getID() : 0); 27281ad6265SDimitry Andric } 27381ad6265SDimitry Andric 27481ad6265SDimitry Andric /// Overloaded version of hash_value for a PartialMapping. 27581ad6265SDimitry Andric hash_code 27681ad6265SDimitry Andric llvm::hash_value(const RegisterBankInfo::PartialMapping &PartMapping) { 27781ad6265SDimitry Andric return hashPartialMapping(PartMapping.StartIdx, PartMapping.Length, 27881ad6265SDimitry Andric PartMapping.RegBank); 27981ad6265SDimitry Andric } 28081ad6265SDimitry Andric 28181ad6265SDimitry Andric const RegisterBankInfo::PartialMapping & 28281ad6265SDimitry Andric RegisterBankInfo::getPartialMapping(unsigned StartIdx, unsigned Length, 28381ad6265SDimitry Andric const RegisterBank &RegBank) const { 28481ad6265SDimitry Andric ++NumPartialMappingsAccessed; 28581ad6265SDimitry Andric 28681ad6265SDimitry Andric hash_code Hash = hashPartialMapping(StartIdx, Length, &RegBank); 28781ad6265SDimitry Andric const auto &It = MapOfPartialMappings.find(Hash); 28881ad6265SDimitry Andric if (It != MapOfPartialMappings.end()) 28981ad6265SDimitry Andric return *It->second; 29081ad6265SDimitry Andric 29181ad6265SDimitry Andric ++NumPartialMappingsCreated; 29281ad6265SDimitry Andric 29381ad6265SDimitry Andric auto &PartMapping = MapOfPartialMappings[Hash]; 29481ad6265SDimitry Andric PartMapping = std::make_unique<PartialMapping>(StartIdx, Length, RegBank); 29581ad6265SDimitry Andric return *PartMapping; 29681ad6265SDimitry Andric } 29781ad6265SDimitry Andric 29881ad6265SDimitry Andric const RegisterBankInfo::ValueMapping & 29981ad6265SDimitry Andric RegisterBankInfo::getValueMapping(unsigned StartIdx, unsigned Length, 30081ad6265SDimitry Andric const RegisterBank &RegBank) const { 30181ad6265SDimitry Andric return getValueMapping(&getPartialMapping(StartIdx, Length, RegBank), 1); 30281ad6265SDimitry Andric } 30381ad6265SDimitry Andric 30481ad6265SDimitry Andric static hash_code 30581ad6265SDimitry Andric hashValueMapping(const RegisterBankInfo::PartialMapping *BreakDown, 30681ad6265SDimitry Andric unsigned NumBreakDowns) { 30781ad6265SDimitry Andric if (LLVM_LIKELY(NumBreakDowns == 1)) 30881ad6265SDimitry Andric return hash_value(*BreakDown); 30981ad6265SDimitry Andric SmallVector<size_t, 8> Hashes(NumBreakDowns); 31081ad6265SDimitry Andric for (unsigned Idx = 0; Idx != NumBreakDowns; ++Idx) 31181ad6265SDimitry Andric Hashes.push_back(hash_value(BreakDown[Idx])); 31281ad6265SDimitry Andric return hash_combine_range(Hashes.begin(), Hashes.end()); 31381ad6265SDimitry Andric } 31481ad6265SDimitry Andric 31581ad6265SDimitry Andric const RegisterBankInfo::ValueMapping & 31681ad6265SDimitry Andric RegisterBankInfo::getValueMapping(const PartialMapping *BreakDown, 31781ad6265SDimitry Andric unsigned NumBreakDowns) const { 31881ad6265SDimitry Andric ++NumValueMappingsAccessed; 31981ad6265SDimitry Andric 32081ad6265SDimitry Andric hash_code Hash = hashValueMapping(BreakDown, NumBreakDowns); 32181ad6265SDimitry Andric const auto &It = MapOfValueMappings.find(Hash); 32281ad6265SDimitry Andric if (It != MapOfValueMappings.end()) 32381ad6265SDimitry Andric return *It->second; 32481ad6265SDimitry Andric 32581ad6265SDimitry Andric ++NumValueMappingsCreated; 32681ad6265SDimitry Andric 32781ad6265SDimitry Andric auto &ValMapping = MapOfValueMappings[Hash]; 32881ad6265SDimitry Andric ValMapping = std::make_unique<ValueMapping>(BreakDown, NumBreakDowns); 32981ad6265SDimitry Andric return *ValMapping; 33081ad6265SDimitry Andric } 33181ad6265SDimitry Andric 33281ad6265SDimitry Andric template <typename Iterator> 33381ad6265SDimitry Andric const RegisterBankInfo::ValueMapping * 33481ad6265SDimitry Andric RegisterBankInfo::getOperandsMapping(Iterator Begin, Iterator End) const { 33581ad6265SDimitry Andric 33681ad6265SDimitry Andric ++NumOperandsMappingsAccessed; 33781ad6265SDimitry Andric 33881ad6265SDimitry Andric // The addresses of the value mapping are unique. 33981ad6265SDimitry Andric // Therefore, we can use them directly to hash the operand mapping. 34081ad6265SDimitry Andric hash_code Hash = hash_combine_range(Begin, End); 34181ad6265SDimitry Andric auto &Res = MapOfOperandsMappings[Hash]; 34281ad6265SDimitry Andric if (Res) 34381ad6265SDimitry Andric return Res.get(); 34481ad6265SDimitry Andric 34581ad6265SDimitry Andric ++NumOperandsMappingsCreated; 34681ad6265SDimitry Andric 34781ad6265SDimitry Andric // Create the array of ValueMapping. 34881ad6265SDimitry Andric // Note: this array will not hash to this instance of operands 34981ad6265SDimitry Andric // mapping, because we use the pointer of the ValueMapping 35081ad6265SDimitry Andric // to hash and we expect them to uniquely identify an instance 35181ad6265SDimitry Andric // of value mapping. 35281ad6265SDimitry Andric Res = std::make_unique<ValueMapping[]>(std::distance(Begin, End)); 35381ad6265SDimitry Andric unsigned Idx = 0; 35481ad6265SDimitry Andric for (Iterator It = Begin; It != End; ++It, ++Idx) { 35581ad6265SDimitry Andric const ValueMapping *ValMap = *It; 35681ad6265SDimitry Andric if (!ValMap) 35781ad6265SDimitry Andric continue; 35881ad6265SDimitry Andric Res[Idx] = *ValMap; 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric return Res.get(); 36181ad6265SDimitry Andric } 36281ad6265SDimitry Andric 36381ad6265SDimitry Andric const RegisterBankInfo::ValueMapping *RegisterBankInfo::getOperandsMapping( 36481ad6265SDimitry Andric const SmallVectorImpl<const RegisterBankInfo::ValueMapping *> &OpdsMapping) 36581ad6265SDimitry Andric const { 36681ad6265SDimitry Andric return getOperandsMapping(OpdsMapping.begin(), OpdsMapping.end()); 36781ad6265SDimitry Andric } 36881ad6265SDimitry Andric 36981ad6265SDimitry Andric const RegisterBankInfo::ValueMapping *RegisterBankInfo::getOperandsMapping( 37081ad6265SDimitry Andric std::initializer_list<const RegisterBankInfo::ValueMapping *> OpdsMapping) 37181ad6265SDimitry Andric const { 37281ad6265SDimitry Andric return getOperandsMapping(OpdsMapping.begin(), OpdsMapping.end()); 37381ad6265SDimitry Andric } 37481ad6265SDimitry Andric 37581ad6265SDimitry Andric static hash_code 37681ad6265SDimitry Andric hashInstructionMapping(unsigned ID, unsigned Cost, 37781ad6265SDimitry Andric const RegisterBankInfo::ValueMapping *OperandsMapping, 37881ad6265SDimitry Andric unsigned NumOperands) { 37981ad6265SDimitry Andric return hash_combine(ID, Cost, OperandsMapping, NumOperands); 38081ad6265SDimitry Andric } 38181ad6265SDimitry Andric 38281ad6265SDimitry Andric const RegisterBankInfo::InstructionMapping & 38381ad6265SDimitry Andric RegisterBankInfo::getInstructionMappingImpl( 38481ad6265SDimitry Andric bool IsInvalid, unsigned ID, unsigned Cost, 38581ad6265SDimitry Andric const RegisterBankInfo::ValueMapping *OperandsMapping, 38681ad6265SDimitry Andric unsigned NumOperands) const { 38781ad6265SDimitry Andric assert(((IsInvalid && ID == InvalidMappingID && Cost == 0 && 38881ad6265SDimitry Andric OperandsMapping == nullptr && NumOperands == 0) || 38981ad6265SDimitry Andric !IsInvalid) && 39081ad6265SDimitry Andric "Mismatch argument for invalid input"); 39181ad6265SDimitry Andric ++NumInstructionMappingsAccessed; 39281ad6265SDimitry Andric 39381ad6265SDimitry Andric hash_code Hash = 39481ad6265SDimitry Andric hashInstructionMapping(ID, Cost, OperandsMapping, NumOperands); 39581ad6265SDimitry Andric const auto &It = MapOfInstructionMappings.find(Hash); 39681ad6265SDimitry Andric if (It != MapOfInstructionMappings.end()) 39781ad6265SDimitry Andric return *It->second; 39881ad6265SDimitry Andric 39981ad6265SDimitry Andric ++NumInstructionMappingsCreated; 40081ad6265SDimitry Andric 40181ad6265SDimitry Andric auto &InstrMapping = MapOfInstructionMappings[Hash]; 40281ad6265SDimitry Andric InstrMapping = std::make_unique<InstructionMapping>( 40381ad6265SDimitry Andric ID, Cost, OperandsMapping, NumOperands); 40481ad6265SDimitry Andric return *InstrMapping; 40581ad6265SDimitry Andric } 40681ad6265SDimitry Andric 40781ad6265SDimitry Andric const RegisterBankInfo::InstructionMapping & 40881ad6265SDimitry Andric RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { 40981ad6265SDimitry Andric const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); 41081ad6265SDimitry Andric if (Mapping.isValid()) 41181ad6265SDimitry Andric return Mapping; 41281ad6265SDimitry Andric llvm_unreachable("The target must implement this"); 41381ad6265SDimitry Andric } 41481ad6265SDimitry Andric 41581ad6265SDimitry Andric RegisterBankInfo::InstructionMappings 41681ad6265SDimitry Andric RegisterBankInfo::getInstrPossibleMappings(const MachineInstr &MI) const { 41781ad6265SDimitry Andric InstructionMappings PossibleMappings; 41881ad6265SDimitry Andric const auto &Mapping = getInstrMapping(MI); 41981ad6265SDimitry Andric if (Mapping.isValid()) { 42081ad6265SDimitry Andric // Put the default mapping first. 42181ad6265SDimitry Andric PossibleMappings.push_back(&Mapping); 42281ad6265SDimitry Andric } 42381ad6265SDimitry Andric 42481ad6265SDimitry Andric // Then the alternative mapping, if any. 42581ad6265SDimitry Andric InstructionMappings AltMappings = getInstrAlternativeMappings(MI); 42681ad6265SDimitry Andric append_range(PossibleMappings, AltMappings); 42781ad6265SDimitry Andric #ifndef NDEBUG 42881ad6265SDimitry Andric for (const InstructionMapping *Mapping : PossibleMappings) 42981ad6265SDimitry Andric assert(Mapping->verify(MI) && "Mapping is invalid"); 43081ad6265SDimitry Andric #endif 43181ad6265SDimitry Andric return PossibleMappings; 43281ad6265SDimitry Andric } 43381ad6265SDimitry Andric 43481ad6265SDimitry Andric RegisterBankInfo::InstructionMappings 43581ad6265SDimitry Andric RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const { 43681ad6265SDimitry Andric // No alternative for MI. 43781ad6265SDimitry Andric return InstructionMappings(); 43881ad6265SDimitry Andric } 43981ad6265SDimitry Andric 44081ad6265SDimitry Andric void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) { 44181ad6265SDimitry Andric MachineInstr &MI = OpdMapper.getMI(); 44281ad6265SDimitry Andric MachineRegisterInfo &MRI = OpdMapper.getMRI(); 44381ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "Applying default-like mapping\n"); 44481ad6265SDimitry Andric for (unsigned OpIdx = 0, 44581ad6265SDimitry Andric EndIdx = OpdMapper.getInstrMapping().getNumOperands(); 44681ad6265SDimitry Andric OpIdx != EndIdx; ++OpIdx) { 44781ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "OpIdx " << OpIdx); 44881ad6265SDimitry Andric MachineOperand &MO = MI.getOperand(OpIdx); 44981ad6265SDimitry Andric if (!MO.isReg()) { 45081ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " is not a register, nothing to be done\n"); 45181ad6265SDimitry Andric continue; 45281ad6265SDimitry Andric } 45381ad6265SDimitry Andric if (!MO.getReg()) { 45481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " is $noreg, nothing to be done\n"); 45581ad6265SDimitry Andric continue; 45681ad6265SDimitry Andric } 457bdd1243dSDimitry Andric LLT Ty = MRI.getType(MO.getReg()); 458bdd1243dSDimitry Andric if (!Ty.isValid()) 459bdd1243dSDimitry Andric continue; 46081ad6265SDimitry Andric assert(OpdMapper.getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns != 46181ad6265SDimitry Andric 0 && 46281ad6265SDimitry Andric "Invalid mapping"); 46381ad6265SDimitry Andric assert(OpdMapper.getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns == 46481ad6265SDimitry Andric 1 && 46581ad6265SDimitry Andric "This mapping is too complex for this function"); 46681ad6265SDimitry Andric iterator_range<SmallVectorImpl<Register>::const_iterator> NewRegs = 46781ad6265SDimitry Andric OpdMapper.getVRegs(OpIdx); 46881ad6265SDimitry Andric if (NewRegs.empty()) { 46981ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " has not been repaired, nothing to be done\n"); 47081ad6265SDimitry Andric continue; 47181ad6265SDimitry Andric } 47281ad6265SDimitry Andric Register OrigReg = MO.getReg(); 47381ad6265SDimitry Andric Register NewReg = *NewRegs.begin(); 47481ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " changed, replace " << printReg(OrigReg, nullptr)); 47581ad6265SDimitry Andric MO.setReg(NewReg); 47681ad6265SDimitry Andric LLVM_DEBUG(dbgs() << " with " << printReg(NewReg, nullptr)); 47781ad6265SDimitry Andric 47881ad6265SDimitry Andric // The OperandsMapper creates plain scalar, we may have to fix that. 47981ad6265SDimitry Andric // Check if the types match and if not, fix that. 48081ad6265SDimitry Andric LLT OrigTy = MRI.getType(OrigReg); 48181ad6265SDimitry Andric LLT NewTy = MRI.getType(NewReg); 48281ad6265SDimitry Andric if (OrigTy != NewTy) { 48381ad6265SDimitry Andric // The default mapping is not supposed to change the size of 48481ad6265SDimitry Andric // the storage. However, right now we don't necessarily bump all 48581ad6265SDimitry Andric // the types to storage size. For instance, we can consider 48681ad6265SDimitry Andric // s16 G_AND legal whereas the storage size is going to be 32. 487*0fca6ea1SDimitry Andric assert( 488*0fca6ea1SDimitry Andric TypeSize::isKnownLE(OrigTy.getSizeInBits(), NewTy.getSizeInBits()) && 48981ad6265SDimitry Andric "Types with difference size cannot be handled by the default " 49081ad6265SDimitry Andric "mapping"); 49181ad6265SDimitry Andric LLVM_DEBUG(dbgs() << "\nChange type of new opd from " << NewTy << " to " 49281ad6265SDimitry Andric << OrigTy); 49381ad6265SDimitry Andric MRI.setType(NewReg, OrigTy); 49481ad6265SDimitry Andric } 49581ad6265SDimitry Andric LLVM_DEBUG(dbgs() << '\n'); 49681ad6265SDimitry Andric } 49781ad6265SDimitry Andric } 49881ad6265SDimitry Andric 4995f757f3fSDimitry Andric TypeSize RegisterBankInfo::getSizeInBits(Register Reg, 50081ad6265SDimitry Andric const MachineRegisterInfo &MRI, 50181ad6265SDimitry Andric const TargetRegisterInfo &TRI) const { 502bdd1243dSDimitry Andric if (Reg.isPhysical()) { 50381ad6265SDimitry Andric // The size is not directly available for physical registers. 50481ad6265SDimitry Andric // Instead, we need to access a register class that contains Reg and 50581ad6265SDimitry Andric // get the size of that register class. 50681ad6265SDimitry Andric // Because this is expensive, we'll cache the register class by calling 50706c3fb27SDimitry Andric auto *RC = getMinimalPhysRegClass(Reg, TRI); 50881ad6265SDimitry Andric assert(RC && "Expecting Register class"); 50981ad6265SDimitry Andric return TRI.getRegSizeInBits(*RC); 51081ad6265SDimitry Andric } 51181ad6265SDimitry Andric return TRI.getRegSizeInBits(Reg, MRI); 51281ad6265SDimitry Andric } 51381ad6265SDimitry Andric 51481ad6265SDimitry Andric //------------------------------------------------------------------------------ 51581ad6265SDimitry Andric // Helper classes implementation. 51681ad6265SDimitry Andric //------------------------------------------------------------------------------ 51781ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 51881ad6265SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::PartialMapping::dump() const { 51981ad6265SDimitry Andric print(dbgs()); 52081ad6265SDimitry Andric dbgs() << '\n'; 52181ad6265SDimitry Andric } 52281ad6265SDimitry Andric #endif 52381ad6265SDimitry Andric 52406c3fb27SDimitry Andric bool RegisterBankInfo::PartialMapping::verify( 52506c3fb27SDimitry Andric const RegisterBankInfo &RBI) const { 52681ad6265SDimitry Andric assert(RegBank && "Register bank not set"); 52781ad6265SDimitry Andric assert(Length && "Empty mapping"); 52881ad6265SDimitry Andric assert((StartIdx <= getHighBitIdx()) && "Overflow, switch to APInt?"); 52981ad6265SDimitry Andric // Check if the minimum width fits into RegBank. 53006c3fb27SDimitry Andric assert(RBI.getMaximumSize(RegBank->getID()) >= Length && 53106c3fb27SDimitry Andric "Register bank too small for Mask"); 53281ad6265SDimitry Andric return true; 53381ad6265SDimitry Andric } 53481ad6265SDimitry Andric 53581ad6265SDimitry Andric void RegisterBankInfo::PartialMapping::print(raw_ostream &OS) const { 53681ad6265SDimitry Andric OS << "[" << StartIdx << ", " << getHighBitIdx() << "], RegBank = "; 53781ad6265SDimitry Andric if (RegBank) 53881ad6265SDimitry Andric OS << *RegBank; 53981ad6265SDimitry Andric else 54081ad6265SDimitry Andric OS << "nullptr"; 54181ad6265SDimitry Andric } 54281ad6265SDimitry Andric 54381ad6265SDimitry Andric bool RegisterBankInfo::ValueMapping::partsAllUniform() const { 54481ad6265SDimitry Andric if (NumBreakDowns < 2) 54581ad6265SDimitry Andric return true; 54681ad6265SDimitry Andric 54781ad6265SDimitry Andric const PartialMapping *First = begin(); 54881ad6265SDimitry Andric for (const PartialMapping *Part = First + 1; Part != end(); ++Part) { 54981ad6265SDimitry Andric if (Part->Length != First->Length || Part->RegBank != First->RegBank) 55081ad6265SDimitry Andric return false; 55181ad6265SDimitry Andric } 55281ad6265SDimitry Andric 55381ad6265SDimitry Andric return true; 55481ad6265SDimitry Andric } 55581ad6265SDimitry Andric 55606c3fb27SDimitry Andric bool RegisterBankInfo::ValueMapping::verify(const RegisterBankInfo &RBI, 5575f757f3fSDimitry Andric TypeSize MeaningfulBitWidth) const { 55881ad6265SDimitry Andric assert(NumBreakDowns && "Value mapped nowhere?!"); 55981ad6265SDimitry Andric unsigned OrigValueBitWidth = 0; 56081ad6265SDimitry Andric for (const RegisterBankInfo::PartialMapping &PartMap : *this) { 56181ad6265SDimitry Andric // Check that each register bank is big enough to hold the partial value: 56281ad6265SDimitry Andric // this check is done by PartialMapping::verify 56306c3fb27SDimitry Andric assert(PartMap.verify(RBI) && "Partial mapping is invalid"); 56481ad6265SDimitry Andric // The original value should completely be mapped. 56581ad6265SDimitry Andric // Thus the maximum accessed index + 1 is the size of the original value. 56681ad6265SDimitry Andric OrigValueBitWidth = 56781ad6265SDimitry Andric std::max(OrigValueBitWidth, PartMap.getHighBitIdx() + 1); 56881ad6265SDimitry Andric } 5695f757f3fSDimitry Andric assert((MeaningfulBitWidth.isScalable() || 5705f757f3fSDimitry Andric OrigValueBitWidth >= MeaningfulBitWidth) && 57181ad6265SDimitry Andric "Meaningful bits not covered by the mapping"); 57281ad6265SDimitry Andric APInt ValueMask(OrigValueBitWidth, 0); 57381ad6265SDimitry Andric for (const RegisterBankInfo::PartialMapping &PartMap : *this) { 57481ad6265SDimitry Andric // Check that the union of the partial mappings covers the whole value, 57581ad6265SDimitry Andric // without overlaps. 57681ad6265SDimitry Andric // The high bit is exclusive in the APInt API, thus getHighBitIdx + 1. 57781ad6265SDimitry Andric APInt PartMapMask = APInt::getBitsSet(OrigValueBitWidth, PartMap.StartIdx, 57881ad6265SDimitry Andric PartMap.getHighBitIdx() + 1); 57981ad6265SDimitry Andric ValueMask ^= PartMapMask; 58081ad6265SDimitry Andric assert((ValueMask & PartMapMask) == PartMapMask && 58181ad6265SDimitry Andric "Some partial mappings overlap"); 58281ad6265SDimitry Andric } 58381ad6265SDimitry Andric assert(ValueMask.isAllOnes() && "Value is not fully mapped"); 58481ad6265SDimitry Andric return true; 58581ad6265SDimitry Andric } 58681ad6265SDimitry Andric 58781ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 58881ad6265SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::ValueMapping::dump() const { 58981ad6265SDimitry Andric print(dbgs()); 59081ad6265SDimitry Andric dbgs() << '\n'; 59181ad6265SDimitry Andric } 59281ad6265SDimitry Andric #endif 59381ad6265SDimitry Andric 59481ad6265SDimitry Andric void RegisterBankInfo::ValueMapping::print(raw_ostream &OS) const { 59581ad6265SDimitry Andric OS << "#BreakDown: " << NumBreakDowns << " "; 59681ad6265SDimitry Andric bool IsFirst = true; 59781ad6265SDimitry Andric for (const PartialMapping &PartMap : *this) { 59881ad6265SDimitry Andric if (!IsFirst) 59981ad6265SDimitry Andric OS << ", "; 60081ad6265SDimitry Andric OS << '[' << PartMap << ']'; 60181ad6265SDimitry Andric IsFirst = false; 60281ad6265SDimitry Andric } 60381ad6265SDimitry Andric } 60481ad6265SDimitry Andric 60581ad6265SDimitry Andric bool RegisterBankInfo::InstructionMapping::verify( 60681ad6265SDimitry Andric const MachineInstr &MI) const { 60781ad6265SDimitry Andric // Check that all the register operands are properly mapped. 60881ad6265SDimitry Andric // Check the constructor invariant. 60981ad6265SDimitry Andric // For PHI, we only care about mapping the definition. 61081ad6265SDimitry Andric assert(NumOperands == (isCopyLike(MI) ? 1 : MI.getNumOperands()) && 61181ad6265SDimitry Andric "NumOperands must match, see constructor"); 61281ad6265SDimitry Andric assert(MI.getParent() && MI.getMF() && 61381ad6265SDimitry Andric "MI must be connected to a MachineFunction"); 61481ad6265SDimitry Andric const MachineFunction &MF = *MI.getMF(); 61581ad6265SDimitry Andric const RegisterBankInfo *RBI = MF.getSubtarget().getRegBankInfo(); 61681ad6265SDimitry Andric (void)RBI; 617bdd1243dSDimitry Andric const MachineRegisterInfo &MRI = MF.getRegInfo(); 61881ad6265SDimitry Andric 61981ad6265SDimitry Andric for (unsigned Idx = 0; Idx < NumOperands; ++Idx) { 62081ad6265SDimitry Andric const MachineOperand &MO = MI.getOperand(Idx); 62181ad6265SDimitry Andric if (!MO.isReg()) { 62281ad6265SDimitry Andric assert(!getOperandMapping(Idx).isValid() && 62381ad6265SDimitry Andric "We should not care about non-reg mapping"); 62481ad6265SDimitry Andric continue; 62581ad6265SDimitry Andric } 62681ad6265SDimitry Andric Register Reg = MO.getReg(); 62781ad6265SDimitry Andric if (!Reg) 62881ad6265SDimitry Andric continue; 629bdd1243dSDimitry Andric LLT Ty = MRI.getType(Reg); 630bdd1243dSDimitry Andric if (!Ty.isValid()) 631bdd1243dSDimitry Andric continue; 63281ad6265SDimitry Andric assert(getOperandMapping(Idx).isValid() && 63381ad6265SDimitry Andric "We must have a mapping for reg operands"); 63481ad6265SDimitry Andric const RegisterBankInfo::ValueMapping &MOMapping = getOperandMapping(Idx); 63581ad6265SDimitry Andric (void)MOMapping; 63681ad6265SDimitry Andric // Register size in bits. 63781ad6265SDimitry Andric // This size must match what the mapping expects. 63806c3fb27SDimitry Andric assert(MOMapping.verify(*RBI, RBI->getSizeInBits( 63906c3fb27SDimitry Andric Reg, MF.getRegInfo(), 64006c3fb27SDimitry Andric *MF.getSubtarget().getRegisterInfo())) && 64181ad6265SDimitry Andric "Value mapping is invalid"); 64281ad6265SDimitry Andric } 64381ad6265SDimitry Andric return true; 64481ad6265SDimitry Andric } 64581ad6265SDimitry Andric 64681ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 64781ad6265SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::InstructionMapping::dump() const { 64881ad6265SDimitry Andric print(dbgs()); 64981ad6265SDimitry Andric dbgs() << '\n'; 65081ad6265SDimitry Andric } 65181ad6265SDimitry Andric #endif 65281ad6265SDimitry Andric 65381ad6265SDimitry Andric void RegisterBankInfo::InstructionMapping::print(raw_ostream &OS) const { 65481ad6265SDimitry Andric OS << "ID: " << getID() << " Cost: " << getCost() << " Mapping: "; 65581ad6265SDimitry Andric 65681ad6265SDimitry Andric for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) { 65781ad6265SDimitry Andric const ValueMapping &ValMapping = getOperandMapping(OpIdx); 65881ad6265SDimitry Andric if (OpIdx) 65981ad6265SDimitry Andric OS << ", "; 66081ad6265SDimitry Andric OS << "{ Idx: " << OpIdx << " Map: " << ValMapping << '}'; 66181ad6265SDimitry Andric } 66281ad6265SDimitry Andric } 66381ad6265SDimitry Andric 66481ad6265SDimitry Andric const int RegisterBankInfo::OperandsMapper::DontKnowIdx = -1; 66581ad6265SDimitry Andric 66681ad6265SDimitry Andric RegisterBankInfo::OperandsMapper::OperandsMapper( 66781ad6265SDimitry Andric MachineInstr &MI, const InstructionMapping &InstrMapping, 66881ad6265SDimitry Andric MachineRegisterInfo &MRI) 66981ad6265SDimitry Andric : MRI(MRI), MI(MI), InstrMapping(InstrMapping) { 67081ad6265SDimitry Andric unsigned NumOpds = InstrMapping.getNumOperands(); 67181ad6265SDimitry Andric OpToNewVRegIdx.resize(NumOpds, OperandsMapper::DontKnowIdx); 67281ad6265SDimitry Andric assert(InstrMapping.verify(MI) && "Invalid mapping for MI"); 67381ad6265SDimitry Andric } 67481ad6265SDimitry Andric 67581ad6265SDimitry Andric iterator_range<SmallVectorImpl<Register>::iterator> 67681ad6265SDimitry Andric RegisterBankInfo::OperandsMapper::getVRegsMem(unsigned OpIdx) { 67781ad6265SDimitry Andric assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access"); 67881ad6265SDimitry Andric unsigned NumPartialVal = 67981ad6265SDimitry Andric getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns; 68081ad6265SDimitry Andric int StartIdx = OpToNewVRegIdx[OpIdx]; 68181ad6265SDimitry Andric 68281ad6265SDimitry Andric if (StartIdx == OperandsMapper::DontKnowIdx) { 68381ad6265SDimitry Andric // This is the first time we try to access OpIdx. 68481ad6265SDimitry Andric // Create the cells that will hold all the partial values at the 68581ad6265SDimitry Andric // end of the list of NewVReg. 68681ad6265SDimitry Andric StartIdx = NewVRegs.size(); 68781ad6265SDimitry Andric OpToNewVRegIdx[OpIdx] = StartIdx; 68881ad6265SDimitry Andric for (unsigned i = 0; i < NumPartialVal; ++i) 68981ad6265SDimitry Andric NewVRegs.push_back(0); 69081ad6265SDimitry Andric } 69181ad6265SDimitry Andric SmallVectorImpl<Register>::iterator End = 69281ad6265SDimitry Andric getNewVRegsEnd(StartIdx, NumPartialVal); 69381ad6265SDimitry Andric 69481ad6265SDimitry Andric return make_range(&NewVRegs[StartIdx], End); 69581ad6265SDimitry Andric } 69681ad6265SDimitry Andric 69781ad6265SDimitry Andric SmallVectorImpl<Register>::const_iterator 69881ad6265SDimitry Andric RegisterBankInfo::OperandsMapper::getNewVRegsEnd(unsigned StartIdx, 69981ad6265SDimitry Andric unsigned NumVal) const { 70081ad6265SDimitry Andric return const_cast<OperandsMapper *>(this)->getNewVRegsEnd(StartIdx, NumVal); 70181ad6265SDimitry Andric } 70281ad6265SDimitry Andric SmallVectorImpl<Register>::iterator 70381ad6265SDimitry Andric RegisterBankInfo::OperandsMapper::getNewVRegsEnd(unsigned StartIdx, 70481ad6265SDimitry Andric unsigned NumVal) { 70581ad6265SDimitry Andric assert((NewVRegs.size() == StartIdx + NumVal || 70681ad6265SDimitry Andric NewVRegs.size() > StartIdx + NumVal) && 70781ad6265SDimitry Andric "NewVRegs too small to contain all the partial mapping"); 70881ad6265SDimitry Andric return NewVRegs.size() <= StartIdx + NumVal ? NewVRegs.end() 70981ad6265SDimitry Andric : &NewVRegs[StartIdx + NumVal]; 71081ad6265SDimitry Andric } 71181ad6265SDimitry Andric 71281ad6265SDimitry Andric void RegisterBankInfo::OperandsMapper::createVRegs(unsigned OpIdx) { 71381ad6265SDimitry Andric assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access"); 71481ad6265SDimitry Andric iterator_range<SmallVectorImpl<Register>::iterator> NewVRegsForOpIdx = 71581ad6265SDimitry Andric getVRegsMem(OpIdx); 71681ad6265SDimitry Andric const ValueMapping &ValMapping = getInstrMapping().getOperandMapping(OpIdx); 71781ad6265SDimitry Andric const PartialMapping *PartMap = ValMapping.begin(); 71881ad6265SDimitry Andric for (Register &NewVReg : NewVRegsForOpIdx) { 71981ad6265SDimitry Andric assert(PartMap != ValMapping.end() && "Out-of-bound access"); 72081ad6265SDimitry Andric assert(NewVReg == 0 && "Register has already been created"); 72181ad6265SDimitry Andric // The new registers are always bound to scalar with the right size. 72281ad6265SDimitry Andric // The actual type has to be set when the target does the mapping 72381ad6265SDimitry Andric // of the instruction. 72481ad6265SDimitry Andric // The rationale is that this generic code cannot guess how the 72581ad6265SDimitry Andric // target plans to split the input type. 72681ad6265SDimitry Andric NewVReg = MRI.createGenericVirtualRegister(LLT::scalar(PartMap->Length)); 72781ad6265SDimitry Andric MRI.setRegBank(NewVReg, *PartMap->RegBank); 72881ad6265SDimitry Andric ++PartMap; 72981ad6265SDimitry Andric } 73081ad6265SDimitry Andric } 73181ad6265SDimitry Andric 73281ad6265SDimitry Andric void RegisterBankInfo::OperandsMapper::setVRegs(unsigned OpIdx, 73381ad6265SDimitry Andric unsigned PartialMapIdx, 73481ad6265SDimitry Andric Register NewVReg) { 73581ad6265SDimitry Andric assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access"); 73681ad6265SDimitry Andric assert(getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns > 73781ad6265SDimitry Andric PartialMapIdx && 73881ad6265SDimitry Andric "Out-of-bound access for partial mapping"); 73981ad6265SDimitry Andric // Make sure the memory is initialized for that operand. 74081ad6265SDimitry Andric (void)getVRegsMem(OpIdx); 74181ad6265SDimitry Andric assert(NewVRegs[OpToNewVRegIdx[OpIdx] + PartialMapIdx] == 0 && 74281ad6265SDimitry Andric "This value is already set"); 74381ad6265SDimitry Andric NewVRegs[OpToNewVRegIdx[OpIdx] + PartialMapIdx] = NewVReg; 74481ad6265SDimitry Andric } 74581ad6265SDimitry Andric 74681ad6265SDimitry Andric iterator_range<SmallVectorImpl<Register>::const_iterator> 74781ad6265SDimitry Andric RegisterBankInfo::OperandsMapper::getVRegs(unsigned OpIdx, 74881ad6265SDimitry Andric bool ForDebug) const { 74981ad6265SDimitry Andric (void)ForDebug; 75081ad6265SDimitry Andric assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access"); 75181ad6265SDimitry Andric int StartIdx = OpToNewVRegIdx[OpIdx]; 75281ad6265SDimitry Andric 75381ad6265SDimitry Andric if (StartIdx == OperandsMapper::DontKnowIdx) 75481ad6265SDimitry Andric return make_range(NewVRegs.end(), NewVRegs.end()); 75581ad6265SDimitry Andric 75681ad6265SDimitry Andric unsigned PartMapSize = 75781ad6265SDimitry Andric getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns; 75881ad6265SDimitry Andric SmallVectorImpl<Register>::const_iterator End = 75981ad6265SDimitry Andric getNewVRegsEnd(StartIdx, PartMapSize); 76081ad6265SDimitry Andric iterator_range<SmallVectorImpl<Register>::const_iterator> Res = 76181ad6265SDimitry Andric make_range(&NewVRegs[StartIdx], End); 76281ad6265SDimitry Andric #ifndef NDEBUG 76381ad6265SDimitry Andric for (Register VReg : Res) 76481ad6265SDimitry Andric assert((VReg || ForDebug) && "Some registers are uninitialized"); 76581ad6265SDimitry Andric #endif 76681ad6265SDimitry Andric return Res; 76781ad6265SDimitry Andric } 76881ad6265SDimitry Andric 76981ad6265SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 77081ad6265SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::OperandsMapper::dump() const { 77181ad6265SDimitry Andric print(dbgs(), true); 77281ad6265SDimitry Andric dbgs() << '\n'; 77381ad6265SDimitry Andric } 77481ad6265SDimitry Andric #endif 77581ad6265SDimitry Andric 77681ad6265SDimitry Andric void RegisterBankInfo::OperandsMapper::print(raw_ostream &OS, 77781ad6265SDimitry Andric bool ForDebug) const { 77881ad6265SDimitry Andric unsigned NumOpds = getInstrMapping().getNumOperands(); 77981ad6265SDimitry Andric if (ForDebug) { 78081ad6265SDimitry Andric OS << "Mapping for " << getMI() << "\nwith " << getInstrMapping() << '\n'; 78181ad6265SDimitry Andric // Print out the internal state of the index table. 78281ad6265SDimitry Andric OS << "Populated indices (CellNumber, IndexInNewVRegs): "; 78381ad6265SDimitry Andric bool IsFirst = true; 78481ad6265SDimitry Andric for (unsigned Idx = 0; Idx != NumOpds; ++Idx) { 78581ad6265SDimitry Andric if (OpToNewVRegIdx[Idx] != DontKnowIdx) { 78681ad6265SDimitry Andric if (!IsFirst) 78781ad6265SDimitry Andric OS << ", "; 78881ad6265SDimitry Andric OS << '(' << Idx << ", " << OpToNewVRegIdx[Idx] << ')'; 78981ad6265SDimitry Andric IsFirst = false; 79081ad6265SDimitry Andric } 79181ad6265SDimitry Andric } 79281ad6265SDimitry Andric OS << '\n'; 79381ad6265SDimitry Andric } else 79481ad6265SDimitry Andric OS << "Mapping ID: " << getInstrMapping().getID() << ' '; 79581ad6265SDimitry Andric 79681ad6265SDimitry Andric OS << "Operand Mapping: "; 79781ad6265SDimitry Andric // If we have a function, we can pretty print the name of the registers. 79881ad6265SDimitry Andric // Otherwise we will print the raw numbers. 79981ad6265SDimitry Andric const TargetRegisterInfo *TRI = 80081ad6265SDimitry Andric getMI().getParent() && getMI().getMF() 80181ad6265SDimitry Andric ? getMI().getMF()->getSubtarget().getRegisterInfo() 80281ad6265SDimitry Andric : nullptr; 80381ad6265SDimitry Andric bool IsFirst = true; 80481ad6265SDimitry Andric for (unsigned Idx = 0; Idx != NumOpds; ++Idx) { 80581ad6265SDimitry Andric if (OpToNewVRegIdx[Idx] == DontKnowIdx) 80681ad6265SDimitry Andric continue; 80781ad6265SDimitry Andric if (!IsFirst) 80881ad6265SDimitry Andric OS << ", "; 80981ad6265SDimitry Andric IsFirst = false; 81081ad6265SDimitry Andric OS << '(' << printReg(getMI().getOperand(Idx).getReg(), TRI) << ", ["; 81181ad6265SDimitry Andric bool IsFirstNewVReg = true; 81281ad6265SDimitry Andric for (Register VReg : getVRegs(Idx)) { 81381ad6265SDimitry Andric if (!IsFirstNewVReg) 81481ad6265SDimitry Andric OS << ", "; 81581ad6265SDimitry Andric IsFirstNewVReg = false; 81681ad6265SDimitry Andric OS << printReg(VReg, TRI); 81781ad6265SDimitry Andric } 81881ad6265SDimitry Andric OS << "])"; 81981ad6265SDimitry Andric } 82081ad6265SDimitry Andric } 821