[PATCH] CodeGen: Add IntegerDivisionPass

Tom Stellard thomas.stellard at amd.com
Tue Sep 23 12:48:34 PDT 2014


This pass will expand unsupported div/rem instructions based on
the result of the newly added TargetLowering::shouldExpandDivRemInIR().
---

A future commit will enable this pass for the R600 backend and add tests.

 include/llvm/CodeGen/Passes.h        |   6 ++
 include/llvm/InitializePasses.h      |   1 +
 include/llvm/Target/TargetLowering.h |   6 ++
 lib/CodeGen/CMakeLists.txt           |   1 +
 lib/CodeGen/IntegerDivisionPass.cpp  | 124 +++++++++++++++++++++++++++++++++++
 5 files changed, 138 insertions(+)
 create mode 100644 lib/CodeGen/IntegerDivisionPass.cpp

diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h
index 31fba89..3fedd5a 100644
--- a/include/llvm/CodeGen/Passes.h
+++ b/include/llvm/CodeGen/Passes.h
@@ -376,6 +376,9 @@ namespace llvm {
   /// load-linked/store-conditional loops.
   extern char &AtomicExpandID;
 
+  /// Lowers unsupported integer division.
+  extern char &IntegerDivisionID;
+
   /// MachineLoopInfo - This pass is a loop analysis pass.
   extern char &MachineLoopInfoID;
 
@@ -598,6 +601,9 @@ namespace llvm {
 
   /// createJumpInstrTables - This pass creates jump-instruction tables.
   ModulePass *createJumpInstrTablesPass();
+
+  /// Lower unsupported integer division
+  FunctionPass *createIntegerDivisionPass(const TargetMachine *TM);
 } // End llvm namespace
 
 /// This initializer registers TargetMachine constructor, so the pass being
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index 2964798..99f7ab5 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -146,6 +146,7 @@ void initializeInlineCostAnalysisPass(PassRegistry&);
 void initializeInstCombinerPass(PassRegistry&);
 void initializeInstCountPass(PassRegistry&);
 void initializeInstNamerPass(PassRegistry&);
+void initializeIntegerDivisionPass(PassRegistry&);
 void initializeInternalizePassPass(PassRegistry&);
 void initializeIntervalPartitionPass(PassRegistry&);
 void initializeJumpInstrTableInfoPass(PassRegistry&);
diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h
index 0a72225..245df33 100644
--- a/include/llvm/Target/TargetLowering.h
+++ b/include/llvm/Target/TargetLowering.h
@@ -1000,6 +1000,12 @@ public:
     return false;
   }
 
+  /// Returns true if the instruction should be expanded by the IR-level
+  /// IntegerDivision pass.
+  virtual bool shouldExpandDivRemInIR(const BinaryOperator &I) const {
+    return false;
+  }
+
   //===--------------------------------------------------------------------===//
   // TargetLowering Configuration Methods - These methods should be invoked by
   // the derived class constructor to configure this object for the target.
diff --git a/lib/CodeGen/CMakeLists.txt b/lib/CodeGen/CMakeLists.txt
index 0e06ed0..d002f47 100644
--- a/lib/CodeGen/CMakeLists.txt
+++ b/lib/CodeGen/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_library(LLVMCodeGen
   GlobalMerge.cpp
   IfConversion.cpp
   InlineSpiller.cpp
+  IntegerDivisionPass.cpp
   InterferenceCache.cpp
   IntrinsicLowering.cpp
   JumpInstrTables.cpp
diff --git a/lib/CodeGen/IntegerDivisionPass.cpp b/lib/CodeGen/IntegerDivisionPass.cpp
new file mode 100644
index 0000000..b198a1f
--- /dev/null
+++ b/lib/CodeGen/IntegerDivisionPass.cpp
@@ -0,0 +1,124 @@
+//===-- IntegerDivisionPass.cpp - Expand div/mod instructions -------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetSubtargetInfo.h"
+#include "llvm/Transforms/Utils/IntegerDivision.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "integer-division"
+
+namespace {
+
+class IntegerDivision : public FunctionPass,
+                        public InstVisitor<IntegerDivision, bool> {
+
+  const TargetMachine *TM;
+  const TargetLowering *TLI;
+
+  std::vector<BinaryOperator *> Divs;
+  std::vector<BinaryOperator *> Rems;
+
+  bool shouldExpandDivRem(const BinaryOperator &I);
+
+public:
+  static char ID;
+  explicit IntegerDivision(const TargetMachine *TM = nullptr)
+      : FunctionPass(ID), TM(TM), TLI(nullptr) {
+        initializeIntegerDivisionPass(*PassRegistry::getPassRegistry());
+      }
+  bool doInitialization(Module &M) override;
+  bool runOnFunction(Function &F) override;
+  const char *getPassName() const override {
+    return "Integer Division Pass";
+  }
+  bool visitInstruction(Instruction &I) { return false; }
+  bool visitSDiv(BinaryOperator &I);
+  bool visitUDiv(BinaryOperator &I);
+  bool visitSRem(BinaryOperator &I);
+  bool visitURem(BinaryOperator &I);
+
+};
+
+} // End anonymous namespace
+
+char IntegerDivision::ID = 0;
+char &llvm::IntegerDivisionID = IntegerDivision::ID;
+INITIALIZE_TM_PASS(IntegerDivision, "integerdivision",
+                   "Expand integer division", false, false);
+
+bool IntegerDivision::doInitialization(Module &M) {
+  return false;
+}
+
+bool IntegerDivision::runOnFunction(Function &F) {
+
+  if (TM)
+    TLI = TM->getSubtargetImpl()->getTargetLowering();
+
+  for (Function::iterator BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
+       BasicBlock *BB = BBI;
+    for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE; ++II) {
+        Instruction *I = II;
+        if (visit(*I)) {
+          BBI = F.begin();
+          break;
+        }
+    }
+  }
+
+  return false;
+}
+
+bool IntegerDivision::shouldExpandDivRem(const BinaryOperator &I) {
+  return TLI && TLI->shouldExpandDivRemInIR(I);
+}
+
+bool IntegerDivision::visitSDiv(BinaryOperator &I) {
+  if (shouldExpandDivRem(I)) {
+    expandDivision(&I);
+    return true;
+  }
+  return false;
+}
+
+bool IntegerDivision::visitUDiv(BinaryOperator &I) {
+  if (shouldExpandDivRem(I)) {
+    expandDivision(&I);
+    return true;
+  }
+  return false;
+}
+
+bool IntegerDivision::visitSRem(BinaryOperator &I) {
+  if (shouldExpandDivRem(I)) {
+    expandRemainder(&I);
+    return true;
+  }
+  return false;
+}
+
+bool IntegerDivision::visitURem(BinaryOperator &I) {
+  if (shouldExpandDivRem(I)) {
+    expandRemainder(&I);
+    return true;
+  }
+  return false;
+}
+
+FunctionPass *llvm::createIntegerDivisionPass(const TargetMachine *TM) {
+  return new IntegerDivision(TM);
+}
-- 
1.8.5.5




More information about the llvm-commits mailing list