1 //===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 /// This file declares the targeting of the RegisterBankInfo class for Mips.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
14 #define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
16 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #define GET_REGBANK_DECLARATIONS
19 #include "MipsGenRegisterBank.inc"
23 class TargetRegisterInfo
;
25 class MipsGenRegisterBankInfo
: public RegisterBankInfo
{
26 #define GET_TARGET_REGBANK_CLASS
27 #include "MipsGenRegisterBank.inc"
30 /// This class provides the information for the target register banks.
31 class MipsRegisterBankInfo final
: public MipsGenRegisterBankInfo
{
33 MipsRegisterBankInfo(const TargetRegisterInfo
&TRI
);
36 getRegBankFromRegClass(const TargetRegisterClass
&RC
) const override
;
38 const InstructionMapping
&
39 getInstrMapping(const MachineInstr
&MI
) const override
;
41 /// Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or
42 /// G_UNMERGE and erase instructions that became dead in the process. We
43 /// manually assign bank to def operand of all new instructions that were
44 /// created in the process since they will not end up in RegBankSelect loop.
45 void applyMappingImpl(const OperandsMapper
&OpdMapper
) const override
;
47 /// RegBankSelect determined that s64 operand is better to be split into two
48 /// s32 operands in gprb. Here we manually set register banks of def operands
49 /// of newly created instructions since they will not get regbankselected.
50 void setRegBank(MachineInstr
&MI
, MachineRegisterInfo
&MRI
) const;
53 /// Some instructions are used with both floating point and integer operands.
54 /// We assign InstType to such instructions as it helps us to avoid cross bank
55 /// copies. InstType deppends on context.
57 /// Temporary type, when visit(..., nullptr) finishes will convert to one of
58 /// the remaining types: Integer, FloatingPoint or Ambiguous.
60 /// Connected with instruction that interprets 'bags of bits' as integers.
61 /// Select gprb to avoid cross bank copies.
63 /// Connected with instruction that interprets 'bags of bits' as floating
64 /// point numbers. Select fprb to avoid cross bank copies.
66 /// Represents moving 'bags of bits' around. Select same bank for entire
67 /// chain to avoid cross bank copies. Currently we select fprb for s64 and
68 /// gprb for s32 Ambiguous operands.
72 /// Some generic instructions have operands that can be mapped to either fprb
73 /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1
74 /// is always gprb since it is a pointer.
75 /// This class provides containers for MI's ambiguous:
76 /// DefUses : MachineInstrs that use one of MI's ambiguous def operands.
77 /// UseDefs : MachineInstrs that define MI's ambiguous use operands.
78 class AmbiguousRegDefUseContainer
{
79 SmallVector
<MachineInstr
*, 2> DefUses
;
80 SmallVector
<MachineInstr
*, 2> UseDefs
;
82 void addDefUses(Register Reg
, const MachineRegisterInfo
&MRI
);
83 void addUseDef(Register Reg
, const MachineRegisterInfo
&MRI
);
85 /// Skip copy instructions until we get to a non-copy instruction or to a
86 /// copy with phys register as def. Used during search for DefUses.
89 /// $v0 = COPY %6 <- we want this one.
90 MachineInstr
*skipCopiesOutgoing(MachineInstr
*MI
) const;
92 /// Skip copy instructions until we get to a non-copy instruction or to a
93 /// copy with phys register as use. Used during search for UseDefs.
94 /// %1 = COPY $a1 <- we want this one.
97 MachineInstr
*skipCopiesIncoming(MachineInstr
*MI
) const;
100 AmbiguousRegDefUseContainer(const MachineInstr
*MI
);
101 SmallVectorImpl
<MachineInstr
*> &getDefUses() { return DefUses
; }
102 SmallVectorImpl
<MachineInstr
*> &getUseDefs() { return UseDefs
; }
105 class TypeInfoForMF
{
106 /// MachineFunction name is used to recognise when MF changes.
107 std::string MFName
= "";
108 /// <key, value> : value is vector of all MachineInstrs that are waiting for
109 /// key to figure out type of some of its ambiguous operands.
110 DenseMap
<const MachineInstr
*, SmallVector
<const MachineInstr
*, 2>>
112 /// Recorded InstTypes for visited instructions.
113 DenseMap
<const MachineInstr
*, InstType
> Types
;
115 /// Recursively visit MI's adjacent instructions and find MI's InstType.
116 bool visit(const MachineInstr
*MI
, const MachineInstr
*WaitingForTypeOfMI
);
118 /// Visit MI's adjacent UseDefs or DefUses.
119 bool visitAdjacentInstrs(const MachineInstr
*MI
,
120 SmallVectorImpl
<MachineInstr
*> &AdjacentInstrs
,
123 /// Set type for MI, and recursively for all instructions that are
124 /// waiting for MI's type.
125 void setTypes(const MachineInstr
*MI
, InstType ITy
);
127 /// InstType for MI is determined, set it to InstType that corresponds to
128 /// physical regisiter that is operand number Op in CopyInst.
129 void setTypesAccordingToPhysicalRegister(const MachineInstr
*MI
,
130 const MachineInstr
*CopyInst
,
133 /// Set default values for MI in order to start visit.
134 void startVisit(const MachineInstr
*MI
) {
135 Types
.try_emplace(MI
, InstType::NotDetermined
);
136 WaitingQueues
.try_emplace(MI
);
139 /// Returns true if instruction was already visited. Type might not be
140 /// determined at this point but will be when visit(..., nullptr) finishes.
141 bool wasVisited(const MachineInstr
*MI
) const { return Types
.count(MI
); };
143 /// Returns recorded type for instruction.
144 const InstType
&getRecordedTypeForInstr(const MachineInstr
*MI
) const {
145 assert(wasVisited(MI
) && "Instruction was not visited!");
146 return Types
.find(MI
)->getSecond();
149 /// Change recorded type for instruction.
150 void changeRecordedTypeForInstr(const MachineInstr
*MI
, InstType InstTy
) {
151 assert(wasVisited(MI
) && "Instruction was not visited!");
152 Types
.find(MI
)->getSecond() = InstTy
;
155 /// Returns WaitingQueue for instruction.
156 const SmallVectorImpl
<const MachineInstr
*> &
157 getWaitingQueueFor(const MachineInstr
*MI
) const {
158 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
159 return WaitingQueues
.find(MI
)->getSecond();
162 /// Add WaitingForMI to MI's WaitingQueue.
163 void addToWaitingQueue(const MachineInstr
*MI
,
164 const MachineInstr
*WaitingForMI
) {
165 assert(WaitingQueues
.count(MI
) && "Instruction was not visited!");
166 WaitingQueues
.find(MI
)->getSecond().push_back(WaitingForMI
);
170 InstType
determineInstType(const MachineInstr
*MI
);
172 void cleanupIfNewFunction(llvm::StringRef FunctionName
);
175 } // end namespace llvm