MipsRegisterBankInfo.h revision 360784
1//===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file declares the targeting of the RegisterBankInfo class for Mips.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
14#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H
15
16#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
17
18#define GET_REGBANK_DECLARATIONS
19#include "MipsGenRegisterBank.inc"
20
21namespace llvm {
22
23class TargetRegisterInfo;
24
25class MipsGenRegisterBankInfo : public RegisterBankInfo {
26#define GET_TARGET_REGBANK_CLASS
27#include "MipsGenRegisterBank.inc"
28};
29
30/// This class provides the information for the target register banks.
31class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo {
32public:
33  MipsRegisterBankInfo(const TargetRegisterInfo &TRI);
34
35  const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC,
36                                             LLT) const override;
37
38  const InstructionMapping &
39  getInstrMapping(const MachineInstr &MI) const override;
40
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;
46
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;
51
52private:
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.
56  enum InstType {
57    /// Temporary type, when visit(..., nullptr) finishes will convert to one of
58    /// the remaining types: Integer, FloatingPoint or Ambiguous.
59    NotDetermined,
60    /// Connected with instruction that interprets 'bags of bits' as integers.
61    /// Select gprb to avoid cross bank copies.
62    Integer,
63    /// Connected with instruction that interprets 'bags of bits' as floating
64    /// point numbers. Select fprb to avoid cross bank copies.
65    FloatingPoint,
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.
69    Ambiguous
70  };
71
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;
81
82    void addDefUses(Register Reg, const MachineRegisterInfo &MRI);
83    void addUseDef(Register Reg, const MachineRegisterInfo &MRI);
84
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.
87    /// MI :  %5 = COPY %4
88    ///       %6 = COPY %5
89    ///       $v0 = COPY %6 <- we want this one.
90    MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const;
91
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.
95    ///       %2 = COPY %1
96    /// MI =  %3 = COPY %2
97    MachineInstr *skipCopiesIncoming(MachineInstr *MI) const;
98
99  public:
100    AmbiguousRegDefUseContainer(const MachineInstr *MI);
101    SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; }
102    SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; }
103  };
104
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>>
111        WaitingQueues;
112    /// Recorded InstTypes for visited instructions.
113    DenseMap<const MachineInstr *, InstType> Types;
114
115    /// Recursively visit MI's adjacent instructions and find MI's InstType.
116    bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI);
117
118    /// Visit MI's adjacent UseDefs or DefUses.
119    bool visitAdjacentInstrs(const MachineInstr *MI,
120                             SmallVectorImpl<MachineInstr *> &AdjacentInstrs,
121                             bool isDefUse);
122
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);
126
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,
131                                             unsigned Op);
132
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);
137    }
138
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); };
142
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();
147    };
148
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;
153    };
154
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();
160    };
161
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);
167    };
168
169  public:
170    InstType determineInstType(const MachineInstr *MI);
171
172    void cleanupIfNewFunction(llvm::StringRef FunctionName);
173  };
174};
175} // end namespace llvm
176#endif
177