[RegisterBankInfo] Add methods to get the possible mapping of an instruction on a...
authorQuentin Colombet <qcolombet@apple.com>
Wed, 6 Apr 2016 21:37:22 +0000 (21:37 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Wed, 6 Apr 2016 21:37:22 +0000 (21:37 +0000)
This will be used by the register bank select pass to assign register banks
for generic virtual registers.

This was originally committed as r265573 but broke at least one windows bot.
The problem with the windows bot was that it was using a copy constructor for
the InstructionMappings class and could not synthesize it. Actually, the fact
that this class is not copy constructable is expected and the compiler should
use the move assignment constructor. Marking the problematic assignment
explicitly as using the move constructor has its own problems.

Indeed, with recent clang we get a warning that we may prevent the elision of
the copy by the compiler. A proper fix for both compilers would be to change the
API of getPossibleInstrMapping to take a InstructionMappings as input/output
parameter. This does not feel natural and since GISel is not used on windows
yet, I chose to workaround the problem by not compiling the problematic code on
windows.

llvm-svn: 265604

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

index 63bb8b2..9077758 100644 (file)
@@ -16,6 +16,7 @@
 #define LLVM_CODEGEN_GLOBALISEL_REGBANKINFO_H
 
 #include "llvm/ADT/APInt.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
 #include "llvm/CodeGen/GlobalISel/Types.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -123,6 +124,11 @@ public:
     void verify(const MachineInstr &MI) const;
   };
 
+  /// Convenient type to represent the alternatives for mapping an
+  /// instruction.
+  /// \todo When we move to TableGen this should be an array ref.
+  typedef SmallVector<InstructionMapping, 4> InstructionMappings;
+
 protected:
   /// Hold the set of supported register banks.
   std::unique_ptr<RegisterBank[]> RegBanks;
@@ -213,6 +219,53 @@ public:
     return 0;
   }
 
+  /// Identifier used when the related instruction mapping instance
+  /// is generated by target independent code.
+  /// Make sure not to use that identifier to avoid possible collision.
+  static const unsigned DefaultMappingID;
+
+  /// Get the mapping of the different operands of \p MI
+  /// on the register bank.
+  /// This mapping should be the direct translation of \p MI.
+  /// The target independent implementation gives a mapping based on
+  /// the register classes for the target specific opcode.
+  /// It uses the ID RegisterBankInfo::DefaultMappingID for that mapping.
+  /// Make sure you do not use that ID for the alternative mapping
+  /// for MI. See getInstrAlternativeMappings for the alternative
+  /// mappings.
+  ///
+  /// For instance, if \p MI is a vector add, the mapping should
+  /// not be a scalarization of the add.
+  ///
+  /// \post returnedVal.verify(MI).
+  ///
+  /// \note If returnedVal does not verify MI, this would probably mean
+  /// that the target does not support that instruction.
+  virtual InstructionMapping getInstrMapping(const MachineInstr &MI) const;
+
+  /// Get the alternative mappings for \p MI.
+  /// Alternative in the sense different from getInstrMapping.
+  virtual InstructionMappings
+  getInstrAlternativeMappings(const MachineInstr &MI) const;
+
+  /// Get the possible mapping for \p MI.
+  /// A mapping defines where the different operands may live and at what cost.
+  /// For instance, let us consider:
+  /// v0(16) = G_ADD <2 x i8> v1, v2
+  /// The possible mapping could be:
+  ///
+  /// {/*ID*/VectorAdd, /*Cost*/1, /*v0*/{(0xFFFF, VPR)}, /*v1*/{(0xFFFF, VPR)},
+  ///                              /*v2*/{(0xFFFF, VPR)}}
+  /// {/*ID*/ScalarAddx2, /*Cost*/2, /*v0*/{(0x00FF, GPR),(0xFF00, GPR)},
+  ///                                /*v1*/{(0x00FF, GPR),(0xFF00, GPR)},
+  ///                                /*v2*/{(0x00FF, GPR),(0xFF00, GPR)}}
+  ///
+  /// \note The first alternative of the returned mapping should be the
+  /// direct translation of \p MI current form.
+  ///
+  /// \post !returnedVal.empty().
+  InstructionMappings getInstrPossibleMappings(const MachineInstr &MI) const;
+
   void verify(const TargetRegisterInfo &TRI) const;
 };
 
index 6e83079..4c7a74a 100644 (file)
@@ -19,6 +19,7 @@
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetOpcodes.h"
 #include "llvm/Target/TargetRegisterInfo.h"
 
 #include <algorithm> // For std::max.
@@ -27,6 +28,8 @@
 
 using namespace llvm;
 
+const unsigned RegisterBankInfo::DefaultMappingID = UINT_MAX;
+
 RegisterBankInfo::RegisterBankInfo(unsigned NumRegBanks)
     : NumRegBanks(NumRegBanks) {
   RegBanks.reset(new RegisterBank[NumRegBanks]);
@@ -176,6 +179,36 @@ void RegisterBankInfo::addRegBankCoverage(unsigned ID, unsigned RCId,
   } while (!WorkList.empty());
 }
 
+RegisterBankInfo::InstructionMapping
+RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
+  if (MI.getOpcode() > TargetOpcode::GENERIC_OP_END) {
+    // TODO.
+  }
+  llvm_unreachable("The target must implement this");
+}
+
+RegisterBankInfo::InstructionMappings
+RegisterBankInfo::getInstrPossibleMappings(const MachineInstr &MI) const {
+  InstructionMappings PossibleMappings;
+  // Put the default mapping first.
+  PossibleMappings.push_back(getInstrMapping(MI));
+  // Then the alternative mapping, if any.
+  InstructionMappings AltMappings = getInstrAlternativeMappings(MI);
+  for (InstructionMapping &AltMapping : AltMappings)
+    PossibleMappings.emplace_back(std::move(AltMapping));
+#ifndef NDEBUG
+  for (const InstructionMapping &Mapping : PossibleMappings)
+    Mapping.verify(MI);
+#endif
+  return PossibleMappings;
+}
+
+RegisterBankInfo::InstructionMappings
+RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
+  // No alternative for MI.
+  return InstructionMappings();
+}
+
 //------------------------------------------------------------------------------
 // Helper classes implementation.
 //------------------------------------------------------------------------------