[llvm] r265707 - [RegBankSelect] Initial implementation for non-optimized output.

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


Author: qcolombet
Date: Thu Apr  7 13:19:27 2016
New Revision: 265707

URL: http://llvm.org/viewvc/llvm-project?rev=265707&view=rev
Log:
[RegBankSelect] Initial implementation for non-optimized output.
The pass walk through the machine function and assign the register banks
using the default mapping. In other words, there is no attempt to reduce
cross register copies.

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

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/RegBankSelect.h?rev=265707&r1=265706&r2=265707&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/RegBankSelect.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/RegBankSelect.h Thu Apr  7 13:19:27 2016
@@ -64,11 +64,13 @@
 #ifndef LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
 #define LLVM_CODEGEN_GLOBALISEL_REGBANKSELECT_H
 
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 
 namespace llvm {
 // Forward declarations.
-class RegisterBankInfo;
+class MachineRegisterInfo;
 
 /// This pass implements the reg bank selector pass used in the GlobalISel
 /// pipeline. At the end of this pass, all register operands have been assigned
@@ -81,6 +83,29 @@ private:
   /// to register banks.
   const RegisterBankInfo *RBI;
 
+  /// MRI contains all the register class/bank information that this
+  /// pass uses and updates.
+  MachineRegisterInfo *MRI;
+
+  /// Helper class used for every code morphing.
+  MachineIRBuilder MIRBuilder;
+
+  /// Assign the register bank of each operand of \p MI.
+  void assignInstr(MachineInstr &MI);
+
+  /// Initialize the field members using \p MF.
+  void init(MachineFunction &MF);
+
+  /// Check if \p Reg is already assigned what is described by \p ValMapping.
+  bool assignmentMatch(unsigned Reg,
+                       const RegisterBankInfo::ValueMapping &ValMapping) const;
+
+  /// Insert repairing code to map \p Reg as specified by \p ValMapping.
+  /// The repairing code is inserted where the MIRBuilder points.
+  /// \return The register of the properly mapped value.
+  unsigned repairReg(unsigned Reg,
+                     const RegisterBankInfo::ValueMapping &ValMapping);
+
 public:
   // Ctor, nothing fancy.
   RegBankSelect();
@@ -89,21 +114,29 @@ public:
     return "RegBankSelect";
   }
 
-  // Simplified algo:
-  //   RBI = MF.subtarget.getRegBankInfo()
-  //   MIRBuilder.reset(MF)
-  //   for each bb in MF
-  //     for each inst in bb
-  //       MappingCosts = RBI.getMapping(inst);
-  //       Idx = findIdxOfMinCost(MappingCosts)
-  //       CurRegBank = MappingCosts[Idx].RegBank
-  //       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
-  //       for each argument in inst
-  //         if (CurRegBank != argument.RegBank)
-  //           ArgReg = argument.getReg()
-  //           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
-  //           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
-  //           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
+  /// Walk through \p MF and assign a register bank to every virtual register
+  /// that are still mapped to nothing.
+  /// The target needs to provide a RegisterBankInfo and in particular
+  /// override RegisterBankInfo::getInstrMapping.
+  ///
+  /// Simplified algo:
+  /// \code
+  ///   RBI = MF.subtarget.getRegBankInfo()
+  ///   MIRBuilder.setMF(MF)
+  ///   for each bb in MF
+  ///     for each inst in bb
+  ///       MIRBuilder.setInstr(inst)
+  ///       MappingCosts = RBI.getMapping(inst);
+  ///       Idx = findIdxOfMinCost(MappingCosts)
+  ///       CurRegBank = MappingCosts[Idx].RegBank
+  ///       MRI.setRegBank(inst.getOperand(0).getReg(), CurRegBank)
+  ///       for each argument in inst
+  ///         if (CurRegBank != argument.RegBank)
+  ///           ArgReg = argument.getReg()
+  ///           Tmp = MRI.createNewVirtual(MRI.getSize(ArgReg), CurRegBank)
+  ///           MIRBuilder.buildInstr(COPY, Tmp, ArgReg)
+  ///           inst.getOperand(argument.getOperandNo()).setReg(Tmp)
+  /// \endcode
   bool runOnMachineFunction(MachineFunction &MF) override;
 };
 } // End namespace llvm.

Modified: llvm/trunk/lib/CodeGen/GlobalISel/RegBankSelect.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/RegBankSelect.cpp?rev=265707&r1=265706&r2=265707&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/RegBankSelect.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/RegBankSelect.cpp Thu Apr  7 13:19:27 2016
@@ -11,6 +11,9 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
+#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
 
 #define DEBUG_TYPE "regbankselect"
 
@@ -21,12 +24,111 @@ INITIALIZE_PASS(RegBankSelect, "regbanks
                 "Assign register bank of generic virtual registers",
                 false, false);
 
