brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · 1e07962 Raw
229 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8/// \file9/// 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_H14#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H15 16#include "llvm/CodeGen/RegisterBankInfo.h"17 18#define GET_REGBANK_DECLARATIONS19#include "MipsGenRegisterBank.inc"20 21namespace llvm {22 23class TargetRegisterInfo;24 25class MipsGenRegisterBankInfo : public RegisterBankInfo {26#define GET_TARGET_REGBANK_CLASS27#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 InstructionMapping &36  getInstrMapping(const MachineInstr &MI) const override;37 38  /// Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or39  /// G_UNMERGE and erase instructions that became dead in the process. We40  /// manually assign bank to def operand of all new instructions that were41  /// created in the process since they will not end up in RegBankSelect loop.42  void applyMappingImpl(MachineIRBuilder &Builder,43                        const OperandsMapper &OpdMapper) const override;44 45  /// RegBankSelect determined that s64 operand is better to be split into two46  /// s32 operands in gprb. Here we manually set register banks of def operands47  /// of newly created instructions since they will not get regbankselected.48  void setRegBank(MachineInstr &MI, MachineRegisterInfo &MRI) const;49 50private:51  /// Some instructions are used with both floating point and integer operands.52  /// We assign InstType to such instructions as it helps us to avoid cross bank53  /// copies. InstType deppends on context.54  enum InstType {55    /// Temporary type, when visit(..., nullptr) finishes will convert to one of56    /// the remaining types: Integer, FloatingPoint or Ambiguous.57    NotDetermined,58    /// Connected with instruction that interprets 'bags of bits' as integers.59    /// Select gprb to avoid cross bank copies.60    Integer,61    /// Connected with instruction that interprets 'bags of bits' as floating62    /// point numbers. Select fprb to avoid cross bank copies.63    FloatingPoint,64    /// Represents moving 'bags of bits' around. Select same bank for entire65    /// chain to avoid cross bank copies. Currently we select fprb for s64 and66    /// gprb for s32 Ambiguous operands.67    Ambiguous,68    /// Only used for s64. Unlike Ambiguous s64, AmbiguousWithMergeOrUnmerge s6469    /// is mapped to gprb (legalized using narrow scalar to s32).70    AmbiguousWithMergeOrUnmerge71  };72 73  bool isAmbiguous_64(InstType InstTy, unsigned OpSize) const {74    if (InstTy == InstType::Ambiguous && OpSize == 64)75      return true;76    return false;77  }78 79  bool isAmbiguous_32(InstType InstTy, unsigned OpSize) const {80    if (InstTy == InstType::Ambiguous && OpSize == 32)81      return true;82    return false;83  }84 85  bool isAmbiguous_32or64(InstType InstTy, unsigned OpSize) const {86    if (InstTy == InstType::Ambiguous && (OpSize == 32 || OpSize == 64))87      return true;88    return false;89  }90 91  bool isAmbiguousWithMergeOrUnmerge_64(InstType InstTy,92                                        unsigned OpSize) const {93    if (InstTy == InstType::AmbiguousWithMergeOrUnmerge && OpSize == 64)94      return true;95    return false;96  }97 98  bool isFloatingPoint_32or64(InstType InstTy, unsigned OpSize) const {99    if (InstTy == InstType::FloatingPoint && (OpSize == 32 || OpSize == 64))100      return true;101    return false;102  }103 104  bool isFloatingPoint_64(InstType InstTy, unsigned OpSize) const {105    if (InstTy == InstType::FloatingPoint && OpSize == 64)106      return true;107    return false;108  }109 110  bool isInteger_32(InstType InstTy, unsigned OpSize) const {111    if (InstTy == InstType::Integer && OpSize == 32)112      return true;113    return false;114  }115 116  /// Some generic instructions have operands that can be mapped to either fprb117  /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1118  /// is always gprb since it is a pointer.119  /// This class provides containers for MI's ambiguous:120  /// DefUses : MachineInstrs that use one of MI's ambiguous def operands.121  /// UseDefs : MachineInstrs that define MI's ambiguous use operands.122  class AmbiguousRegDefUseContainer {123    SmallVector<MachineInstr *, 2> DefUses;124    SmallVector<MachineInstr *, 2> UseDefs;125 126    void addDefUses(Register Reg, const MachineRegisterInfo &MRI);127    void addUseDef(Register Reg, const MachineRegisterInfo &MRI);128 129    /// Skip copy instructions until we get to a non-copy instruction or to a130    /// copy with phys register as def. Used during search for DefUses.131    /// MI :  %5 = COPY %4132    ///       %6 = COPY %5133    ///       $v0 = COPY %6 <- we want this one.134    MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const;135 136    /// Skip copy instructions until we get to a non-copy instruction or to a137    /// copy with phys register as use. Used during search for UseDefs.138    ///       %1 = COPY $a1 <- we want this one.139    ///       %2 = COPY %1140    /// MI =  %3 = COPY %2141    MachineInstr *skipCopiesIncoming(MachineInstr *MI) const;142 143  public:144    AmbiguousRegDefUseContainer(const MachineInstr *MI);145    SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; }146    SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; }147  };148 149  class TypeInfoForMF {150    /// MachineFunction name is used to recognise when MF changes.151    std::string MFName;152    /// <key, value> : value is vector of all MachineInstrs that are waiting for153    /// key to figure out type of some of its ambiguous operands.154    DenseMap<const MachineInstr *, SmallVector<const MachineInstr *, 2>>155        WaitingQueues;156    /// Recorded InstTypes for visited instructions.157    DenseMap<const MachineInstr *, InstType> Types;158 159    /// Recursively visit MI's adjacent instructions and find MI's InstType.160    bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI,161               InstType &AmbiguousTy);162 163    /// Visit MI's adjacent UseDefs or DefUses.164    bool visitAdjacentInstrs(const MachineInstr *MI,165                             SmallVectorImpl<MachineInstr *> &AdjacentInstrs,166                             bool isDefUse, InstType &AmbiguousTy);167 168    /// Set type for MI, and recursively for all instructions that are169    /// waiting for MI's type.170    void setTypes(const MachineInstr *MI, InstType ITy);171 172    /// InstType for MI is determined, set it to InstType that corresponds to173    /// physical regisiter that is operand number Op in CopyInst.174    void setTypesAccordingToPhysicalRegister(const MachineInstr *MI,175                                             const MachineInstr *CopyInst,176                                             unsigned Op);177 178    /// Set default values for MI in order to start visit.179    void startVisit(const MachineInstr *MI) {180      Types.try_emplace(MI, InstType::NotDetermined);181      WaitingQueues.try_emplace(MI);182    }183 184    /// Returns true if instruction was already visited. Type might not be185    /// determined at this point but will be when visit(..., nullptr) finishes.186    bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); };187 188    /// Returns recorded type for instruction.189    const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const {190      assert(wasVisited(MI) && "Instruction was not visited!");191      return Types.find(MI)->getSecond();192    };193 194    /// Change recorded type for instruction.195    void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) {196      assert(wasVisited(MI) && "Instruction was not visited!");197      Types.find(MI)->getSecond() = InstTy;198    };199 200    /// Returns WaitingQueue for instruction.201    const SmallVectorImpl<const MachineInstr *> &202    getWaitingQueueFor(const MachineInstr *MI) const {203      assert(WaitingQueues.count(MI) && "Instruction was not visited!");204      return WaitingQueues.find(MI)->getSecond();205    };206 207    /// Add WaitingForMI to MI's WaitingQueue.208    void addToWaitingQueue(const MachineInstr *MI,209                           const MachineInstr *WaitingForMI) {210      assert(WaitingQueues.count(MI) && "Instruction was not visited!");211      WaitingQueues.find(MI)->getSecond().push_back(WaitingForMI);212    };213 214  public:215    InstType determineInstType(const MachineInstr *MI);216 217    void cleanupIfNewFunction(llvm::StringRef FunctionName);218 219    /// MI is about to get destroyed (using narrow scalar). Internal data is220    /// saved based on MI's address, clear it since it is no longer valid.221    void clearTypeInfoData(const MachineInstr *MI) {222      Types.erase(MI);223      WaitingQueues.erase(MI);224    };225  };226};227} // end namespace llvm228#endif229