[llvm] r276461 - GlobalISel: implement legalization pass, with just one transformation.

Tim Northover via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 22 13:03:44 PDT 2016


Author: tnorthover
Date: Fri Jul 22 15:03:43 2016
New Revision: 276461

URL: http://llvm.org/viewvc/llvm-project?rev=276461&view=rev
Log:
GlobalISel: implement legalization pass, with just one transformation.

This adds the actual MachineLegalizeHelper to do the work and a trivial pass
wrapper that legalizes all instructions in a MachineFunction. Currently the
only transformation supported is splitting up a vector G_ADD into one acting on
smaller vectors.

Added:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp
    llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
    llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.h
    llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
Modified:
    llvm/trunk/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
    llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h
    llvm/trunk/include/llvm/CodeGen/TargetPassConfig.h
    llvm/trunk/include/llvm/InitializePasses.h
    llvm/trunk/include/llvm/Target/GenericOpcodes.td
    llvm/trunk/include/llvm/Target/TargetOpcodes.def
    llvm/trunk/include/llvm/Target/TargetSubtargetInfo.h
    llvm/trunk/lib/CodeGen/GlobalISel/CMakeLists.txt
    llvm/trunk/lib/CodeGen/GlobalISel/GlobalISel.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
    llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp
    llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
    llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp
    llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
    llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
    llvm/trunk/lib/Target/AArch64/CMakeLists.txt
    llvm/trunk/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/GISelAccessor.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/GISelAccessor.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/GISelAccessor.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/GISelAccessor.h Fri Jul 22 15:03:43 2016
@@ -17,6 +17,7 @@
 
 namespace llvm {
 class CallLowering;
+class MachineLegalizer;
 class RegisterBankInfo;
 
 /// The goal of this helper class is to gather the accessor to all
@@ -27,6 +28,9 @@ class RegisterBankInfo;
 struct GISelAccessor {
   virtual ~GISelAccessor() {}
   virtual const CallLowering *getCallLowering() const { return nullptr;}
+  virtual const MachineLegalizer *getMachineLegalizer() const {
+    return nullptr;
+  }
   virtual const RegisterBankInfo *getRegBankInfo() const { return nullptr;}
 };
 } // End namespace llvm;

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h Fri Jul 22 15:03:43 2016
@@ -80,7 +80,7 @@ public:
   /// Set the insertion point to before (\p Before = true) or after
   /// (\p Before = false) \p MI.
   /// \pre MI must be in getMF().
-  void setInstr(MachineInstr &MI, bool Before = false);
+  void setInstr(MachineInstr &MI, bool Before = true);
   /// @}
 
   /// Set the debug location to \p DL for all the next build instructions.
@@ -152,6 +152,37 @@ public:
   /// \return The newly created instruction.
   MachineInstr *buildFrameIndex(LLT Ty, unsigned Res, int Idx);
 
+  /// Build and insert \p Res<def> = G_ADD \p Ty \p Op0, \p Op1
+  ///
+  /// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
+  /// truncated to their width.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return The newly created instruction.
+  MachineInstr *buildAdd(LLT Ty, unsigned Res, unsigned Op0, unsigned Op1);
+
+  /// Build and insert `Res0<def>, ... = G_EXTRACT Ty Src, Idx0, ...`.
+  ///
+  /// If \p Ty has size N bits, G_EXTRACT sets \p Res[0] to bits `[Idxs[0],
+  /// Idxs[0] + N)` of \p Src and similarly for subsequent bit-indexes.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  ///
+  /// \return The newly created instruction.
+  MachineInstr *buildExtract(LLT Ty, ArrayRef<unsigned> Results, unsigned Src,
+                             ArrayRef<unsigned> Indexes);
+
+  /// Build and insert \p Res<def> = G_SEQUENCE \p Ty \p Ops[0], ...
+  ///
+  /// G_SEQUENCE concatenates each element in Ops into a single register, where
+  /// Ops[0] starts at bit 0 of \p Res.
+  ///
+  /// \pre setBasicBlock or setMI must have been called.
+  /// \pre The sum of the input sizes must equal the result's size.
+  ///
+  /// \return The newly created instruction.
+  MachineInstr *buildSequence(LLT Ty, unsigned Res, ArrayRef<unsigned> Ops);
 };
 
 } // End namespace llvm.

