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