[GlobalISel] Teach the IRTranslator how to lower returns.

llvm-svn: 260562
This commit is contained in:
Quentin Colombet 2016-02-11 18:53:28 +00:00
parent d077c29c80
commit 74d7d2f00b
5 changed files with 87 additions and 7 deletions

View File

@ -34,6 +34,7 @@ class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
class MachineRegisterInfo;
class TargetLowering;
// Technically the pass should run on an hypothetical MachineModule,
// since it should translate Global into some sort of MachineGlobal.
@ -49,7 +50,7 @@ public:
private:
// Interface used to lower the everything related to calls.
// TargetLowering *CallLowering;
const TargetLowering *TLI;
// Mapping of the values of the current LLVM IR function
// to the related virtual registers.
// We need several virtual registers for the lowering of things
@ -92,6 +93,8 @@ private:
// 3. Create the generic instruction.
bool translateADD(const Instruction &Inst);
bool translateReturn(const Instruction &Inst);
// Builder for machine instruction a la IRBuilder.
// I.e., compared to regular MIBuilder, this one also inserts the instruction
// in the current block, it can creates block, etc., basically a kind of

View File

@ -84,13 +84,41 @@ public:
/// Set the debug location to \p DL for all the next build instructions.
void setDebugLoc(const DebugLoc &DL) { this->DL = DL; }
/// Build and insert \p Res<def> = \p Opcode [\p Ty] \p Op0, \p Op1.
/// \p Ty is the type of the instruction if \p Opcode describes
/// a generic machine instruction. \p Ty must be nullptr if \p Opcode
/// does not describe a generic instruction.
/// The insertion point is the one set by the last call of either
/// setBasicBlock or setMI.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstr *buildInstr(unsigned Opcode, Type *Ty, unsigned Res,
unsigned Op0, unsigned Op1);
/// Build and insert \p Res<def> = \p Opcode \p Op0, \p Op1.
/// I.e., instruction with a non-generic opcode.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0,
unsigned Op1);
/// Build and insert \p Res<def> = \p Opcode \p Op0.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstr *buildInstr(unsigned Opcode, unsigned Res, unsigned Op0);
/// Build and insert = \p Opcode.
///
/// \pre setBasicBlock or setMI must have been called.
///
/// \return The newly created instruction.
MachineInstr *buildInstr(unsigned Opcode);
};
} // End namespace llvm.

View File

@ -25,6 +25,9 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/DAGCombine.h"
#ifdef LLVM_BUILD_GLOBAL_ISEL
#include "llvm/CodeGen/GlobalISel/Types.h"
#endif
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/Attributes.h"
@ -50,6 +53,9 @@ namespace llvm {
class MachineBasicBlock;
class MachineFunction;
class MachineInstr;
#ifdef LLVM_BUILD_GLOBAL_ISEL
class MachineIRBuilder;
#endif
class MachineJumpTableInfo;
class MachineLoop;
class Mangler;
@ -2506,6 +2512,13 @@ public:
llvm_unreachable("Not Implemented");
}
#ifdef LLVM_BUILD_GLOBAL_ISEL
virtual bool LowerReturn(MachineIRBuilder &MIRBuilder, const Value *Val,
unsigned VReg) const {
return false;
}
#endif
/// Return true if result of the specified node is used by a return node
/// only. It also compute and return the input chain for the tail call.
///

View File

@ -18,6 +18,7 @@
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/Target/TargetLowering.h"
#define DEBUG_TYPE "irtranslator"
@ -65,18 +66,30 @@ bool IRTranslator::translateADD(const Instruction &Inst) {
unsigned Op0 = *getOrCreateVRegs(Inst.getOperand(0)).begin();
unsigned Op1 = *getOrCreateVRegs(Inst.getOperand(1)).begin();
unsigned Res = *getOrCreateVRegs(&Inst).begin();
MIRBuilder.buildInstr(TargetOpcode::G_ADD, Res, Op0, Op1);
MIRBuilder.buildInstr(TargetOpcode::G_ADD, Inst.getType(), Res, Op0, Op1);
return true;
}
bool IRTranslator::translateReturn(const Instruction &Inst) {
assert(isa<ReturnInst>(Inst) && "Return expected");
const Value *Ret = cast<ReturnInst>(Inst).getReturnValue();
// The target may mess up with the insertion point, but
// this is not important as a return is the last instruction
// of the block anyway.
return TLI->LowerReturn(MIRBuilder, Ret,
!Ret ? 0 : *getOrCreateVRegs(Ret).begin());
}
bool IRTranslator::translate(const Instruction &Inst) {
MIRBuilder.setDebugLoc(Inst.getDebugLoc());
switch(Inst.getOpcode()) {
case Instruction::Add: {
return translateADD(Inst);
default:
llvm_unreachable("Opcode not supported");
}
case Instruction::Add:
return translateADD(Inst);
case Instruction::Ret:
return translateReturn(Inst);
default:
llvm_unreachable("Opcode not supported");
}
}
@ -90,6 +103,7 @@ void IRTranslator::finalize() {
bool IRTranslator::runOnMachineFunction(MachineFunction &MF) {
const Function &F = *MF.getFunction();
TLI = MF.getSubtarget().getTargetLowering();
MIRBuilder.setFunction(MF);
MRI = &MF.getRegInfo();
for (const BasicBlock &BB: F) {

View File

@ -54,8 +54,30 @@ MachineBasicBlock::iterator MachineIRBuilder::getInsertPt() {
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, unsigned Res,
unsigned Op0, unsigned Op1) {
return buildInstr(Opcode, nullptr, Res, Op0, Op1);
}
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, Type *Ty,
unsigned Res, unsigned Op0,
unsigned Op1) {
MachineInstr *NewMI =
BuildMI(getMF(), DL, getTII().get(Opcode), Res).addReg(Op0).addReg(Op1);
if (Ty)
NewMI->setType(Ty);
getMBB().insert(getInsertPt(), NewMI);
return NewMI;
}
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode, unsigned Res,
unsigned Op0) {
MachineInstr *NewMI =
BuildMI(getMF(), DL, getTII().get(Opcode), Res).addReg(Op0);
getMBB().insert(getInsertPt(), NewMI);
return NewMI;
}
MachineInstr *MachineIRBuilder::buildInstr(unsigned Opcode) {
MachineInstr *NewMI = BuildMI(getMF(), DL, getTII().get(Opcode));
getMBB().insert(getInsertPt(), NewMI);
return NewMI;
}