Added: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h?rev=276461&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h (added)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h Fri Jul 22 15:03:43 2016
@@ -0,0 +1,92 @@
+//== llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h ----------- -*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file A pass to convert the target-illegal operations created by IR -> MIR
+/// translation into ones the target expects to be able to select. This may
+/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> ->
+/// G_ADD <4 x i16>.
+///
+/// The MachineLegalizeHelper class is where most of the work happens, and is
+/// designed to be callable from other passes that find themselves with an
+/// illegal instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
+#define LLVM_CODEGEN_GLOBALISEL_MACHINELEGALIZEHELPER_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/LowLevelType.h"
+
+namespace llvm {
+// Forward declarations.
+class MachineLegalizeInfo;
+class MachineLegalizer;
+class MachineRegisterInfo;
+
+class MachineLegalizeHelper {
+public:
+  enum LegalizeResult {
+    /// Instruction was already legal and no change was made to the
+    /// MachineFunction.
+    AlreadyLegal,
+
+    /// Instruction has been legalized and the MachineFunction changed.
+    Legalized,
+
+    /// Some kind of error has occurred and we could not legalize this
+    /// instruction.
+    UnableToLegalize,
+  };
+
+  MachineLegalizeHelper(MachineFunction &MF);
+
+  /// Replace \p MI by a sequence of legal instructions that can implement the
+  /// same operation. Note that this means \p MI may be deleted, so any iterator
+  /// steps should be performed before calling this function. \p Helper should
+  /// be initialized to the MachineFunction containing \p MI.
+  ///
+  /// Considered as an opaque blob, the legal code will use and define the same
+  /// registers as \p MI.
+  LegalizeResult legalizeInstr(MachineInstr &MI,
+                               const MachineLegalizer &Legalizer);
+
+  /// Legalize an instruction by reducing the width of the underlying scalar
+  /// type.
+  LegalizeResult narrowScalar(MachineInstr &MI, LLT NarrowTy);
+
+  /// Legalize an instruction by performing the operation on a wider scalar type
+  /// (for example a 16-bit addition can be safely performed at 32-bits
+  /// precision, ignoring the unused bits).
+  LegalizeResult widenScalar(MachineInstr &MI, LLT WideTy);
+
+  /// Legalize a vector instruction by splitting into multiple components, each
+  /// acting on the same scalar type as the original but with fewer elements.
+  LegalizeResult fewerElementsVector(MachineInstr &MI, LLT NarrowTy);
+
+  /// Legalize a vector instruction by increasing the number of vector elements
+  /// involved and ignoring the added elements later.
+  LegalizeResult moreElementsVector(MachineInstr &MI, LLT WideTy);
+
+private:
+
+  /// Helper function to split a wide generic register into bitwise blocks with
+  /// the given Type (which implies the number of blocks needed). The generic
+  /// registers created are appended to Ops, starting at bit 0 of Reg.
+  void extractParts(unsigned Reg, LLT Ty, int NumParts,
+                    SmallVectorImpl<unsigned> &Ops);
+
+  MachineIRBuilder MIRBuilder;
+  MachineRegisterInfo &MRI;
+};
+
+} // End namespace llvm.
+
+#endif

