[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