Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GlobalISel] Introduce an instruction selector.
And implement it for AArch64, supporting x/w ADD/OR. Differential Revision: https://reviews.llvm.org/D22373 llvm-svn: 276875
- Loading branch information
1 parent
5e402ee
commit 6756a2c
Showing
23 changed files
with
683 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
//== llvm/CodeGen/GlobalISel/InstructionSelect.h -----------------*- 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 describes the interface of the MachineFunctionPass | ||
/// responsible for selecting (possibly generic) machine instructions to | ||
/// target-specific instructions. | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECT_H | ||
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECT_H | ||
|
||
#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" | ||
#include "llvm/CodeGen/MachineFunctionPass.h" | ||
|
||
namespace llvm { | ||
/// This pass is responsible for selecting generic machine instructions to | ||
/// target-specific instructions. It relies on the InstructionSelector provided | ||
/// by the target. | ||
/// Selection is done by examining blocks in post-order, and instructions in | ||
/// reverse order. | ||
/// | ||
/// \post for all inst in MF: not isPreISelGenericOpcode(inst.opcode) | ||
class InstructionSelect : public MachineFunctionPass { | ||
public: | ||
static char ID; | ||
const char *getPassName() const override { return "InstructionSelect"; } | ||
|
||
InstructionSelect(); | ||
|
||
bool runOnMachineFunction(MachineFunction &MF) override; | ||
}; | ||
} // End namespace llvm. | ||
|
||
#endif |
63 changes: 63 additions & 0 deletions
63
llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
//==-- llvm/CodeGen/GlobalISel/InstructionSelector.h -------------*- 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 API for the instruction selector. | ||
/// This class is responsible for selecting machine instructions. | ||
/// It's implemented by the target. It's used by the InstructionSelect pass. | ||
// | ||
//===----------------------------------------------------------------------===// | ||
|
||
#ifndef LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H | ||
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTOR_H | ||
|
||
namespace llvm { | ||
class MachineInstr; | ||
class RegisterBankInfo; | ||
class TargetInstrInfo; | ||
class TargetRegisterInfo; | ||
|
||
/// Provides the logic to select generic machine instructions. | ||
class InstructionSelector { | ||
public: | ||
virtual ~InstructionSelector() {} | ||
|
||
/// Select the (possibly generic) instruction \p I to only use target-specific | ||
/// opcodes. It is OK to insert multiple instructions, but they cannot be | ||
/// generic pre-isel instructions. | ||
/// | ||
/// \returns whether selection succeeded. | ||
/// \pre I.getParent() && I.getParent()->getParent() | ||
/// \post | ||
/// if returns true: | ||
/// for I in all mutated/inserted instructions: | ||
/// !isPreISelGenericOpcode(I.getOpcode()) | ||
/// | ||
virtual bool select(MachineInstr &I) const = 0; | ||
|
||
protected: | ||
InstructionSelector(); | ||
|
||
/// Mutate the newly-selected instruction \p I to constrain its (possibly | ||
/// generic) virtual register operands to the instruction's register class. | ||
/// This could involve inserting COPYs before (for uses) or after (for defs). | ||
/// This requires the number of operands to match the instruction description. | ||
/// \returns whether operand regclass constraining succeeded. | ||
/// | ||
// FIXME: Not all instructions have the same number of operands. We should | ||
// probably expose a constrain helper per operand and let the target selector | ||
// constrain individual registers, like fast-isel. | ||
bool constrainSelectedInstRegOperands(MachineInstr &I, | ||
const TargetInstrInfo &TII, | ||
const TargetRegisterInfo &TRI, | ||
const RegisterBankInfo &RBI) const; | ||
}; | ||
|
||
} // End namespace llvm. | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.