[ARM] GlobalISel: Use TableGen instruction selector
authorDiana Picus <diana.picus@linaro.org>
Tue, 2 May 2017 09:40:49 +0000 (09:40 +0000)
committerDiana Picus <diana.picus@linaro.org>
Tue, 2 May 2017 09:40:49 +0000 (09:40 +0000)
Emit and use the TableGen instruction selector for ARM. At the moment,
this allows us to remove the hand-written code for selecting G_SDIV and
G_UDIV.

Future commits will focus on increasing the code coverage for it and
removing more dead code from the current instruction selector.

llvm-svn: 301905

llvm/lib/Target/ARM/ARM.h
llvm/lib/Target/ARM/ARMInstrInfo.td
llvm/lib/Target/ARM/ARMInstructionSelector.cpp
llvm/lib/Target/ARM/ARMTargetMachine.cpp
llvm/lib/Target/ARM/CMakeLists.txt
llvm/utils/TableGen/GlobalISelEmitter.cpp

index 8d136ed..4676226 100644 (file)
@@ -47,7 +47,7 @@ FunctionPass *createARMOptimizeBarriersPass();
 FunctionPass *createThumb2SizeReductionPass(
     std::function<bool(const Function &)> Ftor = nullptr);
 InstructionSelector *
-createARMInstructionSelector(const ARMSubtarget &STI,
+createARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
                              const ARMRegisterBankInfo &RBI);
 
 void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
index 9d8ee5c..28eb5fc 100644 (file)
@@ -317,8 +317,10 @@ def UseNegativeImmediates :
                                "NegativeImmediates">;
 
 // FIXME: Eventually this will be just "hasV6T2Ops".
-def UseMovt          : Predicate<"Subtarget->useMovt(*MF)">;
-def DontUseMovt      : Predicate<"!Subtarget->useMovt(*MF)">;
+let RecomputePerFunction = 1 in {
+  def UseMovt          : Predicate<"Subtarget->useMovt(*MF)">;
+  def DontUseMovt      : Predicate<"!Subtarget->useMovt(*MF)">;
+}
 def UseFPVMLx        : Predicate<"Subtarget->useFPVMLx()">;
 def UseMulOps        : Predicate<"Subtarget->useMulOps()">;
 
@@ -345,8 +347,10 @@ def UseVMOVSR : Predicate<"Subtarget->preferVMOVSR() ||"
 def DontUseVMOVSR : Predicate<"!Subtarget->preferVMOVSR() &&"
                               "Subtarget->useNEONForSinglePrecisionFP()">;
 
-def IsLE             : Predicate<"MF->getDataLayout().isLittleEndian()">;
-def IsBE             : Predicate<"MF->getDataLayout().isBigEndian()">;
+let RecomputePerFunction = 1 in {
+  def IsLE             : Predicate<"MF->getDataLayout().isLittleEndian()">;
+  def IsBE             : Predicate<"MF->getDataLayout().isBigEndian()">;
+}
 
 def GenExecuteOnly : Predicate<"Subtarget->genExecuteOnly()">;
 
