[RegBankSelect] Initial implementation for non-optimized output.
authorQuentin Colombet <qcolombet@apple.com>
Thu, 7 Apr 2016 18:19:27 +0000 (18:19 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Thu, 7 Apr 2016 18:19:27 +0000 (18:19 +0000)
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.

llvm-svn: 265707

llvm/include/llvm/CodeGen/GlobalISel/RegBankSelect.h
llvm/lib/CodeGen/GlobalISel/RegBankSelect.cpp

index 9634f0a..57137ec 100644 (file)
 #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.
index 7f1e9d9..b417923 100644 (file)
@@ -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, "regbankselect",
                 "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;
 }