diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-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/InstructionSelect.cpp | 99 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/CodeGen/LLVMTargetMachine.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/CodeGen/MachineRegisterInfo.cpp | 14 |
7 files changed, 192 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt index 0d18ef63b8f..bad5c03e566 100644 --- a/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt +++ b/llvm/lib/CodeGen/GlobalISel/CMakeLists.txt @@ -1,6 +1,8 @@ # List of all GlobalISel files. set(GLOBAL_ISEL_FILES IRTranslator.cpp + InstructionSelect.cpp + InstructionSelector.cpp MachineIRBuilder.cpp MachineLegalizeHelper.cpp MachineLegalizePass.cpp diff --git a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp index c0ea873bcfe..aac29f595e2 100644 --- a/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp +++ b/llvm/lib/CodeGen/GlobalISel/GlobalISel.cpp @@ -27,5 +27,6 @@ void llvm::initializeGlobalISel(PassRegistry &Registry) { initializeIRTranslatorPass(Registry); initializeMachineLegalizePassPass(Registry); initializeRegBankSelectPass(Registry); + initializeInstructionSelectPass(Registry); } #endif // LLVM_BUILD_GLOBAL_ISEL diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp new file mode 100644 index 00000000000..3279d13ed76 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelect.cpp @@ -0,0 +1,99 @@ +//===- llvm/CodeGen/GlobalISel/InstructionSelect.cpp - InstructionSelect ---==// +// +// 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 InstructionSelect class. +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" +#include "llvm/ADT/PostOrderIterator.h" +#include "llvm/ADT/Twine.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/Function.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Target/TargetSubtargetInfo.h" + +#define DEBUG_TYPE "instruction-select" + +using namespace llvm; + +char InstructionSelect::ID = 0; +INITIALIZE_PASS(InstructionSelect, DEBUG_TYPE, + "Select target instructions out of generic instructions", + false, false); + +InstructionSelect::InstructionSelect() : MachineFunctionPass(ID) { + initializeInstructionSelectPass(*PassRegistry::getPassRegistry()); +} + +static void reportSelectionError(const MachineInstr &MI, const Twine &Message) { + const MachineFunction &MF = *MI.getParent()->getParent(); + std::string ErrStorage; + raw_string_ostream Err(ErrStorage); + Err << Message << ":\nIn function: " << MF.getName() << '\n' << MI << '\n'; + report_fatal_error(Err.str()); +} + +bool InstructionSelect::runOnMachineFunction(MachineFunction &MF) { + DEBUG(dbgs() << "Selecting function: " << MF.getName() << '\n'); + + const InstructionSelector *ISel = MF.getSubtarget().getInstructionSelector(); + assert(ISel && "Cannot work without InstructionSelector"); + + // FIXME: freezeReservedRegs is now done in IRTranslator, but there are many + // other MF/MFI fields we need to initialize. + +#ifndef NDEBUG + // FIXME: We could introduce new blocks and will need to fix the outer loop. + // Until then, keep track of the number of blocks to assert that we don't. + const size_t NumBlocks = MF.size(); +#endif + + for (MachineBasicBlock *MBB : post_order(&MF)) { + for (MachineBasicBlock::reverse_iterator MII = MBB->rbegin(), + End = MBB->rend(); + MII != End;) { + MachineInstr &MI = *MII++; + DEBUG(dbgs() << "Selecting: " << MI << '\n'); + if (!ISel->select(MI)) + reportSelectionError(MI, "Cannot select"); + // FIXME: It would be nice to dump all inserted instructions. It's not + // obvious how, esp. considering select() can insert after MI. + } + } + + assert(MF.size() == NumBlocks && "Inserting blocks is not supported yet"); + + // Check that we did select everything. Do this separately to make sure we + // didn't miss any newly inserted instructions. + // FIXME: This (and other checks) should move into a verifier, predicated on + // a "post-isel" MachineFunction property. That would also let us selectively + // enable it depending on build configuration. + for (MachineBasicBlock &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (isPreISelGenericOpcode(MI.getOpcode())) { + reportSelectionError( + MI, "Generic instruction survived instruction selection"); + } + } + } + + // Now that selection is complete, there are no more generic vregs. + // FIXME: We're still discussing what to do with the vreg->size map: + // it's somewhat redundant (with the def MIs type size), but having to + // examine MIs is also awkward. Another alternative is to track the type on + // the vreg instead, but that's not ideal either, because it's saying that + // vregs have types, which they really don't. But then again, LLT is just + // a size and a "shape": it's probably the same information as regbank info. + MF.getRegInfo().clearVirtRegSizes(); + + // FIXME: Should we accurately track changes? + return true; +} diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp new file mode 100644 index 00000000000..07a4b3d7170 --- /dev/null +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -0,0 +1,52 @@ +//===- llvm/CodeGen/GlobalISel/InstructionSelector.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 InstructionSelector class. +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetRegisterInfo.h" + +#define DEBUG_TYPE "instructionselector" + +using namespace llvm; + +InstructionSelector::InstructionSelector() {} + +bool InstructionSelector::constrainSelectedInstRegOperands( + MachineInstr &I, const TargetInstrInfo &TII, const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI) const { + MachineBasicBlock &MBB = *I.getParent(); + MachineFunction &MF = *MBB.getParent(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + + for (unsigned OpI = 0, OpE = I.getNumExplicitOperands(); OpI != OpE; ++OpI) { + MachineOperand &MO = I.getOperand(OpI); + DEBUG(dbgs() << "Converting operand: " << MO << '\n'); + + assert(MO.isReg() && "Unsupported binop non-reg operand"); + + const TargetRegisterClass *RC = TII.getRegClass(I.getDesc(), OpI, &TRI, MF); + assert(RC && "Selected inst should have regclass operand"); + + // If the operand is a vreg, we should constrain its regclass, and only + // insert COPYs if that's impossible. + // If the operand is a physreg, we only insert COPYs if the register class + // doesn't contain the register. + if (RBI.constrainGenericRegister(MO.getReg(), *RC, MRI)) + continue; + + DEBUG(dbgs() << "Constraining with COPYs isn't implemented yet"); + return false; + } + return true; +} diff --git a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp index 1148f5ce6f9..5e5541799c5 100644 --- a/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp +++ b/llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp @@ -189,6 +189,25 @@ const RegisterBank *RegisterBankInfo::getRegBankFromConstraints( return &RegBank; } +const TargetRegisterClass *RegisterBankInfo::constrainGenericRegister( + unsigned Reg, const TargetRegisterClass &RC, MachineRegisterInfo &MRI) { + + // If the register already has a class, fallback to MRI::constrainRegClass. + auto &RegClassOrBank = MRI.getRegClassOrRegBank(Reg); + if (RegClassOrBank.is<const TargetRegisterClass *>()) + return MRI.constrainRegClass(Reg, &RC); + + const RegisterBank *RB = RegClassOrBank.get<const RegisterBank *>(); + assert(RB && "Generic register does not have a register bank"); + + // Otherwise, all we can do is ensure the bank covers the class, and set it. + if (!RB->covers(RC)) + return nullptr; + + MRI.setRegClass(Reg, &RC); + return &RC; +} + RegisterBankInfo::InstructionMapping RegisterBankInfo::getInstrMappingImpl(const MachineInstr &MI) const { RegisterBankInfo::InstructionMapping Mapping(DefaultMappingID, /*Cost*/ 1, diff --git a/llvm/lib/CodeGen/LLVMTargetMachine.cpp b/llvm/lib/CodeGen/LLVMTargetMachine.cpp index 121e0371180..9ed61c6685b 100644 --- a/llvm/lib/CodeGen/LLVMTargetMachine.cpp +++ b/llvm/lib/CodeGen/LLVMTargetMachine.cpp @@ -177,6 +177,11 @@ addPassesToGenerateCode(LLVMTargetMachine *TM, PassManagerBase &PM, if (PassConfig->addRegBankSelect()) return nullptr; + PassConfig->addPreGlobalInstructionSelect(); + + if (PassConfig->addGlobalInstructionSelect()) + return nullptr; + } else if (PassConfig->addInstSelector()) return nullptr; diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp index 96786552e9b..886de80a271 100644 --- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp +++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp @@ -136,6 +136,20 @@ MachineRegisterInfo::createGenericVirtualRegister(unsigned Size) { return Reg; } +void MachineRegisterInfo::clearVirtRegSizes() { +#ifndef NDEBUG + // Verify that the size of the now-constrained vreg is unchanged. + for (auto &VRegToSize : getVRegToSize()) { + auto *RC = getRegClass(VRegToSize.first); + if (VRegToSize.second != (RC->getSize() * 8)) + llvm_unreachable( + "Virtual register has explicit size different from its class size"); + } +#endif + + getVRegToSize().clear(); +} + /// clearVirtRegs - Remove all virtual registers (after physreg assignment). void MachineRegisterInfo::clearVirtRegs() { #ifndef NDEBUG |