Added: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h?rev=276461&view=auto
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h (added)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizePass.h Fri Jul 22 15:03:43 2016
@@ -0,0 +1,50 @@
+//== llvm/CodeGen/GlobalISel/MachineLegalizePass.h ------------- -*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file A pass to convert the target-illegal operations created by IR -> MIR
+/// translation into ones the target expects to be able to select. This may
+/// occur in multiple phases, for example G_ADD <2 x i8> -> G_ADD <2 x i16> ->
+/// G_ADD <4 x i16>.
+///
+/// The LegalizeHelper class is where most of the work happens, and is designed
+/// to be callable from other passes that find themselves with an illegal
+/// instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_GLOBALISEL_LEGALIZEMACHINEIRPASS_H
+#define LLVM_CODEGEN_GLOBALISEL_LEGALIZEMACHINEIRPASS_H
+
+#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+
+namespace llvm {
+
+class MachineLegalizePass : public MachineFunctionPass {
+public:
+  static char ID;
+
+private:
+
+  /// Initialize the field members using \p MF.
+  void init(MachineFunction &MF);
+
+public:
+  // Ctor, nothing fancy.
+  MachineLegalizePass();
+
+  const char *getPassName() const override {
+    return "MachineLegalizePass";
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+};
+} // End namespace llvm.
+
+#endif

Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/MachineLegalizer.h Fri Jul 22 15:03:43 2016
@@ -71,17 +71,6 @@ public:
 
   MachineLegalizer();
 
-  /// Replace \p MI by a sequence of legal instructions that can implement the
-  /// same operation. Note that this means \p MI may be deleted, so any iterator
-  /// steps should be performed before calling this function.
-  ///
-  /// Considered as an opaque blob, the legal code will use and define the same
-  /// registers as \p MI.
-  ///
-  /// \returns true if the function is modified, false if the instruction was
-  /// already legal.
-  bool legalizeInstr(MachineInstr &MI) const;
-
   /// Compute any ancillary tables needed to quickly decide how an operation
   /// should be handled. This must be called after all "set*Action"methods but
   /// before any query is made or incorrect results may be returned.

Modified: llvm/trunk/include/llvm/CodeGen/TargetPassConfig.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/TargetPassConfig.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/TargetPassConfig.h (original)
+++ llvm/trunk/include/llvm/CodeGen/TargetPassConfig.h Fri Jul 22 15:03:43 2016
@@ -218,6 +218,14 @@ public:
   virtual bool addIRTranslator() { return true; }
 
   /// This method may be implemented by targets that want to run passes
+  /// immediately before legalization.
+  virtual void addPreLegalizeMachineIR() {}
+
+  /// This method should install a legalize pass, which converts the instruction
+  /// sequence into one that can be selected by the target.
+  virtual bool addLegalizeMachineIR() { return true; }
+
+  /// This method may be implemented by targets that want to run passes
   /// immediately before the register bank selection.
   virtual void addPreRegBankSelect() {}
 

Modified: llvm/trunk/include/llvm/InitializePasses.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/InitializePasses.h (original)
+++ llvm/trunk/include/llvm/InitializePasses.h Fri Jul 22 15:03:43 2016
@@ -214,6 +214,7 @@ void initializeMachineCopyPropagationPas
 void initializeMachineDominanceFrontierPass(PassRegistry&);
 void initializeMachineDominatorTreePass(PassRegistry&);
 void initializeMachineFunctionPrinterPassPass(PassRegistry&);
+void initializeMachineLegalizePassPass(PassRegistry&);
 void initializeMachineLICMPass(PassRegistry&);
 void initializeMachineLoopInfoPass(PassRegistry&);
 void initializeMachineModuleInfoPass(PassRegistry&);

Modified: llvm/trunk/include/llvm/Target/GenericOpcodes.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GenericOpcodes.td?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/GenericOpcodes.td (original)
+++ llvm/trunk/include/llvm/Target/GenericOpcodes.td Fri Jul 22 15:03:43 2016
@@ -58,6 +58,27 @@ def G_OR : Instruction {
 }
 
 //------------------------------------------------------------------------------
+// Variadic ops
+//------------------------------------------------------------------------------
+
+// Extract multiple registers specified size, starting from blocks given by
+// indexes. This will almost certainly be mapped to sub-register COPYs after
+// register banks have been selected.
+def G_EXTRACT : Instruction {
+  let OutOperandList = (outs variable_ops);
+  let InOperandList = (ins variable_ops);
+  let hasSideEffects = 0;
+}
+
+// Combine a sequence of generic vregs into a single larger value (starting at
+// bit 0).
+def G_SEQUENCE : Instruction {
+  let OutOperandList = (outs unknown:$dst);
+  let InOperandList = (ins variable_ops);
+  let hasSideEffects = 0;
+}
+
+//------------------------------------------------------------------------------
 // Branches.
 //------------------------------------------------------------------------------
 // Generic unconditional branch.

Modified: llvm/trunk/include/llvm/Target/TargetOpcodes.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOpcodes.def?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetOpcodes.def (original)
+++ llvm/trunk/include/llvm/Target/TargetOpcodes.def Fri Jul 22 15:03:43 2016
@@ -172,6 +172,14 @@ HANDLE_TARGET_OPCODE(G_OR)
 /// stack-based object.
 HANDLE_TARGET_OPCODE(G_FRAME_INDEX)
 
+/// Generic instruction to extract blocks of bits from the register given
+/// (typically a sub-register COPY after instruction selection).
+HANDLE_TARGET_OPCODE(G_EXTRACT)
+
+/// Generic instruction to paste a variable number of components together into a
+/// larger register.
+HANDLE_TARGET_OPCODE(G_SEQUENCE)
+
 /// Generic BRANCH instruction. This is an unconditional branch.
 HANDLE_TARGET_OPCODE(G_BR)
 

Modified: llvm/trunk/include/llvm/Target/TargetSubtargetInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetSubtargetInfo.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/TargetSubtargetInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetSubtargetInfo.h Fri Jul 22 15:03:43 2016
@@ -27,6 +27,7 @@ class CallLowering;
 class DataLayout;
 class MachineFunction;
 class MachineInstr;
+class MachineLegalizer;
 class RegisterBankInfo;
 class SDep;
 class SUnit;
@@ -94,6 +95,10 @@ public:
     return nullptr;
   }
 
