[llvm] r265703 - [RegisterBankInfo] Provide a target independent helper function to guess

Quentin Colombet via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 7 11:01:19 PDT 2016


Author: qcolombet
Date: Thu Apr  7 13:01:19 2016
New Revision: 265703

URL: http://llvm.org/viewvc/llvm-project?rev=265703&view=rev
Log:
[RegisterBankInfo] Provide a target independent helper function to guess
the mapping of an instruction on register bank.

For most instructions, it is possible to guess the mapping of the
instruciton by using the encoding constraints.
It remains instructions without encoding constraints.
For copy-like instructions, we try to propagate the information we get
from the other operands. Otherwise, the target has to give this
information.

Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
    llvm/trunk/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h?rev=265703&r1=265702&r2=265703&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h Thu Apr  7 13:01:19 2016
@@ -26,6 +26,7 @@
 
 namespace llvm {
 class MachineInstr;
+class MachineRegisterInfo;
 class TargetRegisterInfo;
 class raw_ostream;
 
@@ -66,6 +67,7 @@ public:
   struct ValueMapping {
     /// How the value is broken down between the different register banks.
     SmallVector<PartialMapping, 2> BreakDown;
+
     /// Verify that this mapping makes sense for a value of \p ExpectedBitWidth.
     void verify(unsigned ExpectedBitWidth) const;
   };
@@ -132,6 +134,13 @@ public:
     /// This is a lightweight check for obvious wrong instance.
     bool isValid() const { return getID() != InvalidMappingID; }
 
+    /// Set the operand mapping for the \p OpIdx-th operand.
+    /// The mapping will consist of only one element in the break down list.
+    /// This element will map to \p RegBank and fully define a mask, whose
+    /// bitwidth matches the size of \p MaskSize.
+    void setOperandMapping(unsigned OpIdx, unsigned MaskSize,
+                           const RegisterBank &RegBank);
+
     /// Verifiy that this mapping makes sense for \p MI.
     /// \pre \p MI must be connected to a MachineFunction.
     void verify(const MachineInstr &MI) const;
@@ -197,6 +206,25 @@ protected:
     return RegBanks[ID];
   }
 
+  /// Try to get the mapping of \p MI.
+  /// See getInstrMapping for more details on what a mapping represents.
+  ///
+  /// Unlike getInstrMapping the returned InstructionMapping may be invalid
+  /// (isValid() == false).
+  /// This means that the target independent code is not smart enough
+  /// to get the mapping of \p MI and thus, the target has to provide the
+  /// information for \p MI.
+  ///
+  /// This implementation is able to get the mapping of:
+  /// - Target specific instructions by looking at the encoding constraints.
+  /// - Any instruction if all the register operands are already been assigned
+  ///   a register, a register class, or a register bank.
+  /// - Copies and phis if at least one of the operand has been assigned a
+  ///   register, a register class, or a register bank.
+  /// In other words, this method will likely fail to find a mapping for
+  /// any generic opcode that has not been lowered by target specific code.
+  InstructionMapping getInstrMappingImpl(const MachineInstr &MI) const;
+
 public:
   virtual ~RegisterBankInfo() {}
 
@@ -205,6 +233,14 @@ public:
     return const_cast<RegisterBankInfo *>(this)->getRegBank(ID);
   }
 
+  /// Get the register bank of \p Reg.
+  /// If Reg has not been assigned a register, a register class,
+  /// or a register bank, then this returns nullptr.
+  ///
+  /// \pre Reg != 0 (NoRegister)
+  const RegisterBank *getRegBank(unsigned Reg, const MachineRegisterInfo &MRI,
+                                 const TargetRegisterInfo &TRI) const;
+
   /// Get the total number of register banks.
   unsigned getNumRegBanks() const { return NumRegBanks; }
 

Modified: llvm/trunk/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp?rev=265703&r1=265702&r2=265703&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp Thu Apr  7 13:01:19 2016
@@ -209,52 +209,107 @@ void RegisterBankInfo::addRegBankCoverag
   } while (!WorkList.empty());
 }
 
+const RegisterBank *
+RegisterBankInfo::getRegBank(unsigned Reg, const MachineRegisterInfo &MRI,
+                             const TargetRegisterInfo &TRI) const {
+  if (TargetRegisterInfo::isPhysicalRegister(Reg))
+    return &getRegBankFromRegClass(*TRI.getMinimalPhysRegClass(Reg));
+
+  assert(Reg && "NoRegister does not have a register bank");
+  const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
+  if (RegClassOrBank.is<const RegisterBank *>())
+    return RegClassOrBank.get<const RegisterBank *>();
+  const TargetRegisterClass *RC =
+      RegClassOrBank.get<const TargetRegisterClass *>();
+  if (RC)
+    return &getRegBankFromRegClass(*RC);
+  return nullptr;
+}
+
 RegisterBankInfo::InstructionMapping
-RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
-  if (MI.getOpcode() > TargetOpcode::GENERIC_OP_END) {
-    // This is a target specific opcode:
-    // The mapping of the registers is already available via the
-    // register class.
-    // Just map the register class to a register bank.
-    RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1,
-                                                 MI.getNumOperands());
-    const MachineFunction &MF = *MI.getParent()->getParent();
-    const TargetSubtargetInfo &STI = MF.getSubtarget();
-    const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
-    const TargetInstrInfo &TII = *STI.getInstrInfo();
-    const MachineRegisterInfo &MRI = MF.getRegInfo();
-
-    for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) {
-      const MachineOperand &MO = MI.getOperand(OpIdx);
-      if (!MO.isReg())
-        continue;
-      unsigned Reg = MO.getReg();
-      if (!Reg)
-        continue;
-      // Since this is a target instruction, the operand must have a register
-      // class constraint.
+RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const {
+  RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1,
+                                               MI.getNumOperands());
+  const MachineFunction &MF = *MI.getParent()->getParent();
+  const TargetSubtargetInfo &STI = MF.getSubtarget();
+  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
+  const MachineRegisterInfo &MRI = MF.getRegInfo();
+  // We may need to query the instruction encoding to guess the mapping.
+  const TargetInstrInfo &TII = *STI.getInstrInfo();
+
+  // Before doing anything complicated check if the mapping is not
+  // directly available.
+  bool CompleteMapping = true;
+  // For copies we want to walk over the operands and try to find one
+  // that has a register bank.
+  bool isCopyLike = MI.isCopy() || MI.isPHI();
+  // Remember the register bank for reuse for copy-like instructions.
+  const RegisterBank *RegBank = nullptr;
+  // Remember the size of the register for reuse for copy-like instructions.
+  unsigned RegSize = 0;
+  for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) {
+    const MachineOperand &MO = MI.getOperand(OpIdx);
+    if (!MO.isReg())
+      continue;
+    unsigned Reg = MO.getReg();
+    if (!Reg)
+      continue;
+    const RegisterBank *CurRegBank = getRegBank(Reg, MRI, TRI);
+    if (!CurRegBank) {
+      // The mapping of the registers may be available via the
+      // register class constraints.
       const TargetRegisterClass *RC =
           MI.getRegClassConstraint(OpIdx, &TII, &TRI);
-      // Note: This cannot be a "dynamic" constraint like inline asm,
-      //       since inlineasm opcode is a generic opcode.
-      assert(RC && "Invalid encoding constraints for target instruction?");
-
-      // Build the value mapping.
-      const RegisterBank &RegBank = getRegBankFromRegClass(*RC);
-      unsigned RegSize = getSizeInBits(Reg, MRI, TRI);
-      assert(RegSize <= RegBank.getSize() && "Register bank too small");
-      // Assume the value is mapped in one register that lives in the
-      // register bank that covers RC.
-      APInt Mask(RegSize, 0);
-      // The value is represented by all the bits.
-      Mask.flipAllBits();
-
-      // Create the mapping object.
-      ValueMapping ValMapping;
-      ValMapping.BreakDown.push_back(PartialMapping(Mask, RegBank));
-      Mapping.setOperandMapping(OpIdx, ValMapping);
+
+      if (RC)
+        CurRegBank = &getRegBankFromRegClass(*RC);
     }
+    if (!CurRegBank) {
+      CompleteMapping = false;
+
+      if (!isCopyLike)
+        // MI does not carry enough information to guess the mapping.
+        return InstructionMapping();
+
+      // For copies, we want to keep interating to find a register
+      // bank for the other operands if we did not find one yet.
+      if(RegBank)
+        break;
+      continue;
+    }
+    RegBank = CurRegBank;
+    RegSize = getSizeInBits(Reg, MRI, TRI);
+    Mapping.setOperandMapping(OpIdx, RegSize, *CurRegBank);
+  }
+
+  if (CompleteMapping)
     return Mapping;
+
+  assert(isCopyLike && "We should have bailed on non-copies at this point");
+  // For copy like instruction, if none of the operand has a register
+  // bank avialable, there is nothing we can propagate.
+  if (!RegBank)
+    return InstructionMapping();
+
+  // This is a copy-like instruction.
+  // Propagate RegBank to all operands that do not have a
+  // mapping yet.
+  for (unsigned OpIdx = 0, End = MI.getNumOperands(); OpIdx != End; ++OpIdx) {
+    if (!static_cast<const InstructionMapping *>(&Mapping)
+             ->getOperandMapping(OpIdx)
+             .BreakDown.empty())
+      continue;
+    Mapping.setOperandMapping(OpIdx, RegSize, *RegBank);
+  }
+  return Mapping;
+}
+
+RegisterBankInfo::InstructionMapping
+RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
+  if (!isPreISelGenericOpcode(MI.getOpcode())) {
+    RegisterBankInfo::InstructionMapping Mapping = getInstrMappingImpl(MI);
+    if (Mapping.isValid())
+      return Mapping;
   }
   llvm_unreachable("The target must implement this");
 }
@@ -336,6 +391,18 @@ void RegisterBankInfo::ValueMapping::ver
   assert(ValueMask.isAllOnesValue() && "Value is not fully mapped");
 }
 
+void RegisterBankInfo::InstructionMapping::setOperandMapping(
+    unsigned OpIdx, unsigned MaskSize, const RegisterBank &RegBank) {
+  // Build the value mapping.
+  assert(MaskSize <= RegBank.getSize() && "Register bank is too small");
+  APInt Mask(MaskSize, 0);
+  // The value is represented by all the bits.
+  Mask.flipAllBits();
+
+  // Create the mapping object.
+  getOperandMapping(OpIdx).BreakDown.push_back(PartialMapping(Mask, RegBank));
+}
+
 void RegisterBankInfo::InstructionMapping::verify(
     const MachineInstr &MI) const {
   // Check that all the register operands are properly mapped.




More information about the llvm-commits mailing list