[GlobalISel] Teach the IRTranslator how to lower returns.
authorQuentin Colombet <qcolombet@apple.com>
Thu, 11 Feb 2016 18:53:28 +0000 (18:53 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Thu, 11 Feb 2016 18:53:28 +0000 (18:53 +0000)
llvm-svn: 260562

llvm/include/llvm/CodeGen/GlobalISel/IRTranslator.h
llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
llvm/include/llvm/Target/TargetLowering.h
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
llvm/lib/CodeGen/GlobalISel/MachineIRBuilder.cpp

index a515fbb..bc74513 100644 (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
index 7988729..3450835 100644 (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.
index eb64052..857e59a 100644 (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.
   ///
index 193da22..4368f92 100644 (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) {
index 77e73d1..293e8e7 100644 (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;
 }