forked from OSchip/llvm-project
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. llvm-svn: 276461
This commit is contained in:
parent
e4a4f33daf
commit
33b07d6725
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
||||
|
|
|
@ -217,6 +217,14 @@ public:
|
|||
/// LLVM code to machine instructions with possibly generic opcodes.
|
||||
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() {}
|
||||
|
|
|
@ -214,6 +214,7 @@ void initializeMachineCopyPropagationPass(PassRegistry&);
|
|||
void initializeMachineDominanceFrontierPass(PassRegistry&);
|
||||
void initializeMachineDominatorTreePass(PassRegistry&);
|
||||
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
|
||||
void initializeMachineLegalizePassPass(PassRegistry&);
|
||||
void initializeMachineLICMPass(PassRegistry&);
|
||||
void initializeMachineLoopInfoPass(PassRegistry&);
|
||||
void initializeMachineModuleInfoPass(PassRegistry&);
|
||||
|
|
|
@ -57,6 +57,27 @@ def G_OR : Instruction {
|
|||
let isCommutable = 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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.
|
||||
//------------------------------------------------------------------------------
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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.
|
||||
///
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
set(GLOBAL_ISEL_FILES
|
||||
IRTranslator.cpp
|
||||
MachineIRBuilder.cpp
|
||||
MachineLegalizeHelper.cpp
|
||||
MachineLegalizePass.cpp
|
||||
MachineLegalizer.cpp
|
||||
RegBankSelect.cpp
|
||||
RegisterBank.cpp
|
||||
|
|
|
@ -25,6 +25,7 @@ void llvm::initializeGlobalISel(PassRegistry &Registry) {
|
|||
|
||||
void llvm::initializeGlobalISel(PassRegistry &Registry) {
|
||||
initializeIRTranslatorPass(Registry);
|
||||
initializeMachineLegalizePassPass(Registry);
|
||||
initializeRegBankSelectPass(Registry);
|
||||
}
|
||||
#endif // LLVM_BUILD_GLOBAL_ISEL
|
||||
|
|
|
@ -110,3 +110,35 @@ MachineInstr *MachineIRBuilder::buildFrameIndex(LLT Ty, unsigned Res, int Idx) {
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -28,10 +28,6 @@ MachineLegalizer::MachineLegalizer() : TablesInitialized(false) {
|
|||
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 Opcode, LLT Ty) const {
|
|||
// 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);
|
||||
|
|
|
@ -165,6 +165,11 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM,
|
|||
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();
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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
|
|
@ -98,6 +98,11 @@ const CallLowering *AArch64Subtarget::getCallLowering() const {
|
|||
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();
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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::~AArch64TargetMachine() {}
|
|||
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(const Function &F) const {
|
|||
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;
|
||||
|
|
|
@ -19,6 +19,7 @@ add_public_tablegen_target(AArch64CommonTableGen)
|
|||
# List of all GlobalISel files.
|
||||
set(GLOBAL_ISEL_FILES
|
||||
AArch64CallLowering.cpp
|
||||
AArch64MachineLegalizer.cpp
|
||||
AArch64RegisterBankInfo.cpp
|
||||
)
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
...
|
Loading…
Reference in New Issue