diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/CMakeLists.txt | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp | 32 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp | 98 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp | 72 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/CodeGen/LLVMTargetMachine.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp | 30 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64MachineLegalizer.h | 30 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64Subtarget.h | 1 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/AArch64TargetMachine.cpp | 12 | ||||
-rw-r--r-- | llvm/lib/Target/AArch64/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp | 5 |
14 files changed, 299 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index 960f51a842d..0d18ef63b8f 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -2,6 +2,8 @@ set(GLOBAL_ISEL_FILES IRTranslator.cpp MachineIRBuilder.cpp + MachineLegalizeHelper.cpp + MachineLegalizePass.cpp MachineLegalizer.cpp RegBankSelect.cpp RegisterBank.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp index 231e5ac82be..c0ea873bcfe 100644 --- a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GlobalISel.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 diff --git a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp index 220965ce660..2b91584c75d 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp @@ -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; +} diff --git a/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp new file mode 100644 index 00000000000..55adbbd20ce --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp @@ -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; + } + } +} diff --git a/llvm/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp b/llvm/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp new file mode 100644 index 00000000000..4ddc82fc6b7 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp @@ -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; +} diff --git a/llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp b/llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp index edd5ccfd9cd..600f7bc5973 100644 --- a/llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp +++ b/llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp @@ -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); diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 9eb43d2bec1..b18a186c122 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -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(); diff --git a/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp new file mode 100644 index 00000000000..40fda0b2243 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp @@ -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(); +} diff --git a/llvm/lib/Target/AArch64/AArch64MachineLegalizer.h b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.h new file mode 100644 index 00000000000..86708a558a3 --- /dev/null +++ b/llvm/lib/Target/AArch64/AArch64MachineLegalizer.h @@ -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 diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp index 7dd8ccbe6c2..9ec3b164243 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.cpp +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.cpp @@ -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(); diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index 16a35405c89..7083be44bc5 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -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; } diff --git a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp index 145ff573d1b..605fb579d7b 100644 --- a/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetMachine.cpp @@ -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; diff --git a/llvm/lib/Target/AArch64/CMakeLists.txt b/llvm/lib/Target/AArch64/CMakeLists.txt index a79960ea960..9944a068243 100644 --- a/llvm/lib/Target/AArch64/CMakeLists.txt +++ b/llvm/lib/Target/AArch64/CMakeLists.txt @@ -19,6 +19,7 @@ add_public_tablegen_target(AArch64CommonTableGen) # List of all GlobalISel files. set(GLOBAL_ISEL_FILES AArch64CallLowering.cpp + AArch64MachineLegalizer.cpp AArch64RegisterBankInfo.cpp ) diff --git a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp index b2d4e1144c7..9affa2e003d 100644 --- a/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp +++ b/llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.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; } |