-RegBankSelect::RegBankSelect() : MachineFunctionPass(ID), RBI(nullptr) {
+RegBankSelect::RegBankSelect()
+    : MachineFunctionPass(ID), RBI(nullptr), MRI(nullptr) {
   initializeRegBankSelectPass(*PassRegistry::getPassRegistry());
 }
 
+void RegBankSelect::init(MachineFunction &MF) {
+  RBI = MF.getSubtarget().getRegBankInfo();
+  assert(RBI && "Cannot work without RegisterBankInfo");
+  MRI = &MF.getRegInfo();
+  MIRBuilder.setMF(MF);
+}
+
+bool RegBankSelect::assignmentMatch(
+    unsigned Reg, const RegisterBankInfo::ValueMapping &ValMapping) const {
+  // Each part of a break down needs to end up in a different register.
+  // In other word, Reg assignement does not match.
+  if (ValMapping.BreakDown.size() > 1)
+    return false;
+
+  const RegClassOrRegBank &CurAssignment = MRI->getRegClassOrRegBank(Reg);
+  // Nothing assigned, the assignment does not match.
+  if (!CurAssignment)
+    return false;
+  // Get the register bank form the current assignment.
+  const RegisterBank *CurRegBank = nullptr;
+  if (CurAssignment.is<const TargetRegisterClass *>())
+    CurRegBank = &RBI->getRegBankFromRegClass(
+        *CurAssignment.get<const TargetRegisterClass *>());
+  else
+    CurRegBank = CurAssignment.get<const RegisterBank *>();
+  return CurRegBank == ValMapping.BreakDown[0].RegBank;
+}
+
+unsigned
+RegBankSelect::repairReg(unsigned Reg,
+                         const RegisterBankInfo::ValueMapping &ValMapping) {
+  assert(ValMapping.BreakDown.size() == 1 &&
+         "Support for complex break down not supported yet");
+  const RegisterBankInfo::PartialMapping &PartialMap = ValMapping.BreakDown[0];
+  assert(PartialMap.Mask.getBitWidth() == MRI->getSize(Reg) &&
+         "Repairing other than copy not implemented yet");
+  unsigned NewReg =
+      MRI->createGenericVirtualRegister(PartialMap.Mask.getBitWidth());
+  (void)MIRBuilder.buildInstr(TargetOpcode::COPY, NewReg, Reg);
+  return NewReg;
+}
+
+void RegBankSelect::assignInstr(MachineInstr &MI) {
+  const RegisterBankInfo::InstructionMapping DefaultMapping =
+      RBI->getInstrMapping(MI);
+  // Make sure the mapping is valid for MI.
+  DefaultMapping.verify(MI);
+  // Set the insertion point before MI.
+  // This is where we are going to insert the repairing code if any.
+  MIRBuilder.setInstr(MI, /*Before*/ true);
+
+  // For now, do not look for alternative mappings.
+  // Alternative mapping may require to rewrite MI and we do not support
+  // that yet.
+  // Walk the operands and assign then to the chosen mapping, possibly with
+  // the insertion of repair code for uses.
+  for (unsigned OpIdx = 0, EndIdx = MI.getNumOperands(); OpIdx != EndIdx;
+       ++OpIdx) {
+    MachineOperand &MO = MI.getOperand(OpIdx);
+    // Nothing to be done for non-register operands.
+    if (!MO.isReg())
+      continue;
+    unsigned Reg = MO.getReg();
+    if (!Reg)
+      continue;
+
+    const RegisterBankInfo::ValueMapping &ValMapping =
+        DefaultMapping.getOperandMapping(OpIdx);
+    // If Reg is already properly mapped, move on.
+    if (assignmentMatch(Reg, ValMapping))
+      continue;
+
+    // For uses, we may need to create a new temporary.
+    // Indeed, if Reg is already assigned a register bank, at this
+    // point, we know it is different from the one defined by the
+    // chosen mapping, we need to adjust for that.
+    assert(ValMapping.BreakDown.size() == 1 &&
+           "Support for complex break down not supported yet");
+    if (!MO.isDef() && MRI->getRegClassOrRegBank(Reg)) {
+      // For phis, we need to change the insertion point to the end of
+      // the related predecessor block.
+      assert(!MI.isPHI() && "PHI support not implemented yet");
+      Reg = repairReg(Reg, ValMapping);
+    }
+    // If we end up here, MO should be free of encoding constraints,
+    // i.e., we do not have to constrained the RegBank of Reg to
+    // the requirement of the operands.
+    // If that is not the case, this means the code was broken before
+    // hands because we should have found that the assignment match.
+    // This will not hold when we will consider alternative mappings.
+    MRI->setRegBank(Reg, *ValMapping.BreakDown[0].RegBank);
+    MO.setReg(Reg);
+  }
+}
+
 bool RegBankSelect::runOnMachineFunction(MachineFunction &MF) {
-  // Avoid unused field member warning.
-  (void)RBI;
+  init(MF);
+  // Walk the function and assign register banks to all operands.
+  for (MachineBasicBlock &MBB : MF)
+    for (MachineInstr &MI : MBB)
+      assignInstr(MI);
   return false;
 }




More information about the llvm-commits mailing list