109467b48Spatrick //===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick /// \file 909467b48Spatrick /// This file declares the targeting of the RegisterBankInfo class for Mips. 1009467b48Spatrick /// \todo This should be generated by TableGen. 1109467b48Spatrick //===----------------------------------------------------------------------===// 1209467b48Spatrick 1309467b48Spatrick #ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H 1409467b48Spatrick #define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H 1509467b48Spatrick 16*d415bd75Srobert #include "llvm/CodeGen/RegisterBankInfo.h" 1709467b48Spatrick 1809467b48Spatrick #define GET_REGBANK_DECLARATIONS 1909467b48Spatrick #include "MipsGenRegisterBank.inc" 2009467b48Spatrick 2109467b48Spatrick namespace llvm { 2209467b48Spatrick 2309467b48Spatrick class TargetRegisterInfo; 2409467b48Spatrick 2509467b48Spatrick class MipsGenRegisterBankInfo : public RegisterBankInfo { 2609467b48Spatrick #define GET_TARGET_REGBANK_CLASS 2709467b48Spatrick #include "MipsGenRegisterBank.inc" 2809467b48Spatrick }; 2909467b48Spatrick 3009467b48Spatrick /// This class provides the information for the target register banks. 3109467b48Spatrick class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo { 3209467b48Spatrick public: 3309467b48Spatrick MipsRegisterBankInfo(const TargetRegisterInfo &TRI); 3409467b48Spatrick 3509467b48Spatrick const RegisterBank &getRegBankFromRegClass(const TargetRegisterClass &RC, 3609467b48Spatrick LLT) const override; 3709467b48Spatrick 3809467b48Spatrick const InstructionMapping & 3909467b48Spatrick getInstrMapping(const MachineInstr &MI) const override; 4009467b48Spatrick 4109467b48Spatrick /// Here we have to narrowScalar s64 operands to s32, combine away G_MERGE or 4209467b48Spatrick /// G_UNMERGE and erase instructions that became dead in the process. We 4309467b48Spatrick /// manually assign bank to def operand of all new instructions that were 4409467b48Spatrick /// created in the process since they will not end up in RegBankSelect loop. 4509467b48Spatrick void applyMappingImpl(const OperandsMapper &OpdMapper) const override; 4609467b48Spatrick 4709467b48Spatrick /// RegBankSelect determined that s64 operand is better to be split into two 4809467b48Spatrick /// s32 operands in gprb. Here we manually set register banks of def operands 4909467b48Spatrick /// of newly created instructions since they will not get regbankselected. 5009467b48Spatrick void setRegBank(MachineInstr &MI, MachineRegisterInfo &MRI) const; 5109467b48Spatrick 5209467b48Spatrick private: 5309467b48Spatrick /// Some instructions are used with both floating point and integer operands. 5409467b48Spatrick /// We assign InstType to such instructions as it helps us to avoid cross bank 5509467b48Spatrick /// copies. InstType deppends on context. 5609467b48Spatrick enum InstType { 5709467b48Spatrick /// Temporary type, when visit(..., nullptr) finishes will convert to one of 5809467b48Spatrick /// the remaining types: Integer, FloatingPoint or Ambiguous. 5909467b48Spatrick NotDetermined, 6009467b48Spatrick /// Connected with instruction that interprets 'bags of bits' as integers. 6109467b48Spatrick /// Select gprb to avoid cross bank copies. 6209467b48Spatrick Integer, 6309467b48Spatrick /// Connected with instruction that interprets 'bags of bits' as floating 6409467b48Spatrick /// point numbers. Select fprb to avoid cross bank copies. 6509467b48Spatrick FloatingPoint, 6609467b48Spatrick /// Represents moving 'bags of bits' around. Select same bank for entire 6709467b48Spatrick /// chain to avoid cross bank copies. Currently we select fprb for s64 and 6809467b48Spatrick /// gprb for s32 Ambiguous operands. 69097a140dSpatrick Ambiguous, 70097a140dSpatrick /// Only used for s64. Unlike Ambiguous s64, AmbiguousWithMergeOrUnmerge s64 71097a140dSpatrick /// is mapped to gprb (legalized using narrow scalar to s32). 72097a140dSpatrick AmbiguousWithMergeOrUnmerge 7309467b48Spatrick }; 7409467b48Spatrick isAmbiguous_64(InstType InstTy,unsigned OpSize)75097a140dSpatrick bool isAmbiguous_64(InstType InstTy, unsigned OpSize) const { 76097a140dSpatrick if (InstTy == InstType::Ambiguous && OpSize == 64) 77097a140dSpatrick return true; 78097a140dSpatrick return false; 79097a140dSpatrick } 80097a140dSpatrick isAmbiguous_32(InstType InstTy,unsigned OpSize)81097a140dSpatrick bool isAmbiguous_32(InstType InstTy, unsigned OpSize) const { 82097a140dSpatrick if (InstTy == InstType::Ambiguous && OpSize == 32) 83097a140dSpatrick return true; 84097a140dSpatrick return false; 85097a140dSpatrick } 86097a140dSpatrick isAmbiguous_32or64(InstType InstTy,unsigned OpSize)87097a140dSpatrick bool isAmbiguous_32or64(InstType InstTy, unsigned OpSize) const { 88097a140dSpatrick if (InstTy == InstType::Ambiguous && (OpSize == 32 || OpSize == 64)) 89097a140dSpatrick return true; 90097a140dSpatrick return false; 91097a140dSpatrick } 92097a140dSpatrick isAmbiguousWithMergeOrUnmerge_64(InstType InstTy,unsigned OpSize)93097a140dSpatrick bool isAmbiguousWithMergeOrUnmerge_64(InstType InstTy, 94097a140dSpatrick unsigned OpSize) const { 95097a140dSpatrick if (InstTy == InstType::AmbiguousWithMergeOrUnmerge && OpSize == 64) 96097a140dSpatrick return true; 97097a140dSpatrick return false; 98097a140dSpatrick } 99097a140dSpatrick isFloatingPoint_32or64(InstType InstTy,unsigned OpSize)100097a140dSpatrick bool isFloatingPoint_32or64(InstType InstTy, unsigned OpSize) const { 101097a140dSpatrick if (InstTy == InstType::FloatingPoint && (OpSize == 32 || OpSize == 64)) 102097a140dSpatrick return true; 103097a140dSpatrick return false; 104097a140dSpatrick } 105097a140dSpatrick isFloatingPoint_64(InstType InstTy,unsigned OpSize)106097a140dSpatrick bool isFloatingPoint_64(InstType InstTy, unsigned OpSize) const { 107097a140dSpatrick if (InstTy == InstType::FloatingPoint && OpSize == 64) 108097a140dSpatrick return true; 109097a140dSpatrick return false; 110097a140dSpatrick } 111097a140dSpatrick isInteger_32(InstType InstTy,unsigned OpSize)112097a140dSpatrick bool isInteger_32(InstType InstTy, unsigned OpSize) const { 113097a140dSpatrick if (InstTy == InstType::Integer && OpSize == 32) 114097a140dSpatrick return true; 115097a140dSpatrick return false; 116097a140dSpatrick } 117097a140dSpatrick 11809467b48Spatrick /// Some generic instructions have operands that can be mapped to either fprb 11909467b48Spatrick /// or gprb e.g. for G_LOAD we consider only operand 0 as ambiguous, operand 1 12009467b48Spatrick /// is always gprb since it is a pointer. 12109467b48Spatrick /// This class provides containers for MI's ambiguous: 12209467b48Spatrick /// DefUses : MachineInstrs that use one of MI's ambiguous def operands. 12309467b48Spatrick /// UseDefs : MachineInstrs that define MI's ambiguous use operands. 12409467b48Spatrick class AmbiguousRegDefUseContainer { 12509467b48Spatrick SmallVector<MachineInstr *, 2> DefUses; 12609467b48Spatrick SmallVector<MachineInstr *, 2> UseDefs; 12709467b48Spatrick 12809467b48Spatrick void addDefUses(Register Reg, const MachineRegisterInfo &MRI); 12909467b48Spatrick void addUseDef(Register Reg, const MachineRegisterInfo &MRI); 13009467b48Spatrick 13109467b48Spatrick /// Skip copy instructions until we get to a non-copy instruction or to a 13209467b48Spatrick /// copy with phys register as def. Used during search for DefUses. 13309467b48Spatrick /// MI : %5 = COPY %4 13409467b48Spatrick /// %6 = COPY %5 13509467b48Spatrick /// $v0 = COPY %6 <- we want this one. 13609467b48Spatrick MachineInstr *skipCopiesOutgoing(MachineInstr *MI) const; 13709467b48Spatrick 13809467b48Spatrick /// Skip copy instructions until we get to a non-copy instruction or to a 13909467b48Spatrick /// copy with phys register as use. Used during search for UseDefs. 14009467b48Spatrick /// %1 = COPY $a1 <- we want this one. 14109467b48Spatrick /// %2 = COPY %1 14209467b48Spatrick /// MI = %3 = COPY %2 14309467b48Spatrick MachineInstr *skipCopiesIncoming(MachineInstr *MI) const; 14409467b48Spatrick 14509467b48Spatrick public: 14609467b48Spatrick AmbiguousRegDefUseContainer(const MachineInstr *MI); getDefUses()14709467b48Spatrick SmallVectorImpl<MachineInstr *> &getDefUses() { return DefUses; } getUseDefs()14809467b48Spatrick SmallVectorImpl<MachineInstr *> &getUseDefs() { return UseDefs; } 14909467b48Spatrick }; 15009467b48Spatrick 15109467b48Spatrick class TypeInfoForMF { 15209467b48Spatrick /// MachineFunction name is used to recognise when MF changes. 15373471bf0Spatrick std::string MFName; 15409467b48Spatrick /// <key, value> : value is vector of all MachineInstrs that are waiting for 15509467b48Spatrick /// key to figure out type of some of its ambiguous operands. 15609467b48Spatrick DenseMap<const MachineInstr *, SmallVector<const MachineInstr *, 2>> 15709467b48Spatrick WaitingQueues; 15809467b48Spatrick /// Recorded InstTypes for visited instructions. 15909467b48Spatrick DenseMap<const MachineInstr *, InstType> Types; 16009467b48Spatrick 16109467b48Spatrick /// Recursively visit MI's adjacent instructions and find MI's InstType. 162097a140dSpatrick bool visit(const MachineInstr *MI, const MachineInstr *WaitingForTypeOfMI, 163097a140dSpatrick InstType &AmbiguousTy); 16409467b48Spatrick 16509467b48Spatrick /// Visit MI's adjacent UseDefs or DefUses. 16609467b48Spatrick bool visitAdjacentInstrs(const MachineInstr *MI, 16709467b48Spatrick SmallVectorImpl<MachineInstr *> &AdjacentInstrs, 168097a140dSpatrick bool isDefUse, InstType &AmbiguousTy); 16909467b48Spatrick 17009467b48Spatrick /// Set type for MI, and recursively for all instructions that are 17109467b48Spatrick /// waiting for MI's type. 17209467b48Spatrick void setTypes(const MachineInstr *MI, InstType ITy); 17309467b48Spatrick 17409467b48Spatrick /// InstType for MI is determined, set it to InstType that corresponds to 17509467b48Spatrick /// physical regisiter that is operand number Op in CopyInst. 17609467b48Spatrick void setTypesAccordingToPhysicalRegister(const MachineInstr *MI, 17709467b48Spatrick const MachineInstr *CopyInst, 17809467b48Spatrick unsigned Op); 17909467b48Spatrick 18009467b48Spatrick /// Set default values for MI in order to start visit. startVisit(const MachineInstr * MI)18109467b48Spatrick void startVisit(const MachineInstr *MI) { 18209467b48Spatrick Types.try_emplace(MI, InstType::NotDetermined); 18309467b48Spatrick WaitingQueues.try_emplace(MI); 18409467b48Spatrick } 18509467b48Spatrick 18609467b48Spatrick /// Returns true if instruction was already visited. Type might not be 18709467b48Spatrick /// determined at this point but will be when visit(..., nullptr) finishes. wasVisited(const MachineInstr * MI)18809467b48Spatrick bool wasVisited(const MachineInstr *MI) const { return Types.count(MI); }; 18909467b48Spatrick 19009467b48Spatrick /// Returns recorded type for instruction. getRecordedTypeForInstr(const MachineInstr * MI)19109467b48Spatrick const InstType &getRecordedTypeForInstr(const MachineInstr *MI) const { 19209467b48Spatrick assert(wasVisited(MI) && "Instruction was not visited!"); 19309467b48Spatrick return Types.find(MI)->getSecond(); 19409467b48Spatrick }; 19509467b48Spatrick 19609467b48Spatrick /// Change recorded type for instruction. changeRecordedTypeForInstr(const MachineInstr * MI,InstType InstTy)19709467b48Spatrick void changeRecordedTypeForInstr(const MachineInstr *MI, InstType InstTy) { 19809467b48Spatrick assert(wasVisited(MI) && "Instruction was not visited!"); 19909467b48Spatrick Types.find(MI)->getSecond() = InstTy; 20009467b48Spatrick }; 20109467b48Spatrick 20209467b48Spatrick /// Returns WaitingQueue for instruction. 20309467b48Spatrick const SmallVectorImpl<const MachineInstr *> & getWaitingQueueFor(const MachineInstr * MI)20409467b48Spatrick getWaitingQueueFor(const MachineInstr *MI) const { 20509467b48Spatrick assert(WaitingQueues.count(MI) && "Instruction was not visited!"); 20609467b48Spatrick return WaitingQueues.find(MI)->getSecond(); 20709467b48Spatrick }; 20809467b48Spatrick 20909467b48Spatrick /// Add WaitingForMI to MI's WaitingQueue. addToWaitingQueue(const MachineInstr * MI,const MachineInstr * WaitingForMI)21009467b48Spatrick void addToWaitingQueue(const MachineInstr *MI, 21109467b48Spatrick const MachineInstr *WaitingForMI) { 21209467b48Spatrick assert(WaitingQueues.count(MI) && "Instruction was not visited!"); 21309467b48Spatrick WaitingQueues.find(MI)->getSecond().push_back(WaitingForMI); 21409467b48Spatrick }; 21509467b48Spatrick 21609467b48Spatrick public: 21709467b48Spatrick InstType determineInstType(const MachineInstr *MI); 21809467b48Spatrick 21909467b48Spatrick void cleanupIfNewFunction(llvm::StringRef FunctionName); 220097a140dSpatrick 221097a140dSpatrick /// MI is about to get destroyed (using narrow scalar). Internal data is 222097a140dSpatrick /// saved based on MI's address, clear it since it is no longer valid. clearTypeInfoData(const MachineInstr * MI)223097a140dSpatrick void clearTypeInfoData(const MachineInstr *MI) { 224097a140dSpatrick Types.erase(MI); 225097a140dSpatrick WaitingQueues.erase(MI); 226097a140dSpatrick }; 22709467b48Spatrick }; 22809467b48Spatrick }; 22909467b48Spatrick } // end namespace llvm 23009467b48Spatrick #endif 231