xref: /src/contrib/llvm-project/llvm/lib/CodeGen/RegisterBankInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
101095a5dSDimitry Andric //===- llvm/CodeGen/GlobalISel/RegisterBankInfo.cpp --------------*- C++ -*-==//
201095a5dSDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
601095a5dSDimitry Andric //
701095a5dSDimitry Andric //===----------------------------------------------------------------------===//
801095a5dSDimitry Andric /// \file
901095a5dSDimitry Andric /// This file implements the RegisterBankInfo class.
1001095a5dSDimitry Andric //===----------------------------------------------------------------------===//
1101095a5dSDimitry Andric 
12145449b1SDimitry Andric #include "llvm/CodeGen/RegisterBankInfo.h"
137fa27ce4SDimitry Andric #include "llvm/ADT/APInt.h"
1401095a5dSDimitry Andric #include "llvm/ADT/SmallVector.h"
15b915e9e0SDimitry Andric #include "llvm/ADT/Statistic.h"
1601095a5dSDimitry Andric #include "llvm/ADT/iterator_range.h"
1701095a5dSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
1801095a5dSDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
19145449b1SDimitry Andric #include "llvm/CodeGen/RegisterBank.h"
20044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetOpcodes.h"
21044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetRegisterInfo.h"
22044eb2f6SDimitry Andric #include "llvm/CodeGen/TargetSubtargetInfo.h"
23eb11fae6SDimitry Andric #include "llvm/Config/llvm-config.h"
2401095a5dSDimitry Andric #include "llvm/Support/Debug.h"
2501095a5dSDimitry Andric #include "llvm/Support/raw_ostream.h"
2601095a5dSDimitry Andric 
2701095a5dSDimitry Andric #include <algorithm> // For std::max.
2801095a5dSDimitry Andric 
2901095a5dSDimitry Andric #define DEBUG_TYPE "registerbankinfo"
3001095a5dSDimitry Andric 
3101095a5dSDimitry Andric using namespace llvm;
3201095a5dSDimitry Andric 
33b915e9e0SDimitry Andric STATISTIC(NumPartialMappingsCreated,
34b915e9e0SDimitry Andric           "Number of partial mappings dynamically created");
35b915e9e0SDimitry Andric STATISTIC(NumPartialMappingsAccessed,
36b915e9e0SDimitry Andric           "Number of partial mappings dynamically accessed");
37b915e9e0SDimitry Andric STATISTIC(NumValueMappingsCreated,
38b915e9e0SDimitry Andric           "Number of value mappings dynamically created");
39b915e9e0SDimitry Andric STATISTIC(NumValueMappingsAccessed,
40b915e9e0SDimitry Andric           "Number of value mappings dynamically accessed");
41b915e9e0SDimitry Andric STATISTIC(NumOperandsMappingsCreated,
42b915e9e0SDimitry Andric           "Number of operands mappings dynamically created");
43b915e9e0SDimitry Andric STATISTIC(NumOperandsMappingsAccessed,
44b915e9e0SDimitry Andric           "Number of operands mappings dynamically accessed");
45c46e6a59SDimitry Andric STATISTIC(NumInstructionMappingsCreated,
46c46e6a59SDimitry Andric           "Number of instruction mappings dynamically created");
47c46e6a59SDimitry Andric STATISTIC(NumInstructionMappingsAccessed,
48c46e6a59SDimitry Andric           "Number of instruction mappings dynamically accessed");
49b915e9e0SDimitry Andric 
5001095a5dSDimitry Andric const unsigned RegisterBankInfo::DefaultMappingID = UINT_MAX;
5101095a5dSDimitry Andric const unsigned RegisterBankInfo::InvalidMappingID = UINT_MAX - 1;
5201095a5dSDimitry Andric 
5301095a5dSDimitry Andric //------------------------------------------------------------------------------
5401095a5dSDimitry Andric // RegisterBankInfo implementation.
5501095a5dSDimitry Andric //------------------------------------------------------------------------------
RegisterBankInfo(const RegisterBank ** RegBanks,unsigned NumRegBanks,const unsigned * Sizes,unsigned HwMode)567fa27ce4SDimitry Andric RegisterBankInfo::RegisterBankInfo(const RegisterBank **RegBanks,
577fa27ce4SDimitry Andric                                    unsigned NumRegBanks, const unsigned *Sizes,
587fa27ce4SDimitry Andric                                    unsigned HwMode)
597fa27ce4SDimitry Andric     : RegBanks(RegBanks), NumRegBanks(NumRegBanks), Sizes(Sizes),
607fa27ce4SDimitry Andric       HwMode(HwMode) {
617e7b6700SDimitry Andric #ifndef NDEBUG
62581a6d85SDimitry Andric   for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) {
63b915e9e0SDimitry Andric     assert(RegBanks[Idx] != nullptr && "Invalid RegisterBank");
64b1c73532SDimitry Andric     assert(RegBanks[Idx]->getID() == Idx &&
65b1c73532SDimitry Andric            "RegisterBank ID should match index");
66581a6d85SDimitry Andric   }
677e7b6700SDimitry Andric #endif // NDEBUG
68b915e9e0SDimitry Andric }
69b915e9e0SDimitry Andric 
verify(const TargetRegisterInfo & TRI) const7001095a5dSDimitry Andric bool RegisterBankInfo::verify(const TargetRegisterInfo &TRI) const {
717e7b6700SDimitry Andric #ifndef NDEBUG
727e7b6700SDimitry Andric   for (unsigned Idx = 0, End = getNumRegBanks(); Idx != End; ++Idx) {
7301095a5dSDimitry Andric     const RegisterBank &RegBank = getRegBank(Idx);
7401095a5dSDimitry Andric     assert(Idx == RegBank.getID() &&
7501095a5dSDimitry Andric            "ID does not match the index in the array");
76eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "Verify " << RegBank << '\n');
777fa27ce4SDimitry Andric     assert(RegBank.verify(*this, TRI) && "RegBank is invalid");
787e7b6700SDimitry Andric   }
797e7b6700SDimitry Andric #endif // NDEBUG
8001095a5dSDimitry Andric   return true;
8101095a5dSDimitry Andric }
8201095a5dSDimitry Andric 
8301095a5dSDimitry Andric const RegisterBank *
getRegBank(Register Reg,const MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI) const84e6d15924SDimitry Andric RegisterBankInfo::getRegBank(Register Reg, const MachineRegisterInfo &MRI,
8501095a5dSDimitry Andric                              const TargetRegisterInfo &TRI) const {
867fa27ce4SDimitry Andric   if (!Reg.isVirtual()) {
87706b4fc4SDimitry Andric     // FIXME: This was probably a copy to a virtual register that does have a
88706b4fc4SDimitry Andric     // type we could use.
897fa27ce4SDimitry Andric     const TargetRegisterClass *RC = getMinimalPhysRegClass(Reg, TRI);
907fa27ce4SDimitry Andric     return RC ? &getRegBankFromRegClass(*RC, LLT()) : nullptr;
91706b4fc4SDimitry Andric   }
9201095a5dSDimitry Andric 
9301095a5dSDimitry Andric   const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
947fa27ce4SDimitry Andric   if (auto *RB = dyn_cast_if_present<const RegisterBank *>(RegClassOrBank))
95b915e9e0SDimitry Andric     return RB;
967fa27ce4SDimitry Andric   if (auto *RC =
977fa27ce4SDimitry Andric           dyn_cast_if_present<const TargetRegisterClass *>(RegClassOrBank))
98706b4fc4SDimitry Andric     return &getRegBankFromRegClass(*RC, MRI.getType(Reg));
9901095a5dSDimitry Andric   return nullptr;
10001095a5dSDimitry Andric }
10101095a5dSDimitry Andric 
1027fa27ce4SDimitry Andric const TargetRegisterClass *
getMinimalPhysRegClass(Register Reg,const TargetRegisterInfo & TRI) const103e6d15924SDimitry Andric RegisterBankInfo::getMinimalPhysRegClass(Register Reg,
104044eb2f6SDimitry Andric                                          const TargetRegisterInfo &TRI) const {
105e3b55780SDimitry Andric   assert(Reg.isPhysical() && "Reg must be a physreg");
106044eb2f6SDimitry Andric   const auto &RegRCIt = PhysRegMinimalRCs.find(Reg);
107044eb2f6SDimitry Andric   if (RegRCIt != PhysRegMinimalRCs.end())
1087fa27ce4SDimitry Andric     return RegRCIt->second;
1097fa27ce4SDimitry Andric   const TargetRegisterClass *PhysRC = TRI.getMinimalPhysRegClassLLT(Reg, LLT());
110044eb2f6SDimitry Andric   PhysRegMinimalRCs[Reg] = PhysRC;
1117fa27ce4SDimitry Andric   return PhysRC;
112044eb2f6SDimitry Andric }
113044eb2f6SDimitry Andric 
getRegBankFromConstraints(const MachineInstr & MI,unsigned OpIdx,const TargetInstrInfo & TII,const MachineRegisterInfo & MRI) const11401095a5dSDimitry Andric const RegisterBank *RegisterBankInfo::getRegBankFromConstraints(
11501095a5dSDimitry Andric     const MachineInstr &MI, unsigned OpIdx, const TargetInstrInfo &TII,
116706b4fc4SDimitry Andric     const MachineRegisterInfo &MRI) const {
117706b4fc4SDimitry Andric   const TargetRegisterInfo *TRI = MRI.getTargetRegisterInfo();
118706b4fc4SDimitry Andric 
11901095a5dSDimitry Andric   // The mapping of the registers may be available via the
12001095a5dSDimitry Andric   // register class constraints.
121706b4fc4SDimitry Andric   const TargetRegisterClass *RC = MI.getRegClassConstraint(OpIdx, &TII, TRI);
12201095a5dSDimitry Andric 
12301095a5dSDimitry Andric   if (!RC)
12401095a5dSDimitry Andric     return nullptr;
12501095a5dSDimitry Andric 
126706b4fc4SDimitry Andric   Register Reg = MI.getOperand(OpIdx).getReg();
127706b4fc4SDimitry Andric   const RegisterBank &RegBank = getRegBankFromRegClass(*RC, MRI.getType(Reg));
128f65dcba8SDimitry Andric   // Check that the target properly implemented getRegBankFromRegClass.
12901095a5dSDimitry Andric   assert(RegBank.covers(*RC) &&
13001095a5dSDimitry Andric          "The mapping of the register bank does not make sense");
13101095a5dSDimitry Andric   return &RegBank;
13201095a5dSDimitry Andric }
13301095a5dSDimitry Andric 
constrainGenericRegister(Register Reg,const TargetRegisterClass & RC,MachineRegisterInfo & MRI)134b915e9e0SDimitry Andric const TargetRegisterClass *RegisterBankInfo::constrainGenericRegister(
135e6d15924SDimitry Andric     Register Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI) {
136b915e9e0SDimitry Andric 
137b915e9e0SDimitry Andric   // If the register already has a class, fallback to MRI::constrainRegClass.
138b915e9e0SDimitry Andric   auto &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
1397fa27ce4SDimitry Andric   if (isa<const TargetRegisterClass *>(RegClassOrBank))
140b915e9e0SDimitry Andric     return MRI.constrainRegClass(Reg, &RC);
141b915e9e0SDimitry Andric 
1427fa27ce4SDimitry Andric   const RegisterBank *RB = cast<const RegisterBank *>(RegClassOrBank);
143b915e9e0SDimitry Andric   // Otherwise, all we can do is ensure the bank covers the class, and set it.
144b915e9e0SDimitry Andric   if (RB && !RB->covers(RC))
145b915e9e0SDimitry Andric     return nullptr;
146b915e9e0SDimitry Andric 
147b915e9e0SDimitry Andric   // If nothing was set or the class is simply compatible, set it.
148b915e9e0SDimitry Andric   MRI.setRegClass(Reg, &RC);
149b915e9e0SDimitry Andric   return &RC;
150b915e9e0SDimitry Andric }
151b915e9e0SDimitry Andric 
15271d5a254SDimitry Andric /// Check whether or not \p MI should be treated like a copy
15371d5a254SDimitry Andric /// for the mappings.
15471d5a254SDimitry Andric /// Copy like instruction are special for mapping because
15571d5a254SDimitry Andric /// they don't have actual register constraints. Moreover,
15671d5a254SDimitry Andric /// they sometimes have register classes assigned and we can
15771d5a254SDimitry Andric /// just use that instead of failing to provide a generic mapping.
isCopyLike(const MachineInstr & MI)15871d5a254SDimitry Andric static bool isCopyLike(const MachineInstr &MI) {
15971d5a254SDimitry Andric   return MI.isCopy() || MI.isPHI() ||
16071d5a254SDimitry Andric          MI.getOpcode() == TargetOpcode::REG_SEQUENCE;
16171d5a254SDimitry Andric }
16271d5a254SDimitry Andric 
163c46e6a59SDimitry Andric const RegisterBankInfo::InstructionMapping &
getInstrMappingImpl(const MachineInstr & MI) const16401095a5dSDimitry Andric RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const {
165b915e9e0SDimitry Andric   // For copies we want to walk over the operands and try to find one
166b915e9e0SDimitry Andric   // that has a register bank since the instruction itself will not get
167b915e9e0SDimitry Andric   // us any constraint.
16871d5a254SDimitry Andric   bool IsCopyLike = isCopyLike(MI);
169b915e9e0SDimitry Andric   // For copy like instruction, only the mapping of the definition
170b915e9e0SDimitry Andric   // is important. The rest is not constrained.
17171d5a254SDimitry Andric   unsigned NumOperandsForMapping = IsCopyLike ? 1 : MI.getNumOperands();
172b915e9e0SDimitry Andric 
173044eb2f6SDimitry Andric   const MachineFunction &MF = *MI.getMF();
17401095a5dSDimitry Andric   const TargetSubtargetInfo &STI = MF.getSubtarget();
17501095a5dSDimitry Andric   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
17601095a5dSDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
17701095a5dSDimitry Andric   // We may need to query the instruction encoding to guess the mapping.
17801095a5dSDimitry Andric   const TargetInstrInfo &TII = *STI.getInstrInfo();
17901095a5dSDimitry Andric 
18001095a5dSDimitry Andric   // Before doing anything complicated check if the mapping is not
18101095a5dSDimitry Andric   // directly available.
18201095a5dSDimitry Andric   bool CompleteMapping = true;
183b915e9e0SDimitry Andric 
184b915e9e0SDimitry Andric   SmallVector<const ValueMapping *, 8> OperandsMapping(NumOperandsForMapping);
185b915e9e0SDimitry Andric   for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx;
186b915e9e0SDimitry Andric        ++OpIdx) {
18701095a5dSDimitry Andric     const MachineOperand &MO = MI.getOperand(OpIdx);
18801095a5dSDimitry Andric     if (!MO.isReg())
18901095a5dSDimitry Andric       continue;
190e6d15924SDimitry Andric     Register Reg = MO.getReg();
19101095a5dSDimitry Andric     if (!Reg)
19201095a5dSDimitry Andric       continue;
19301095a5dSDimitry Andric     // The register bank of Reg is just a side effect of the current
19401095a5dSDimitry Andric     // excution and in particular, there is no reason to believe this
19501095a5dSDimitry Andric     // is the best default mapping for the current instruction.  Keep
19601095a5dSDimitry Andric     // it as an alternative register bank if we cannot figure out
19701095a5dSDimitry Andric     // something.
19801095a5dSDimitry Andric     const RegisterBank *AltRegBank = getRegBank(Reg, MRI, TRI);
19901095a5dSDimitry Andric     // For copy-like instruction, we want to reuse the register bank
20001095a5dSDimitry Andric     // that is already set on Reg, if any, since those instructions do
20101095a5dSDimitry Andric     // not have any constraints.
20271d5a254SDimitry Andric     const RegisterBank *CurRegBank = IsCopyLike ? AltRegBank : nullptr;
20301095a5dSDimitry Andric     if (!CurRegBank) {
20401095a5dSDimitry Andric       // If this is a target specific instruction, we can deduce
20501095a5dSDimitry Andric       // the register bank from the encoding constraints.
206706b4fc4SDimitry Andric       CurRegBank = getRegBankFromConstraints(MI, OpIdx, TII, MRI);
20701095a5dSDimitry Andric       if (!CurRegBank) {
20801095a5dSDimitry Andric         // All our attempts failed, give up.
20901095a5dSDimitry Andric         CompleteMapping = false;
21001095a5dSDimitry Andric 
21171d5a254SDimitry Andric         if (!IsCopyLike)
21201095a5dSDimitry Andric           // MI does not carry enough information to guess the mapping.
213c46e6a59SDimitry Andric           return getInvalidInstructionMapping();
21401095a5dSDimitry Andric         continue;
21501095a5dSDimitry Andric       }
21601095a5dSDimitry Andric     }
217e6d15924SDimitry Andric 
218e6d15924SDimitry Andric     unsigned Size = getSizeInBits(Reg, MRI, TRI);
219e6d15924SDimitry Andric     const ValueMapping *ValMapping = &getValueMapping(0, Size, *CurRegBank);
22071d5a254SDimitry Andric     if (IsCopyLike) {
221e6d15924SDimitry Andric       if (!OperandsMapping[0]) {
222e6d15924SDimitry Andric         if (MI.isRegSequence()) {
223e6d15924SDimitry Andric           // For reg_sequence, the result size does not match the input.
224e6d15924SDimitry Andric           unsigned ResultSize = getSizeInBits(MI.getOperand(0).getReg(),
225e6d15924SDimitry Andric                                               MRI, TRI);
226e6d15924SDimitry Andric           OperandsMapping[0] = &getValueMapping(0, ResultSize, *CurRegBank);
227e6d15924SDimitry Andric         } else {
228b915e9e0SDimitry Andric           OperandsMapping[0] = ValMapping;
229e6d15924SDimitry Andric         }
230e6d15924SDimitry Andric       }
231e6d15924SDimitry Andric 
232e6d15924SDimitry Andric       // The default handling assumes any register bank can be copied to any
233e6d15924SDimitry Andric       // other. If this isn't the case, the target should specially deal with
234e6d15924SDimitry Andric       // reg_sequence/phi. There may also be unsatisfiable copies.
235e6d15924SDimitry Andric       for (; OpIdx != EndIdx; ++OpIdx) {
236e6d15924SDimitry Andric         const MachineOperand &MO = MI.getOperand(OpIdx);
237e6d15924SDimitry Andric         if (!MO.isReg())
238e6d15924SDimitry Andric           continue;
239e6d15924SDimitry Andric         Register Reg = MO.getReg();
240e6d15924SDimitry Andric         if (!Reg)
241e6d15924SDimitry Andric           continue;
242e6d15924SDimitry Andric 
243e6d15924SDimitry Andric         const RegisterBank *AltRegBank = getRegBank(Reg, MRI, TRI);
244e6d15924SDimitry Andric         if (AltRegBank &&
245e6d15924SDimitry Andric             cannotCopy(*CurRegBank, *AltRegBank, getSizeInBits(Reg, MRI, TRI)))
246e6d15924SDimitry Andric           return getInvalidInstructionMapping();
247e6d15924SDimitry Andric       }
248e6d15924SDimitry Andric 
249b915e9e0SDimitry Andric       CompleteMapping = true;
250b915e9e0SDimitry Andric       break;
25101095a5dSDimitry Andric     }
252e6d15924SDimitry Andric 
253b915e9e0SDimitry Andric     OperandsMapping[OpIdx] = ValMapping;
25401095a5dSDimitry Andric   }
25501095a5dSDimitry Andric 
256e6d15924SDimitry Andric   if (IsCopyLike && !CompleteMapping) {
257b915e9e0SDimitry Andric     // No way to deduce the type from what we have.
258c46e6a59SDimitry Andric     return getInvalidInstructionMapping();
259e6d15924SDimitry Andric   }
26001095a5dSDimitry Andric 
261b915e9e0SDimitry Andric   assert(CompleteMapping && "Setting an uncomplete mapping");
262c46e6a59SDimitry Andric   return getInstructionMapping(
263c46e6a59SDimitry Andric       DefaultMappingID, /*Cost*/ 1,
264c46e6a59SDimitry Andric       /*OperandsMapping*/ getOperandsMapping(OperandsMapping),
265c46e6a59SDimitry Andric       NumOperandsForMapping);
26601095a5dSDimitry Andric }
26701095a5dSDimitry Andric 
268b915e9e0SDimitry Andric /// Hashing function for PartialMapping.
hashPartialMapping(unsigned StartIdx,unsigned Length,const RegisterBank * RegBank)269b915e9e0SDimitry Andric static hash_code hashPartialMapping(unsigned StartIdx, unsigned Length,
270b915e9e0SDimitry Andric                                     const RegisterBank *RegBank) {
271b915e9e0SDimitry Andric   return hash_combine(StartIdx, Length, RegBank ? RegBank->getID() : 0);
272b915e9e0SDimitry Andric }
273b915e9e0SDimitry Andric 
274b915e9e0SDimitry Andric /// Overloaded version of hash_value for a PartialMapping.
275b915e9e0SDimitry Andric hash_code
hash_value(const RegisterBankInfo::PartialMapping & PartMapping)276b915e9e0SDimitry Andric llvm::hash_value(const RegisterBankInfo::PartialMapping &PartMapping) {
277b915e9e0SDimitry Andric   return hashPartialMapping(PartMapping.StartIdx, PartMapping.Length,
278b915e9e0SDimitry Andric                             PartMapping.RegBank);
279b915e9e0SDimitry Andric }
280b915e9e0SDimitry Andric 
281b915e9e0SDimitry Andric const RegisterBankInfo::PartialMapping &
getPartialMapping(unsigned StartIdx,unsigned Length,const RegisterBank & RegBank) const282b915e9e0SDimitry Andric RegisterBankInfo::getPartialMapping(unsigned StartIdx, unsigned Length,
283b915e9e0SDimitry Andric                                     const RegisterBank &RegBank) const {
284b915e9e0SDimitry Andric   ++NumPartialMappingsAccessed;
285b915e9e0SDimitry Andric 
286b915e9e0SDimitry Andric   hash_code Hash = hashPartialMapping(StartIdx, Length, &RegBank);
287b915e9e0SDimitry Andric   const auto &It = MapOfPartialMappings.find(Hash);
288b915e9e0SDimitry Andric   if (It != MapOfPartialMappings.end())
289b915e9e0SDimitry Andric     return *It->second;
290b915e9e0SDimitry Andric 
291b915e9e0SDimitry Andric   ++NumPartialMappingsCreated;
292b915e9e0SDimitry Andric 
29371d5a254SDimitry Andric   auto &PartMapping = MapOfPartialMappings[Hash];
2941d5ae102SDimitry Andric   PartMapping = std::make_unique<PartialMapping>(StartIdx, Length, RegBank);
295b915e9e0SDimitry Andric   return *PartMapping;
296b915e9e0SDimitry Andric }
297b915e9e0SDimitry Andric 
298b915e9e0SDimitry Andric const RegisterBankInfo::ValueMapping &
getValueMapping(unsigned StartIdx,unsigned Length,const RegisterBank & RegBank) const299b915e9e0SDimitry Andric RegisterBankInfo::getValueMapping(unsigned StartIdx, unsigned Length,
300b915e9e0SDimitry Andric                                   const RegisterBank &RegBank) const {
301b915e9e0SDimitry Andric   return getValueMapping(&getPartialMapping(StartIdx, Length, RegBank), 1);
302b915e9e0SDimitry Andric }
303b915e9e0SDimitry Andric 
304b915e9e0SDimitry Andric static hash_code
hashValueMapping(const RegisterBankInfo::PartialMapping * BreakDown,unsigned NumBreakDowns)305b915e9e0SDimitry Andric hashValueMapping(const RegisterBankInfo::PartialMapping *BreakDown,
306b915e9e0SDimitry Andric                  unsigned NumBreakDowns) {
307b915e9e0SDimitry Andric   if (LLVM_LIKELY(NumBreakDowns == 1))
308b915e9e0SDimitry Andric     return hash_value(*BreakDown);
309b915e9e0SDimitry Andric   SmallVector<size_t, 8> Hashes(NumBreakDowns);
310b915e9e0SDimitry Andric   for (unsigned Idx = 0; Idx != NumBreakDowns; ++Idx)
311b915e9e0SDimitry Andric     Hashes.push_back(hash_value(BreakDown[Idx]));
312b915e9e0SDimitry Andric   return hash_combine_range(Hashes.begin(), Hashes.end());
313b915e9e0SDimitry Andric }
314b915e9e0SDimitry Andric 
315b915e9e0SDimitry Andric const RegisterBankInfo::ValueMapping &
getValueMapping(const PartialMapping * BreakDown,unsigned NumBreakDowns) const316b915e9e0SDimitry Andric RegisterBankInfo::getValueMapping(const PartialMapping *BreakDown,
317b915e9e0SDimitry Andric                                   unsigned NumBreakDowns) const {
318b915e9e0SDimitry Andric   ++NumValueMappingsAccessed;
319b915e9e0SDimitry Andric 
320b915e9e0SDimitry Andric   hash_code Hash = hashValueMapping(BreakDown, NumBreakDowns);
321b915e9e0SDimitry Andric   const auto &It = MapOfValueMappings.find(Hash);
322b915e9e0SDimitry Andric   if (It != MapOfValueMappings.end())
323b915e9e0SDimitry Andric     return *It->second;
324b915e9e0SDimitry Andric 
325b915e9e0SDimitry Andric   ++NumValueMappingsCreated;
326b915e9e0SDimitry Andric 
32771d5a254SDimitry Andric   auto &ValMapping = MapOfValueMappings[Hash];
3281d5ae102SDimitry Andric   ValMapping = std::make_unique<ValueMapping>(BreakDown, NumBreakDowns);
329b915e9e0SDimitry Andric   return *ValMapping;
330b915e9e0SDimitry Andric }
331b915e9e0SDimitry Andric 
332b915e9e0SDimitry Andric template <typename Iterator>
333b915e9e0SDimitry Andric const RegisterBankInfo::ValueMapping *
getOperandsMapping(Iterator Begin,Iterator End) const334b915e9e0SDimitry Andric RegisterBankInfo::getOperandsMapping(Iterator Begin, Iterator End) const {
335b915e9e0SDimitry Andric 
336b915e9e0SDimitry Andric   ++NumOperandsMappingsAccessed;
337b915e9e0SDimitry Andric 
338b915e9e0SDimitry Andric   // The addresses of the value mapping are unique.
339b915e9e0SDimitry Andric   // Therefore, we can use them directly to hash the operand mapping.
340b915e9e0SDimitry Andric   hash_code Hash = hash_combine_range(Begin, End);
34171d5a254SDimitry Andric   auto &Res = MapOfOperandsMappings[Hash];
34271d5a254SDimitry Andric   if (Res)
34371d5a254SDimitry Andric     return Res.get();
344b915e9e0SDimitry Andric 
345b915e9e0SDimitry Andric   ++NumOperandsMappingsCreated;
346b915e9e0SDimitry Andric 
347b915e9e0SDimitry Andric   // Create the array of ValueMapping.
348b915e9e0SDimitry Andric   // Note: this array will not hash to this instance of operands
349b915e9e0SDimitry Andric   // mapping, because we use the pointer of the ValueMapping
350b915e9e0SDimitry Andric   // to hash and we expect them to uniquely identify an instance
351b915e9e0SDimitry Andric   // of value mapping.
3521d5ae102SDimitry Andric   Res = std::make_unique<ValueMapping[]>(std::distance(Begin, End));
353b915e9e0SDimitry Andric   unsigned Idx = 0;
354b915e9e0SDimitry Andric   for (Iterator It = Begin; It != End; ++It, ++Idx) {
355b915e9e0SDimitry Andric     const ValueMapping *ValMap = *It;
356b915e9e0SDimitry Andric     if (!ValMap)
357b915e9e0SDimitry Andric       continue;
358b915e9e0SDimitry Andric     Res[Idx] = *ValMap;
359b915e9e0SDimitry Andric   }
36071d5a254SDimitry Andric   return Res.get();
361b915e9e0SDimitry Andric }
362b915e9e0SDimitry Andric 
getOperandsMapping(const SmallVectorImpl<const RegisterBankInfo::ValueMapping * > & OpdsMapping) const363b915e9e0SDimitry Andric const RegisterBankInfo::ValueMapping *RegisterBankInfo::getOperandsMapping(
364b915e9e0SDimitry Andric     const SmallVectorImpl<const RegisterBankInfo::ValueMapping *> &OpdsMapping)
365b915e9e0SDimitry Andric     const {
366b915e9e0SDimitry Andric   return getOperandsMapping(OpdsMapping.begin(), OpdsMapping.end());
367b915e9e0SDimitry Andric }
368b915e9e0SDimitry Andric 
getOperandsMapping(std::initializer_list<const RegisterBankInfo::ValueMapping * > OpdsMapping) const369b915e9e0SDimitry Andric const RegisterBankInfo::ValueMapping *RegisterBankInfo::getOperandsMapping(
370b915e9e0SDimitry Andric     std::initializer_list<const RegisterBankInfo::ValueMapping *> OpdsMapping)
371b915e9e0SDimitry Andric     const {
372b915e9e0SDimitry Andric   return getOperandsMapping(OpdsMapping.begin(), OpdsMapping.end());
373b915e9e0SDimitry Andric }
374b915e9e0SDimitry Andric 
375c46e6a59SDimitry Andric static hash_code
hashInstructionMapping(unsigned ID,unsigned Cost,const RegisterBankInfo::ValueMapping * OperandsMapping,unsigned NumOperands)376c46e6a59SDimitry Andric hashInstructionMapping(unsigned ID, unsigned Cost,
377c46e6a59SDimitry Andric                        const RegisterBankInfo::ValueMapping *OperandsMapping,
378c46e6a59SDimitry Andric                        unsigned NumOperands) {
379c46e6a59SDimitry Andric   return hash_combine(ID, Cost, OperandsMapping, NumOperands);
380c46e6a59SDimitry Andric }
381c46e6a59SDimitry Andric 
382c46e6a59SDimitry Andric const RegisterBankInfo::InstructionMapping &
getInstructionMappingImpl(bool IsInvalid,unsigned ID,unsigned Cost,const RegisterBankInfo::ValueMapping * OperandsMapping,unsigned NumOperands) const383c46e6a59SDimitry Andric RegisterBankInfo::getInstructionMappingImpl(
384c46e6a59SDimitry Andric     bool IsInvalid, unsigned ID, unsigned Cost,
385c46e6a59SDimitry Andric     const RegisterBankInfo::ValueMapping *OperandsMapping,
386c46e6a59SDimitry Andric     unsigned NumOperands) const {
387c46e6a59SDimitry Andric   assert(((IsInvalid && ID == InvalidMappingID && Cost == 0 &&
388c46e6a59SDimitry Andric            OperandsMapping == nullptr && NumOperands == 0) ||
389c46e6a59SDimitry Andric           !IsInvalid) &&
390c46e6a59SDimitry Andric          "Mismatch argument for invalid input");
391c46e6a59SDimitry Andric   ++NumInstructionMappingsAccessed;
392c46e6a59SDimitry Andric 
393c46e6a59SDimitry Andric   hash_code Hash =
394c46e6a59SDimitry Andric       hashInstructionMapping(ID, Cost, OperandsMapping, NumOperands);
395c46e6a59SDimitry Andric   const auto &It = MapOfInstructionMappings.find(Hash);
396c46e6a59SDimitry Andric   if (It != MapOfInstructionMappings.end())
397c46e6a59SDimitry Andric     return *It->second;
398c46e6a59SDimitry Andric 
399c46e6a59SDimitry Andric   ++NumInstructionMappingsCreated;
400c46e6a59SDimitry Andric 
401c46e6a59SDimitry Andric   auto &InstrMapping = MapOfInstructionMappings[Hash];
4021d5ae102SDimitry Andric   InstrMapping = std::make_unique<InstructionMapping>(
403c46e6a59SDimitry Andric       ID, Cost, OperandsMapping, NumOperands);
404c46e6a59SDimitry Andric   return *InstrMapping;
405c46e6a59SDimitry Andric }
406c46e6a59SDimitry Andric 
407c46e6a59SDimitry Andric const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const40801095a5dSDimitry Andric RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
409c46e6a59SDimitry Andric   const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI);
41001095a5dSDimitry Andric   if (Mapping.isValid())
41101095a5dSDimitry Andric     return Mapping;
41201095a5dSDimitry Andric   llvm_unreachable("The target must implement this");
41301095a5dSDimitry Andric }
41401095a5dSDimitry Andric 
41501095a5dSDimitry Andric RegisterBankInfo::InstructionMappings
getInstrPossibleMappings(const MachineInstr & MI) const41601095a5dSDimitry Andric RegisterBankInfo::getInstrPossibleMappings(const MachineInstr &MI) const {
41701095a5dSDimitry Andric   InstructionMappings PossibleMappings;
418e6d15924SDimitry Andric   const auto &Mapping = getInstrMapping(MI);
419e6d15924SDimitry Andric   if (Mapping.isValid()) {
42001095a5dSDimitry Andric     // Put the default mapping first.
421e6d15924SDimitry Andric     PossibleMappings.push_back(&Mapping);
422e6d15924SDimitry Andric   }
423e6d15924SDimitry Andric 
42401095a5dSDimitry Andric   // Then the alternative mapping, if any.
42501095a5dSDimitry Andric   InstructionMappings AltMappings = getInstrAlternativeMappings(MI);
426b60736ecSDimitry Andric   append_range(PossibleMappings, AltMappings);
42701095a5dSDimitry Andric #ifndef NDEBUG
428c46e6a59SDimitry Andric   for (const InstructionMapping *Mapping : PossibleMappings)
429c46e6a59SDimitry Andric     assert(Mapping->verify(MI) && "Mapping is invalid");
43001095a5dSDimitry Andric #endif
43101095a5dSDimitry Andric   return PossibleMappings;
43201095a5dSDimitry Andric }
43301095a5dSDimitry Andric 
43401095a5dSDimitry Andric RegisterBankInfo::InstructionMappings
getInstrAlternativeMappings(const MachineInstr & MI) const43501095a5dSDimitry Andric RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
43601095a5dSDimitry Andric   // No alternative for MI.
43701095a5dSDimitry Andric   return InstructionMappings();
43801095a5dSDimitry Andric }
43901095a5dSDimitry Andric 
applyDefaultMapping(const OperandsMapper & OpdMapper)44001095a5dSDimitry Andric void RegisterBankInfo::applyDefaultMapping(const OperandsMapper &OpdMapper) {
44101095a5dSDimitry Andric   MachineInstr &MI = OpdMapper.getMI();
44271d5a254SDimitry Andric   MachineRegisterInfo &MRI = OpdMapper.getMRI();
443eb11fae6SDimitry Andric   LLVM_DEBUG(dbgs() << "Applying default-like mapping\n");
444b915e9e0SDimitry Andric   for (unsigned OpIdx = 0,
445b915e9e0SDimitry Andric                 EndIdx = OpdMapper.getInstrMapping().getNumOperands();
446b915e9e0SDimitry Andric        OpIdx != EndIdx; ++OpIdx) {
447eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << "OpIdx " << OpIdx);
44801095a5dSDimitry Andric     MachineOperand &MO = MI.getOperand(OpIdx);
44901095a5dSDimitry Andric     if (!MO.isReg()) {
450eb11fae6SDimitry Andric       LLVM_DEBUG(dbgs() << " is not a register, nothing to be done\n");
45101095a5dSDimitry Andric       continue;
45201095a5dSDimitry Andric     }
45371d5a254SDimitry Andric     if (!MO.getReg()) {
454706b4fc4SDimitry Andric       LLVM_DEBUG(dbgs() << " is $noreg, nothing to be done\n");
45571d5a254SDimitry Andric       continue;
45671d5a254SDimitry Andric     }
457e3b55780SDimitry Andric     LLT Ty = MRI.getType(MO.getReg());
458e3b55780SDimitry Andric     if (!Ty.isValid())
459e3b55780SDimitry Andric       continue;
46071d5a254SDimitry Andric     assert(OpdMapper.getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns !=
46171d5a254SDimitry Andric                0 &&
46271d5a254SDimitry Andric            "Invalid mapping");
463b915e9e0SDimitry Andric     assert(OpdMapper.getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns ==
46401095a5dSDimitry Andric                1 &&
46501095a5dSDimitry Andric            "This mapping is too complex for this function");
466e6d15924SDimitry Andric     iterator_range<SmallVectorImpl<Register>::const_iterator> NewRegs =
46701095a5dSDimitry Andric         OpdMapper.getVRegs(OpIdx);
4681d5ae102SDimitry Andric     if (NewRegs.empty()) {
469eb11fae6SDimitry Andric       LLVM_DEBUG(dbgs() << " has not been repaired, nothing to be done\n");
47001095a5dSDimitry Andric       continue;
47101095a5dSDimitry Andric     }
472e6d15924SDimitry Andric     Register OrigReg = MO.getReg();
473e6d15924SDimitry Andric     Register NewReg = *NewRegs.begin();
474eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << " changed, replace " << printReg(OrigReg, nullptr));
47571d5a254SDimitry Andric     MO.setReg(NewReg);
476eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << " with " << printReg(NewReg, nullptr));
47771d5a254SDimitry Andric 
47871d5a254SDimitry Andric     // The OperandsMapper creates plain scalar, we may have to fix that.
47971d5a254SDimitry Andric     // Check if the types match and if not, fix that.
48071d5a254SDimitry Andric     LLT OrigTy = MRI.getType(OrigReg);
48171d5a254SDimitry Andric     LLT NewTy = MRI.getType(NewReg);
48271d5a254SDimitry Andric     if (OrigTy != NewTy) {
483044eb2f6SDimitry Andric       // The default mapping is not supposed to change the size of
484044eb2f6SDimitry Andric       // the storage. However, right now we don't necessarily bump all
485044eb2f6SDimitry Andric       // the types to storage size. For instance, we can consider
486044eb2f6SDimitry Andric       // s16 G_AND legal whereas the storage size is going to be 32.
487ac9a064cSDimitry Andric       assert(
488ac9a064cSDimitry Andric           TypeSize::isKnownLE(OrigTy.getSizeInBits(), NewTy.getSizeInBits()) &&
48971d5a254SDimitry Andric           "Types with difference size cannot be handled by the default "
49071d5a254SDimitry Andric           "mapping");
491eb11fae6SDimitry Andric       LLVM_DEBUG(dbgs() << "\nChange type of new opd from " << NewTy << " to "
49271d5a254SDimitry Andric                         << OrigTy);
49371d5a254SDimitry Andric       MRI.setType(NewReg, OrigTy);
49471d5a254SDimitry Andric     }
495eb11fae6SDimitry Andric     LLVM_DEBUG(dbgs() << '\n');
49601095a5dSDimitry Andric   }
49701095a5dSDimitry Andric }
49801095a5dSDimitry Andric 
getSizeInBits(Register Reg,const MachineRegisterInfo & MRI,const TargetRegisterInfo & TRI) const499b1c73532SDimitry Andric TypeSize RegisterBankInfo::getSizeInBits(Register Reg,
50001095a5dSDimitry Andric                                          const MachineRegisterInfo &MRI,
501044eb2f6SDimitry Andric                                          const TargetRegisterInfo &TRI) const {
502e3b55780SDimitry Andric   if (Reg.isPhysical()) {
50301095a5dSDimitry Andric     // The size is not directly available for physical registers.
50401095a5dSDimitry Andric     // Instead, we need to access a register class that contains Reg and
50501095a5dSDimitry Andric     // get the size of that register class.
506eb11fae6SDimitry Andric     // Because this is expensive, we'll cache the register class by calling
5077fa27ce4SDimitry Andric     auto *RC = getMinimalPhysRegClass(Reg, TRI);
508eb11fae6SDimitry Andric     assert(RC && "Expecting Register class");
50912f3ca4cSDimitry Andric     return TRI.getRegSizeInBits(*RC);
51001095a5dSDimitry Andric   }
511eb11fae6SDimitry Andric   return TRI.getRegSizeInBits(Reg, MRI);
512eb11fae6SDimitry Andric }
51301095a5dSDimitry Andric 
51401095a5dSDimitry Andric //------------------------------------------------------------------------------
51501095a5dSDimitry Andric // Helper classes implementation.
51601095a5dSDimitry Andric //------------------------------------------------------------------------------
51771d5a254SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const518b915e9e0SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::PartialMapping::dump() const {
51901095a5dSDimitry Andric   print(dbgs());
52001095a5dSDimitry Andric   dbgs() << '\n';
52101095a5dSDimitry Andric }
52271d5a254SDimitry Andric #endif
52301095a5dSDimitry Andric 
verify(const RegisterBankInfo & RBI) const5247fa27ce4SDimitry Andric bool RegisterBankInfo::PartialMapping::verify(
5257fa27ce4SDimitry Andric     const RegisterBankInfo &RBI) const {
52601095a5dSDimitry Andric   assert(RegBank && "Register bank not set");
52701095a5dSDimitry Andric   assert(Length && "Empty mapping");
528b915e9e0SDimitry Andric   assert((StartIdx <= getHighBitIdx()) && "Overflow, switch to APInt?");
52901095a5dSDimitry Andric   // Check if the minimum width fits into RegBank.
5307fa27ce4SDimitry Andric   assert(RBI.getMaximumSize(RegBank->getID()) >= Length &&
5317fa27ce4SDimitry Andric          "Register bank too small for Mask");
53201095a5dSDimitry Andric   return true;
53301095a5dSDimitry Andric }
53401095a5dSDimitry Andric 
print(raw_ostream & OS) const53501095a5dSDimitry Andric void RegisterBankInfo::PartialMapping::print(raw_ostream &OS) const {
53601095a5dSDimitry Andric   OS << "[" << StartIdx << ", " << getHighBitIdx() << "], RegBank = ";
53701095a5dSDimitry Andric   if (RegBank)
53801095a5dSDimitry Andric     OS << *RegBank;
53901095a5dSDimitry Andric   else
54001095a5dSDimitry Andric     OS << "nullptr";
54101095a5dSDimitry Andric }
54201095a5dSDimitry Andric 
partsAllUniform() const543e6d15924SDimitry Andric bool RegisterBankInfo::ValueMapping::partsAllUniform() const {
544e6d15924SDimitry Andric   if (NumBreakDowns < 2)
545e6d15924SDimitry Andric     return true;
546e6d15924SDimitry Andric 
547e6d15924SDimitry Andric   const PartialMapping *First = begin();
548e6d15924SDimitry Andric   for (const PartialMapping *Part = First + 1; Part != end(); ++Part) {
549e6d15924SDimitry Andric     if (Part->Length != First->Length || Part->RegBank != First->RegBank)
550e6d15924SDimitry Andric       return false;
551e6d15924SDimitry Andric   }
552e6d15924SDimitry Andric 
553e6d15924SDimitry Andric   return true;
554e6d15924SDimitry Andric }
555e6d15924SDimitry Andric 
verify(const RegisterBankInfo & RBI,TypeSize MeaningfulBitWidth) const5567fa27ce4SDimitry Andric bool RegisterBankInfo::ValueMapping::verify(const RegisterBankInfo &RBI,
557b1c73532SDimitry Andric                                             TypeSize MeaningfulBitWidth) const {
558b915e9e0SDimitry Andric   assert(NumBreakDowns && "Value mapped nowhere?!");
55901095a5dSDimitry Andric   unsigned OrigValueBitWidth = 0;
560b915e9e0SDimitry Andric   for (const RegisterBankInfo::PartialMapping &PartMap : *this) {
56101095a5dSDimitry Andric     // Check that each register bank is big enough to hold the partial value:
56201095a5dSDimitry Andric     // this check is done by PartialMapping::verify
5637fa27ce4SDimitry Andric     assert(PartMap.verify(RBI) && "Partial mapping is invalid");
56401095a5dSDimitry Andric     // The original value should completely be mapped.
56501095a5dSDimitry Andric     // Thus the maximum accessed index + 1 is the size of the original value.
56601095a5dSDimitry Andric     OrigValueBitWidth =
56701095a5dSDimitry Andric         std::max(OrigValueBitWidth, PartMap.getHighBitIdx() + 1);
56801095a5dSDimitry Andric   }
569b1c73532SDimitry Andric   assert((MeaningfulBitWidth.isScalable() ||
570b1c73532SDimitry Andric           OrigValueBitWidth >= MeaningfulBitWidth) &&
571b915e9e0SDimitry Andric          "Meaningful bits not covered by the mapping");
57201095a5dSDimitry Andric   APInt ValueMask(OrigValueBitWidth, 0);
573b915e9e0SDimitry Andric   for (const RegisterBankInfo::PartialMapping &PartMap : *this) {
57401095a5dSDimitry Andric     // Check that the union of the partial mappings covers the whole value,
57501095a5dSDimitry Andric     // without overlaps.
57601095a5dSDimitry Andric     // The high bit is exclusive in the APInt API, thus getHighBitIdx + 1.
57701095a5dSDimitry Andric     APInt PartMapMask = APInt::getBitsSet(OrigValueBitWidth, PartMap.StartIdx,
57801095a5dSDimitry Andric                                           PartMap.getHighBitIdx() + 1);
57901095a5dSDimitry Andric     ValueMask ^= PartMapMask;
58001095a5dSDimitry Andric     assert((ValueMask & PartMapMask) == PartMapMask &&
58101095a5dSDimitry Andric            "Some partial mappings overlap");
58201095a5dSDimitry Andric   }
583c0981da4SDimitry Andric   assert(ValueMask.isAllOnes() && "Value is not fully mapped");
58401095a5dSDimitry Andric   return true;
58501095a5dSDimitry Andric }
58601095a5dSDimitry Andric 
58771d5a254SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const588b915e9e0SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::ValueMapping::dump() const {
58901095a5dSDimitry Andric   print(dbgs());
59001095a5dSDimitry Andric   dbgs() << '\n';
59101095a5dSDimitry Andric }
59271d5a254SDimitry Andric #endif
59301095a5dSDimitry Andric 
print(raw_ostream & OS) const59401095a5dSDimitry Andric void RegisterBankInfo::ValueMapping::print(raw_ostream &OS) const {
595b915e9e0SDimitry Andric   OS << "#BreakDown: " << NumBreakDowns << " ";
59601095a5dSDimitry Andric   bool IsFirst = true;
597b915e9e0SDimitry Andric   for (const PartialMapping &PartMap : *this) {
59801095a5dSDimitry Andric     if (!IsFirst)
59901095a5dSDimitry Andric       OS << ", ";
60001095a5dSDimitry Andric     OS << '[' << PartMap << ']';
60101095a5dSDimitry Andric     IsFirst = false;
60201095a5dSDimitry Andric   }
60301095a5dSDimitry Andric }
60401095a5dSDimitry Andric 
verify(const MachineInstr & MI) const60501095a5dSDimitry Andric bool RegisterBankInfo::InstructionMapping::verify(
60601095a5dSDimitry Andric     const MachineInstr &MI) const {
60701095a5dSDimitry Andric   // Check that all the register operands are properly mapped.
60801095a5dSDimitry Andric   // Check the constructor invariant.
609b915e9e0SDimitry Andric   // For PHI, we only care about mapping the definition.
61071d5a254SDimitry Andric   assert(NumOperands == (isCopyLike(MI) ? 1 : MI.getNumOperands()) &&
61101095a5dSDimitry Andric          "NumOperands must match, see constructor");
612044eb2f6SDimitry Andric   assert(MI.getParent() && MI.getMF() &&
61301095a5dSDimitry Andric          "MI must be connected to a MachineFunction");
614044eb2f6SDimitry Andric   const MachineFunction &MF = *MI.getMF();
615044eb2f6SDimitry Andric   const RegisterBankInfo *RBI = MF.getSubtarget().getRegBankInfo();
616044eb2f6SDimitry Andric   (void)RBI;
617e3b55780SDimitry Andric   const MachineRegisterInfo &MRI = MF.getRegInfo();
61801095a5dSDimitry Andric 
61901095a5dSDimitry Andric   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
62001095a5dSDimitry Andric     const MachineOperand &MO = MI.getOperand(Idx);
62101095a5dSDimitry Andric     if (!MO.isReg()) {
622b915e9e0SDimitry Andric       assert(!getOperandMapping(Idx).isValid() &&
62301095a5dSDimitry Andric              "We should not care about non-reg mapping");
62401095a5dSDimitry Andric       continue;
62501095a5dSDimitry Andric     }
626e6d15924SDimitry Andric     Register Reg = MO.getReg();
62701095a5dSDimitry Andric     if (!Reg)
62801095a5dSDimitry Andric       continue;
629e3b55780SDimitry Andric     LLT Ty = MRI.getType(Reg);
630e3b55780SDimitry Andric     if (!Ty.isValid())
631e3b55780SDimitry Andric       continue;
632b915e9e0SDimitry Andric     assert(getOperandMapping(Idx).isValid() &&
633b915e9e0SDimitry Andric            "We must have a mapping for reg operands");
634b915e9e0SDimitry Andric     const RegisterBankInfo::ValueMapping &MOMapping = getOperandMapping(Idx);
635b915e9e0SDimitry Andric     (void)MOMapping;
63601095a5dSDimitry Andric     // Register size in bits.
63701095a5dSDimitry Andric     // This size must match what the mapping expects.
6387fa27ce4SDimitry Andric     assert(MOMapping.verify(*RBI, RBI->getSizeInBits(
6397fa27ce4SDimitry Andric                                       Reg, MF.getRegInfo(),
6407fa27ce4SDimitry Andric                                       *MF.getSubtarget().getRegisterInfo())) &&
64101095a5dSDimitry Andric            "Value mapping is invalid");
64201095a5dSDimitry Andric   }
64301095a5dSDimitry Andric   return true;
64401095a5dSDimitry Andric }
64501095a5dSDimitry Andric 
64671d5a254SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const647b915e9e0SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::InstructionMapping::dump() const {
64801095a5dSDimitry Andric   print(dbgs());
64901095a5dSDimitry Andric   dbgs() << '\n';
65001095a5dSDimitry Andric }
65171d5a254SDimitry Andric #endif
65201095a5dSDimitry Andric 
print(raw_ostream & OS) const65301095a5dSDimitry Andric void RegisterBankInfo::InstructionMapping::print(raw_ostream &OS) const {
65401095a5dSDimitry Andric   OS << "ID: " << getID() << " Cost: " << getCost() << " Mapping: ";
65501095a5dSDimitry Andric 
65601095a5dSDimitry Andric   for (unsigned OpIdx = 0; OpIdx != NumOperands; ++OpIdx) {
65701095a5dSDimitry Andric     const ValueMapping &ValMapping = getOperandMapping(OpIdx);
65801095a5dSDimitry Andric     if (OpIdx)
65901095a5dSDimitry Andric       OS << ", ";
66001095a5dSDimitry Andric     OS << "{ Idx: " << OpIdx << " Map: " << ValMapping << '}';
66101095a5dSDimitry Andric   }
66201095a5dSDimitry Andric }
66301095a5dSDimitry Andric 
66401095a5dSDimitry Andric const int RegisterBankInfo::OperandsMapper::DontKnowIdx = -1;
66501095a5dSDimitry Andric 
OperandsMapper(MachineInstr & MI,const InstructionMapping & InstrMapping,MachineRegisterInfo & MRI)66601095a5dSDimitry Andric RegisterBankInfo::OperandsMapper::OperandsMapper(
66701095a5dSDimitry Andric     MachineInstr &MI, const InstructionMapping &InstrMapping,
66801095a5dSDimitry Andric     MachineRegisterInfo &MRI)
66901095a5dSDimitry Andric     : MRI(MRI), MI(MI), InstrMapping(InstrMapping) {
670b915e9e0SDimitry Andric   unsigned NumOpds = InstrMapping.getNumOperands();
671b915e9e0SDimitry Andric   OpToNewVRegIdx.resize(NumOpds, OperandsMapper::DontKnowIdx);
67201095a5dSDimitry Andric   assert(InstrMapping.verify(MI) && "Invalid mapping for MI");
67301095a5dSDimitry Andric }
67401095a5dSDimitry Andric 
675e6d15924SDimitry Andric iterator_range<SmallVectorImpl<Register>::iterator>
getVRegsMem(unsigned OpIdx)67601095a5dSDimitry Andric RegisterBankInfo::OperandsMapper::getVRegsMem(unsigned OpIdx) {
677b915e9e0SDimitry Andric   assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access");
67801095a5dSDimitry Andric   unsigned NumPartialVal =
679b915e9e0SDimitry Andric       getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns;
68001095a5dSDimitry Andric   int StartIdx = OpToNewVRegIdx[OpIdx];
68101095a5dSDimitry Andric 
68201095a5dSDimitry Andric   if (StartIdx == OperandsMapper::DontKnowIdx) {
68301095a5dSDimitry Andric     // This is the first time we try to access OpIdx.
68401095a5dSDimitry Andric     // Create the cells that will hold all the partial values at the
68501095a5dSDimitry Andric     // end of the list of NewVReg.
68601095a5dSDimitry Andric     StartIdx = NewVRegs.size();
68701095a5dSDimitry Andric     OpToNewVRegIdx[OpIdx] = StartIdx;
68801095a5dSDimitry Andric     for (unsigned i = 0; i < NumPartialVal; ++i)
68901095a5dSDimitry Andric       NewVRegs.push_back(0);
69001095a5dSDimitry Andric   }
691e6d15924SDimitry Andric   SmallVectorImpl<Register>::iterator End =
69201095a5dSDimitry Andric       getNewVRegsEnd(StartIdx, NumPartialVal);
69301095a5dSDimitry Andric 
69401095a5dSDimitry Andric   return make_range(&NewVRegs[StartIdx], End);
69501095a5dSDimitry Andric }
69601095a5dSDimitry Andric 
697e6d15924SDimitry Andric SmallVectorImpl<Register>::const_iterator
getNewVRegsEnd(unsigned StartIdx,unsigned NumVal) const69801095a5dSDimitry Andric RegisterBankInfo::OperandsMapper::getNewVRegsEnd(unsigned StartIdx,
69901095a5dSDimitry Andric                                                  unsigned NumVal) const {
70001095a5dSDimitry Andric   return const_cast<OperandsMapper *>(this)->getNewVRegsEnd(StartIdx, NumVal);
70101095a5dSDimitry Andric }
702e6d15924SDimitry Andric SmallVectorImpl<Register>::iterator
getNewVRegsEnd(unsigned StartIdx,unsigned NumVal)70301095a5dSDimitry Andric RegisterBankInfo::OperandsMapper::getNewVRegsEnd(unsigned StartIdx,
70401095a5dSDimitry Andric                                                  unsigned NumVal) {
70501095a5dSDimitry Andric   assert((NewVRegs.size() == StartIdx + NumVal ||
70601095a5dSDimitry Andric           NewVRegs.size() > StartIdx + NumVal) &&
70701095a5dSDimitry Andric          "NewVRegs too small to contain all the partial mapping");
70801095a5dSDimitry Andric   return NewVRegs.size() <= StartIdx + NumVal ? NewVRegs.end()
70901095a5dSDimitry Andric                                               : &NewVRegs[StartIdx + NumVal];
71001095a5dSDimitry Andric }
71101095a5dSDimitry Andric 
createVRegs(unsigned OpIdx)71201095a5dSDimitry Andric void RegisterBankInfo::OperandsMapper::createVRegs(unsigned OpIdx) {
713b915e9e0SDimitry Andric   assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access");
714e6d15924SDimitry Andric   iterator_range<SmallVectorImpl<Register>::iterator> NewVRegsForOpIdx =
71501095a5dSDimitry Andric       getVRegsMem(OpIdx);
716b915e9e0SDimitry Andric   const ValueMapping &ValMapping = getInstrMapping().getOperandMapping(OpIdx);
717b915e9e0SDimitry Andric   const PartialMapping *PartMap = ValMapping.begin();
718e6d15924SDimitry Andric   for (Register &NewVReg : NewVRegsForOpIdx) {
719b915e9e0SDimitry Andric     assert(PartMap != ValMapping.end() && "Out-of-bound access");
72001095a5dSDimitry Andric     assert(NewVReg == 0 && "Register has already been created");
72171d5a254SDimitry Andric     // The new registers are always bound to scalar with the right size.
72271d5a254SDimitry Andric     // The actual type has to be set when the target does the mapping
72371d5a254SDimitry Andric     // of the instruction.
72471d5a254SDimitry Andric     // The rationale is that this generic code cannot guess how the
72571d5a254SDimitry Andric     // target plans to split the input type.
726b915e9e0SDimitry Andric     NewVReg = MRI.createGenericVirtualRegister(LLT::scalar(PartMap->Length));
72701095a5dSDimitry Andric     MRI.setRegBank(NewVReg, *PartMap->RegBank);
72801095a5dSDimitry Andric     ++PartMap;
72901095a5dSDimitry Andric   }
73001095a5dSDimitry Andric }
73101095a5dSDimitry Andric 
setVRegs(unsigned OpIdx,unsigned PartialMapIdx,Register NewVReg)73201095a5dSDimitry Andric void RegisterBankInfo::OperandsMapper::setVRegs(unsigned OpIdx,
73301095a5dSDimitry Andric                                                 unsigned PartialMapIdx,
734e6d15924SDimitry Andric                                                 Register NewVReg) {
735b915e9e0SDimitry Andric   assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access");
736b915e9e0SDimitry Andric   assert(getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns >
73701095a5dSDimitry Andric              PartialMapIdx &&
73801095a5dSDimitry Andric          "Out-of-bound access for partial mapping");
73901095a5dSDimitry Andric   // Make sure the memory is initialized for that operand.
74001095a5dSDimitry Andric   (void)getVRegsMem(OpIdx);
74101095a5dSDimitry Andric   assert(NewVRegs[OpToNewVRegIdx[OpIdx] + PartialMapIdx] == 0 &&
74201095a5dSDimitry Andric          "This value is already set");
74301095a5dSDimitry Andric   NewVRegs[OpToNewVRegIdx[OpIdx] + PartialMapIdx] = NewVReg;
74401095a5dSDimitry Andric }
74501095a5dSDimitry Andric 
746e6d15924SDimitry Andric iterator_range<SmallVectorImpl<Register>::const_iterator>
getVRegs(unsigned OpIdx,bool ForDebug) const74701095a5dSDimitry Andric RegisterBankInfo::OperandsMapper::getVRegs(unsigned OpIdx,
74801095a5dSDimitry Andric                                            bool ForDebug) const {
74901095a5dSDimitry Andric   (void)ForDebug;
750b915e9e0SDimitry Andric   assert(OpIdx < getInstrMapping().getNumOperands() && "Out-of-bound access");
75101095a5dSDimitry Andric   int StartIdx = OpToNewVRegIdx[OpIdx];
75201095a5dSDimitry Andric 
75301095a5dSDimitry Andric   if (StartIdx == OperandsMapper::DontKnowIdx)
75401095a5dSDimitry Andric     return make_range(NewVRegs.end(), NewVRegs.end());
75501095a5dSDimitry Andric 
75601095a5dSDimitry Andric   unsigned PartMapSize =
757b915e9e0SDimitry Andric       getInstrMapping().getOperandMapping(OpIdx).NumBreakDowns;
758e6d15924SDimitry Andric   SmallVectorImpl<Register>::const_iterator End =
75901095a5dSDimitry Andric       getNewVRegsEnd(StartIdx, PartMapSize);
760e6d15924SDimitry Andric   iterator_range<SmallVectorImpl<Register>::const_iterator> Res =
76101095a5dSDimitry Andric       make_range(&NewVRegs[StartIdx], End);
76201095a5dSDimitry Andric #ifndef NDEBUG
763e6d15924SDimitry Andric   for (Register VReg : Res)
76401095a5dSDimitry Andric     assert((VReg || ForDebug) && "Some registers are uninitialized");
76501095a5dSDimitry Andric #endif
76601095a5dSDimitry Andric   return Res;
76701095a5dSDimitry Andric }
76801095a5dSDimitry Andric 
76971d5a254SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const770b915e9e0SDimitry Andric LLVM_DUMP_METHOD void RegisterBankInfo::OperandsMapper::dump() const {
77101095a5dSDimitry Andric   print(dbgs(), true);
77201095a5dSDimitry Andric   dbgs() << '\n';
77301095a5dSDimitry Andric }
77471d5a254SDimitry Andric #endif
77501095a5dSDimitry Andric 
print(raw_ostream & OS,bool ForDebug) const77601095a5dSDimitry Andric void RegisterBankInfo::OperandsMapper::print(raw_ostream &OS,
77701095a5dSDimitry Andric                                              bool ForDebug) const {
778b915e9e0SDimitry Andric   unsigned NumOpds = getInstrMapping().getNumOperands();
77901095a5dSDimitry Andric   if (ForDebug) {
78001095a5dSDimitry Andric     OS << "Mapping for " << getMI() << "\nwith " << getInstrMapping() << '\n';
78101095a5dSDimitry Andric     // Print out the internal state of the index table.
78201095a5dSDimitry Andric     OS << "Populated indices (CellNumber, IndexInNewVRegs): ";
78301095a5dSDimitry Andric     bool IsFirst = true;
78401095a5dSDimitry Andric     for (unsigned Idx = 0; Idx != NumOpds; ++Idx) {
78501095a5dSDimitry Andric       if (OpToNewVRegIdx[Idx] != DontKnowIdx) {
78601095a5dSDimitry Andric         if (!IsFirst)
78701095a5dSDimitry Andric           OS << ", ";
78801095a5dSDimitry Andric         OS << '(' << Idx << ", " << OpToNewVRegIdx[Idx] << ')';
78901095a5dSDimitry Andric         IsFirst = false;
79001095a5dSDimitry Andric       }
79101095a5dSDimitry Andric     }
79201095a5dSDimitry Andric     OS << '\n';
79301095a5dSDimitry Andric   } else
79401095a5dSDimitry Andric     OS << "Mapping ID: " << getInstrMapping().getID() << ' ';
79501095a5dSDimitry Andric 
79601095a5dSDimitry Andric   OS << "Operand Mapping: ";
79701095a5dSDimitry Andric   // If we have a function, we can pretty print the name of the registers.
79801095a5dSDimitry Andric   // Otherwise we will print the raw numbers.
79901095a5dSDimitry Andric   const TargetRegisterInfo *TRI =
800044eb2f6SDimitry Andric       getMI().getParent() && getMI().getMF()
801044eb2f6SDimitry Andric           ? getMI().getMF()->getSubtarget().getRegisterInfo()
80201095a5dSDimitry Andric           : nullptr;
80301095a5dSDimitry Andric   bool IsFirst = true;
80401095a5dSDimitry Andric   for (unsigned Idx = 0; Idx != NumOpds; ++Idx) {
80501095a5dSDimitry Andric     if (OpToNewVRegIdx[Idx] == DontKnowIdx)
80601095a5dSDimitry Andric       continue;
80701095a5dSDimitry Andric     if (!IsFirst)
80801095a5dSDimitry Andric       OS << ", ";
80901095a5dSDimitry Andric     IsFirst = false;
810044eb2f6SDimitry Andric     OS << '(' << printReg(getMI().getOperand(Idx).getReg(), TRI) << ", [";
81101095a5dSDimitry Andric     bool IsFirstNewVReg = true;
812e6d15924SDimitry Andric     for (Register VReg : getVRegs(Idx)) {
81301095a5dSDimitry Andric       if (!IsFirstNewVReg)
81401095a5dSDimitry Andric         OS << ", ";
81501095a5dSDimitry Andric       IsFirstNewVReg = false;
816044eb2f6SDimitry Andric       OS << printReg(VReg, TRI);
81701095a5dSDimitry Andric     }
81801095a5dSDimitry Andric     OS << "])";
81901095a5dSDimitry Andric   }
82001095a5dSDimitry Andric }
821