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:
Tim Northover 2016-07-22 20:03:43 +00:00
parent e4a4f33daf
commit 33b07d6725
25 changed files with 554 additions and 16 deletions

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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() {}

View File

@ -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&);

View File

@ -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.
//------------------------------------------------------------------------------

View File

@ -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)

View File

@ -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.
///

View File

@ -2,6 +2,8 @@
set(GLOBAL_ISEL_FILES
IRTranslator.cpp
MachineIRBuilder.cpp
MachineLegalizeHelper.cpp
MachineLegalizePass.cpp
MachineLegalizer.cpp
RegBankSelect.cpp
RegisterBank.cpp

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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();

View File

@ -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();
}

View File

@ -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

View File

@ -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();

View File

@ -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; }

View File

@ -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;

View File

@ -19,6 +19,7 @@ add_public_tablegen_target(AArch64CommonTableGen)
# List of all GlobalISel files.
set(GLOBAL_ISEL_FILES
AArch64CallLowering.cpp
AArch64MachineLegalizer.cpp
AArch64RegisterBankInfo.cpp
)

View File

@ -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;
}

View File

@ -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
...