[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