summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/CMakeLists.txt2
-rw-r--r--llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp1
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp32
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineLegalizeHelper.cpp98
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineLegalizePass.cpp72
-rw-r--r--llvm/lib/CodeGen/GlobalISel/MachineLegalizer.cpp9
-rw-r--r--llvm/lib/CodeGen/LLVMTargetMachine.cpp5
-rw-r--r--llvm/lib/Target/AArch64/AArch64MachineLegalizer.cpp30
-rw-r--r--llvm/lib/Target/AArch64/AArch64MachineLegalizer.h30
-rw-r--r--llvm/lib/Target/AArch64/AArch64Subtarget.cpp5
-rw-r--r--llvm/lib/Target/AArch64/AArch64Subtarget.h1
-rw-r--r--llvm/lib/Target/AArch64/AArch64TargetMachine.cpp12
-rw-r--r--llvm/lib/Target/AArch64/CMakeLists.txt1
-rw-r--r--llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp5
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;
}
OpenPOWER on IntegriCloud