index 8ce8e32..2ac3fda 100644 (file)
@@ -27,32 +27,67 @@ using namespace llvm;
 #endif
 
 namespace {
+
+#define GET_GLOBALISEL_PREDICATE_BITSET
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATE_BITSET
+
 class ARMInstructionSelector : public InstructionSelector {
 public:
-  ARMInstructionSelector(const ARMSubtarget &STI,
+  ARMInstructionSelector(const ARMBaseTargetMachine &TM, const ARMSubtarget &STI,
                          const ARMRegisterBankInfo &RBI);
 
   bool select(MachineInstr &I) const override;
 
 private:
+  bool selectImpl(MachineInstr &I) const;
+
   const ARMBaseInstrInfo &TII;
   const ARMBaseRegisterInfo &TRI;
+  const ARMBaseTargetMachine &TM;
   const ARMRegisterBankInfo &RBI;
+  const ARMSubtarget &STI;
+
+#define GET_GLOBALISEL_PREDICATES_DECL
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATES_DECL
+
+// We declare the temporaries used by selectImpl() in the class to minimize the
+// cost of constructing placeholder values.
+#define GET_GLOBALISEL_TEMPORARIES_DECL
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_TEMPORARIES_DECL
 };
 } // end anonymous namespace
 
 namespace llvm {
 InstructionSelector *
-createARMInstructionSelector(const ARMSubtarget &STI,
+createARMInstructionSelector(const ARMBaseTargetMachine &TM,
+                             const ARMSubtarget &STI,
                              const ARMRegisterBankInfo &RBI) {
-  return new ARMInstructionSelector(STI, RBI);
+  return new ARMInstructionSelector(TM, STI, RBI);
 }
 }
 
-ARMInstructionSelector::ARMInstructionSelector(const ARMSubtarget &STI,
+unsigned zero_reg = 0;
+
+#define GET_GLOBALISEL_IMPL
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_IMPL
+
+ARMInstructionSelector::ARMInstructionSelector(const ARMBaseTargetMachine &TM,
+                                               const ARMSubtarget &STI,
                                                const ARMRegisterBankInfo &RBI)
     : InstructionSelector(), TII(*STI.getInstrInfo()),
-      TRI(*STI.getRegisterInfo()), RBI(RBI) {}
+      TRI(*STI.getRegisterInfo()), TM(TM), RBI(RBI), STI(STI),
+#define GET_GLOBALISEL_PREDICATES_INIT
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_PREDICATES_INIT
+#define GET_GLOBALISEL_TEMPORARIES_INIT
+#include "ARMGenGlobalISel.inc"
+#undef GET_GLOBALISEL_TEMPORARIES_INIT
+{
+}
 
 static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII,
                        MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI,
@@ -255,6 +290,9 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
     return true;
   }
 
+  if (selectImpl(I))
+    return true;
+
   MachineInstrBuilder MIB{MF, I};
   bool isSExt = false;
 
@@ -355,16 +393,6 @@ bool ARMInstructionSelector::select(MachineInstr &I) const {
     }
     MIB.add(predOps(ARMCC::AL)).add(condCodeOp());
     break;
-  case G_SDIV:
-    assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
-    I.setDesc(TII.get(ARM::SDIV));
-    MIB.add(predOps(ARMCC::AL));
-    break;
-  case G_UDIV:
-    assert(TII.getSubtarget().hasDivideInARMMode() && "Unsupported operation");
-    I.setDesc(TII.get(ARM::UDIV));
-    MIB.add(predOps(ARMCC::AL));
-    break;
   case G_FADD:
     if (!selectFAdd(MIB, TII, MRI))
       return false;
index 5bf827c..d09f3ec 100644 (file)
@@ -338,7 +338,7 @@ ARMBaseTargetMachine::getSubtargetImpl(const Function &F) const {
     // FIXME: At this point, we can't rely on Subtarget having RBI.
     // It's awkward to mix passing RBI and the Subtarget; should we pass
     // TII/TRI as well?
-    GISel->InstSelector.reset(createARMInstructionSelector(*I, *RBI));
+    GISel->InstSelector.reset(createARMInstructionSelector(*this, *I, *RBI));
 
     GISel->RegBankInfo.reset(RBI);
 #endif
index 1062c79..3cde439 100644 (file)
@@ -1,6 +1,9 @@
 set(LLVM_TARGET_DEFINITIONS ARM.td)
 
-tablegen(LLVM ARMGenRegisterBank.inc -gen-register-bank)
+if(LLVM_BUILD_GLOBAL_ISEL)
+  tablegen(LLVM ARMGenRegisterBank.inc -gen-register-bank)
+  tablegen(LLVM ARMGenGlobalISel.inc -gen-global-isel)
+endif()
 tablegen(LLVM ARMGenRegisterInfo.inc -gen-register-info)
 tablegen(LLVM ARMGenInstrInfo.inc -gen-instr-info)
 tablegen(LLVM ARMGenMCCodeEmitter.inc -gen-emitter)
index a25429b..65a1ea2 100644 (file)
@@ -854,7 +854,9 @@ public:
   }
 
   void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
-    OS << "    MIB.addReg(" << RegisterDef->getValueAsString("Namespace")
+    OS << "    MIB.addReg(" << (RegisterDef->getValue("Namespace")
+                                    ? RegisterDef->getValueAsString("Namespace")
+                                    : "")
        << "::" << RegisterDef->getName() << ");\n";
   }
 };
@@ -987,12 +989,16 @@ public:
            << ");\n";
 
         for (auto Def : I->ImplicitDefs) {
-          auto Namespace = Def->getValueAsString("Namespace");
+          auto Namespace = Def->getValue("Namespace")
+                               ? Def->getValueAsString("Namespace")
+                               : "";
           OS << "    MIB.addDef(" << Namespace << "::" << Def->getName()
              << ", RegState::Implicit);\n";
         }
         for (auto Use : I->ImplicitUses) {
-          auto Namespace = Use->getValueAsString("Namespace");
+          auto Namespace = Use->getValue("Namespace")
+                               ? Use->getValueAsString("Namespace")
+                               : "";
           OS << "    MIB.addUse(" << Namespace << "::" << Use->getName()
              << ", RegState::Implicit);\n";
         }