+  virtual const MachineLegalizer *getMachineLegalizer() const {
+    return nullptr;
+  }
+
   /// getRegisterInfo - If register information is available, return it.  If
   /// not, return null.
   ///

Modified: llvm/trunk/lib/CodeGen/GlobalISel/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/CMakeLists.txt?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/CMakeLists.txt (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/CMakeLists.txt Fri Jul 22 15:03:43 2016
@@ -2,6 +2,8 @@
 set(GLOBAL_ISEL_FILES
       IRTranslator.cpp
       MachineIRBuilder.cpp
+      MachineLegalizeHelper.cpp
+      MachineLegalizePass.cpp
       MachineLegalizer.cpp
       RegBankSelect.cpp
       RegisterBank.cpp

Modified: llvm/trunk/lib/CodeGen/GlobalISel/GlobalISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/GlobalISel.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/GlobalISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/GlobalISel.cpp Fri Jul 22 15:03:43 2016
@@ -25,6 +25,7 @@ void llvm::initializeGlobalISel(PassRegi
 
 void llvm::initializeGlobalISel(PassRegistry &Registry) {
   initializeIRTranslatorPass(Registry);
+  initializeMachineLegalizePassPass(Registry);
   initializeRegBankSelectPass(Registry);
 }
 #endif // LLVM_BUILD_GLOBAL_ISEL

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp Fri Jul 22 15:03:43 2016
@@ -110,3 +110,35 @@ MachineInstr *MachineIRBuilder::buildFra
   MIB.addImm(Idx);
   return NewMI;
 }
+
+MachineInstr *MachineIRBuilder::buildAdd(LLT Ty, unsigned Res, unsigned Op0,
+                                         unsigned Op1) {
+  return buildInstr(TargetOpcode::G_ADD, Ty, Res, Op0, Op1);
+}
+
+MachineInstr *MachineIRBuilder::buildExtract(LLT Ty, ArrayRef<unsigned> Results,
+                                             unsigned Src,
+                                             ArrayRef<unsigned> Indexes) {
+  assert(Results.size() == Indexes.size() && "inconsistent number of regs");
+
+  MachineInstr *NewMI = buildInstr(TargetOpcode::G_EXTRACT, Ty);
+  auto MIB = MachineInstrBuilder(getMF(), NewMI);
+  for (auto Res : Results)
+    MIB.addReg(Res, RegState::Define);
+
+  MIB.addReg(Src);
+
+  for (auto Idx : Indexes)
+    MIB.addImm(Idx);
+  return NewMI;
+}
+
+MachineInstr *MachineIRBuilder::buildSequence(LLT Ty, unsigned Res,
+                                              ArrayRef<unsigned> Ops) {
+  MachineInstr *NewMI = buildInstr(TargetOpcode::G_SEQUENCE, Ty);
+  auto MIB = MachineInstrBuilder(getMF(), NewMI);
+  MIB.addReg(Res, RegState::Define);
+  for (auto Op : Ops)
+    MIB.addReg(Op);
+  return NewMI;
+}

Added: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp?rev=276461&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp (added)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp Fri Jul 22 15:03:43 2016
@@ -0,0 +1,98 @@
+//===-- llvm/CodeGen/GlobalISel/MachineLegalizeHelper.cpp -----------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file implements the MachineLegalizeHelper class to legalize
+/// individual instructions and the LegalizeMachineIR wrapper pass for the
+/// primary legalization.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h"
+#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+#include <sstream>
+
+#define DEBUG_TYPE "legalize-mir"
+
+using namespace llvm;
+
+MachineLegalizeHelper::MachineLegalizeHelper(MachineFunction &MF)
+  : MRI(MF.getRegInfo()) {
+  MIRBuilder.setMF(MF);
+}
+
+MachineLegalizeHelper::LegalizeResult MachineLegalizeHelper::legalizeInstr(
+    MachineInstr &MI, const MachineLegalizer &Legalizer) {
+  auto Action = Legalizer.getAction(MI);
+  switch (Action.first) {
+  case MachineLegalizer::Legal:
+    return AlreadyLegal;
+  case MachineLegalizer::NarrowScalar:
+    return narrowScalar(MI, Action.second);
+  case MachineLegalizer::WidenScalar:
+    return widenScalar(MI, Action.second);
+  case MachineLegalizer::FewerElements:
+    return fewerElementsVector(MI, Action.second);
+  default:
+    return UnableToLegalize;
+  }
+}
+
+void MachineLegalizeHelper::extractParts(unsigned Reg, LLT Ty, int NumParts,
+                                         SmallVectorImpl<unsigned> &VRegs) {
+  unsigned Size = Ty.getSizeInBits();
+  SmallVector<unsigned, 4> Indexes;
+  for (int i = 0; i < NumParts; ++i) {
+    VRegs.push_back(MRI.createGenericVirtualRegister(Size));
+    Indexes.push_back(i * Size);
+  }
+  MIRBuilder.buildExtract(Ty, VRegs, Reg, Indexes);
+}
+
+MachineLegalizeHelper::LegalizeResult
+MachineLegalizeHelper::narrowScalar(MachineInstr &MI, LLT NarrowTy) {
+  return UnableToLegalize;
+}
+
+MachineLegalizeHelper::LegalizeResult
+MachineLegalizeHelper::widenScalar(MachineInstr &MI, LLT WideTy) {
+  return UnableToLegalize;
+}
+
+MachineLegalizeHelper::LegalizeResult
+MachineLegalizeHelper::fewerElementsVector(MachineInstr &MI, LLT NarrowTy) {
+  switch (MI.getOpcode()) {
+  default:
+    return UnableToLegalize;
+  case TargetOpcode::G_ADD: {
+    unsigned NarrowSize = NarrowTy.getSizeInBits();
+    int NumParts = MI.getType().getSizeInBits() / NarrowSize;
+
+    MIRBuilder.setInstr(MI);
+
+    SmallVector<unsigned, 2> Src1Regs, Src2Regs, DstRegs;
+    extractParts(MI.getOperand(1).getReg(), NarrowTy, NumParts, Src1Regs);
+    extractParts(MI.getOperand(2).getReg(), NarrowTy, NumParts, Src2Regs);
+
+    for (int i = 0; i < NumParts; ++i) {
+      unsigned DstReg = MRI.createGenericVirtualRegister(NarrowSize);
+      MIRBuilder.buildAdd(NarrowTy, DstReg, Src1Regs[i], Src2Regs[i]);
+      DstRegs.push_back(DstReg);
+    }
+
+    MIRBuilder.buildSequence(MI.getType(), MI.getOperand(0).getReg(), DstRegs);
+    MI.eraseFromParent();
+    return Legalized;
+  }
+  }
+}

Added: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp?rev=276461&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp (added)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp Fri Jul 22 15:03:43 2016
@@ -0,0 +1,72 @@
+//===-- llvm/CodeGen/GlobalISel/MachineLegalizePass.cpp -------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file This file implements the LegalizeHelper class to legalize individual
+/// instructions and the MachineLegalizePass wrapper pass for the primary
+/// legalization.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/GlobalISel/MachineLegalizePass.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/GlobalISel/MachineLegalizeHelper.h"
+#include "llvm/CodeGen/GlobalISel/MachineLegalizer.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+
+#define DEBUG_TYPE "legalize-mir"
+
+using namespace llvm;
+
+char MachineLegalizePass::ID = 0;
+INITIALIZE_PASS(MachineLegalizePass, DEBUG_TYPE,
+                "Legalize the Machine IR a function's Machine IR", false,
+                false);
+
+MachineLegalizePass::MachineLegalizePass() : MachineFunctionPass(ID) {
+  initializeMachineLegalizePassPass(*PassRegistry::getPassRegistry());
+}
+
+void MachineLegalizePass::init(MachineFunction &MF) {
+}
+
+bool MachineLegalizePass::runOnMachineFunction(MachineFunction &MF) {
+  DEBUG(dbgs() << "Legalize Machine IR for: " << MF.getName() << '\n');
+  init(MF);
+  const MachineLegalizer &Legalizer = *MF.getSubtarget().getMachineLegalizer();
+  MachineLegalizeHelper Helper(MF);
+
+  // FIXME: an instruction may need more than one pass before it is legal. For
+  // example on most architectures <3 x i3> is doubly-illegal. It would
+  // typically proceed along a path like: <3 x i3> -> <3 x i8> -> <8 x i8>. We
+  // probably want a worklist of instructions rather than naive iterate until
+  // convergence for performance reasons.
+  bool Changed = false;
+  MachineBasicBlock::iterator NextMI;
+  for (auto &MBB : MF)
+    for (auto MI = MBB.begin(); MI != MBB.end(); MI = NextMI) {
+      // Get the next Instruction before we try to legalize, because there's a
+      // good chance MI will be deleted.
+      NextMI = std::next(MI);
+      auto Res = Helper.legalizeInstr(*MI, Legalizer);
+
+      // Error out if we couldn't legalize this instruction. We may want to fall
+      // back to DAG ISel instead in the future.
+      if (Res == MachineLegalizeHelper::UnableToLegalize) {
+        std::string Msg;
+        raw_string_ostream OS(Msg);
+        OS << "unable to legalize instruction: ";
+        MI->print(OS);
+        report_fatal_error(OS.str());
+      }
+
+      Changed |= Res == MachineLegalizeHelper::Legalized;
+    }
+  return Changed;
+}

Modified: llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp (original)
+++ llvm/trunk/lib/CodeGen/GlobalISel/MachineLegalizer.cpp Fri Jul 22 15:03:43 2016
@@ -28,10 +28,6 @@ MachineLegalizer::MachineLegalizer() : T
   DefaultActions[TargetOpcode::G_ADD] = NarrowScalar;
 }
 
-bool MachineLegalizer::legalizeInstr(MachineInstr &MI) const {
-  llvm_unreachable("Unimplemented functionality");
-}
-
 void MachineLegalizer::computeTables() {
   for (auto &Op : Actions) {
     LLT Ty = Op.first.second;
@@ -56,6 +52,11 @@ MachineLegalizer::getAction(unsigned Opc
   // These *have* to be implemented for now, they're the fundamental basis of
   // how everything else is transformed.
 
+  // FIXME: the long-term plan calls for expansion in terms of load/store (if
+  // they're not legal).
+  if (Opcode == TargetOpcode::G_SEQUENCE || Opcode == TargetOpcode::G_EXTRACT)
+    return std::make_pair(Legal, Ty);
+
   auto ActionIt = Actions.find(std::make_pair(Opcode, Ty));
   if (ActionIt != Actions.end())
     return findLegalAction(Opcode, Ty, ActionIt->second);

Modified: llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp (original)
+++ llvm/trunk/lib/CodeGen/LLVMTargetMachine.cpp Fri Jul 22 15:03:43 2016
@@ -165,6 +165,11 @@ addPassesToGenerateCode(LLVMTargetMachin
     if (PassConfig->addIRTranslator())
       return nullptr;
 
+    PassConfig->addPreLegalizeMachineIR();
+
+    if (PassConfig->addLegalizeMachineIR())
+      return nullptr;
+
     // Before running the register bank selector, ask the target if it
     // wants to run some passes.
     PassConfig->addPreRegBankSelect();

Added: llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp?rev=276461&view=auto
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp (added)
+++ llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.cpp Fri Jul 22 15:03:43 2016
@@ -0,0 +1,30 @@
+//===- AArch64MachineLegalizer.cpp -------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file implements the targeting of the Machinelegalizer class for
+/// AArch64.
+/// \todo This should be generated by TableGen.
+//===----------------------------------------------------------------------===//
+
+#include "AArch64MachineLegalizer.h"
+#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/Type.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/Target/TargetOpcodes.h"
+
+using namespace llvm;
+
+#ifndef LLVM_BUILD_GLOBAL_ISEL
+#error "You shouldn't build this"
+#endif
+
+AArch64MachineLegalizer::AArch64MachineLegalizer() {
+  setAction(TargetOpcode::G_ADD, LLT::vector(2, 64), Legal);
+  computeTables();
+}

Added: llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.h?rev=276461&view=auto
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.h (added)
+++ llvm/trunk/lib/Target/AArch64/AArch64MachineLegalizer.h Fri Jul 22 15:03:43 2016
@@ -0,0 +1,30 @@
+//===- AArch64Machinelegalizer --------------------------------*- C++ -*-==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This file declares the targeting of the Machinelegalizer class for
+/// AArch64.
+/// \todo This should be generated by TableGen.
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H
+#define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINELEGALIZER_H
+
+#include "llvm/CodeGen/GlobalISel/Machinelegalizer.h"
+
+namespace llvm {
+
+class LLVMContext;
+
+/// This class provides the information for the target register banks.
+class AArch64MachineLegalizer : public MachineLegalizer {
+public:
+  AArch64MachineLegalizer();
+};
+} // End llvm namespace.
+#endif

Modified: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.cpp Fri Jul 22 15:03:43 2016
@@ -98,6 +98,11 @@ const CallLowering *AArch64Subtarget::ge
   return GISel->getCallLowering();
 }
 
+const MachineLegalizer *AArch64Subtarget::getMachineLegalizer() const {
+  assert(GISel && "Access to GlobalISel APIs not set");
+  return GISel->getMachineLegalizer();
+}
+
 const RegisterBankInfo *AArch64Subtarget::getRegBankInfo() const {
   assert(GISel && "Access to GlobalISel APIs not set");
   return GISel->getRegBankInfo();

Modified: llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64Subtarget.h Fri Jul 22 15:03:43 2016
@@ -147,6 +147,7 @@ public:
     return &getInstrInfo()->getRegisterInfo();
   }
   const CallLowering *getCallLowering() const override;
+  const MachineLegalizer *getMachineLegalizer() const override;
   const RegisterBankInfo *getRegBankInfo() const override;
   const Triple &getTargetTriple() const { return TargetTriple; }
   bool enableMachineScheduler() const override { return true; }

Modified: llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64TargetMachine.cpp Fri Jul 22 15:03:43 2016
@@ -12,11 +12,13 @@
 
 #include "AArch64.h"
 #include "AArch64CallLowering.h"
+#include "AArch64MachineLegalizer.h"
 #include "AArch64RegisterBankInfo.h"
 #include "AArch64TargetMachine.h"
 #include "AArch64TargetObjectFile.h"
 #include "AArch64TargetTransformInfo.h"
 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
+#include "llvm/CodeGen/GlobalISel/MachineLegalizePass.h"
 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/RegAllocRegistry.h"
@@ -196,10 +198,14 @@ AArch64TargetMachine::~AArch64TargetMach
 namespace {
 struct AArch64GISelActualAccessor : public GISelAccessor {
   std::unique_ptr<CallLowering> CallLoweringInfo;
+  std::unique_ptr<MachineLegalizer> MachineLegalizer;
   std::unique_ptr<RegisterBankInfo> RegBankInfo;
   const CallLowering *getCallLowering() const override {
     return CallLoweringInfo.get();
   }
+  const class MachineLegalizer *getMachineLegalizer() const override {
+    return MachineLegalizer.get();
+  }
   const RegisterBankInfo *getRegBankInfo() const override {
     return RegBankInfo.get();
   }
@@ -234,6 +240,7 @@ AArch64TargetMachine::getSubtargetImpl(c
         new AArch64GISelActualAccessor();
     GISel->CallLoweringInfo.reset(
         new AArch64CallLowering(*I->getTargetLowering()));
+    GISel->MachineLegalizer.reset(new AArch64MachineLegalizer());
     GISel->RegBankInfo.reset(
         new AArch64RegisterBankInfo(*I->getRegisterInfo()));
 #endif
@@ -277,6 +284,7 @@ public:
   bool addInstSelector() override;
 #ifdef LLVM_BUILD_GLOBAL_ISEL
   bool addIRTranslator() override;
+  bool addLegalizeMachineIR() override;
   bool addRegBankSelect() override;
 #endif
   bool addILPOpts() override;
@@ -375,6 +383,10 @@ bool AArch64PassConfig::addIRTranslator(
   addPass(new IRTranslator());
   return false;
 }
+bool AArch64PassConfig::addLegalizeMachineIR() {
+  addPass(new MachineLegalizePass());
+  return false;
+}
 bool AArch64PassConfig::addRegBankSelect() {
   addPass(new RegBankSelect());
   return false;

Modified: llvm/trunk/lib/Target/AArch64/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/CMakeLists.txt?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/CMakeLists.txt (original)
+++ llvm/trunk/lib/Target/AArch64/CMakeLists.txt Fri Jul 22 15:03:43 2016
@@ -19,6 +19,7 @@ add_public_tablegen_target(AArch64Common
 # List of all GlobalISel files.
 set(GLOBAL_ISEL_FILES
       AArch64CallLowering.cpp
+      AArch64MachineLegalizer.cpp
       AArch64RegisterBankInfo.cpp
       )
 

Modified: llvm/trunk/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp?rev=276461&r1=276460&r2=276461&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp (original)
+++ llvm/trunk/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp Fri Jul 22 15:03:43 2016
@@ -315,6 +315,7 @@ public:
   bool addInstSelector() override;
 #ifdef LLVM_BUILD_GLOBAL_ISEL
   bool addIRTranslator() override;
+  bool addLegalizeMachineIR() override;
   bool addRegBankSelect() override;
 #endif
   void addFastRegAlloc(FunctionPass *RegAllocPass) override;
@@ -520,6 +521,10 @@ bool GCNPassConfig::addIRTranslator() {
   return false;
 }
 
+bool GCNPassConfig::addLegalizeMachineIR() {
+  return false;
+}
+
 bool GCNPassConfig::addRegBankSelect() {
   return false;
 }

Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir?rev=276461&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/legalize-add.mir Fri Jul 22 15:03:43 2016
@@ -0,0 +1,34 @@
+# RUN: llc -O0 -run-pass=legalize-mir -global-isel %s -o - 2>&1 | FileCheck %s
+# REQUIRES: global-isel
+
+--- |
+  target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+  target triple = "aarch64-apple-ios"
+  define void @test_vector_add() {
+  entry:
+    ret void
+  }
+...
+
+---
+name:            test_vector_add
+isSSA:           true
+registers:
+  - { id: 0, class: _ }
+  - { id: 1, class: _ }
+  - { id: 2, class: _ }
+body: |
+  bb.0.entry:
+    liveins: %q0, %q1, %q2, %q3
+    ; CHECK-LABEL: name: test_vector_add
+    ; CHECK-DAG: [[LHS_LO:%.*]](128), [[LHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %0, 0, 128
+    ; CHECK-DAG: [[RHS_LO:%.*]](128), [[RHS_HI:%.*]](128) = G_EXTRACT <2 x s64> %1, 0, 128
+    ; CHECK: [[RES_LO:%.*]](128) = G_ADD <2 x s64> [[LHS_LO]], [[RHS_LO]]
+    ; CHECK: [[RES_HI:%.*]](128) = G_ADD <2 x s64> [[LHS_HI]], [[RHS_HI]]
+    ; CHECK: %2(256) = G_SEQUENCE <4 x s64> [[RES_LO]], [[RES_HI]]
+
+    %0(256) = G_SEQUENCE <4 x s64> %q0, %q1
+    %1(256) = G_SEQUENCE <4 x s64> %q2, %q3
+    %2(256) = G_ADD <4 x s64> %0, %1
+    %q0, %q1 = G_EXTRACT <2 x s64> %2, 0, 128
+...




More information about the llvm-commits mailing list