Here is a patch that improve the BlockGenerator, so that it is able to
generate ScopStmt that is no "independent" and no basicblock centric
(well, these features are not implemented in this patch).
After this patch, all instruction copying should be handle by
"cloneInstrTree", which means, we do not need these functions anymore:
void copyInstScalar(const Instruction *Inst, ValueMapT &BBMap,
ValueMapT &GlobalMap);
Value *generateScalarLoad(const LoadInst *load, ValueMapT &BBMap,
ValueMapT &GlobalMap);
Value *generateScalarStore(const StoreInst *store, ValueMapT &BBMap,
ValueMapT &GlobalMap);
And the copying process perform dead code elimination implicitly
because it only copy instructions that have side effect or contribute
to the instructions that have side effect.
It pass the regression tests on 32 bit platform right now, to not
break some other people's benchmark, i will going to add a command
line option to disable the newly added block generate function by
default when i commit the patch (Or I should move the function to a
new BlockGenerator so it doesn't messing up the old BlockGenrator?).
best regards
ether
PS: Whats the status of Polly's LNT? Any extra steps to run it comparing to [1]?
[1]http://llvm.org/docs/lnt/quickstart.html
---
lib/CodeGen/CodeGeneration.cpp | 179 +++++++++++++++++++++++++++++++++++++++-
1 files changed, 178 insertions(+), 1 deletions(-)
diff --git a/lib/CodeGen/CodeGeneration.cpp b/lib/CodeGen/CodeGeneration.cpp
index 7edd136..c274b34 100644
--- a/lib/CodeGen/CodeGeneration.cpp
+++ b/lib/CodeGen/CodeGeneration.cpp
@@ -212,6 +212,72 @@ public:
Generator.copyBB(GlobalMap);
}
+ /// @brief Generate a new BasicBlock for a ScopStmt.
+ ///
+ /// @param Builder The LLVM-IR Builder used to generate the statement. The
+ /// code is generated at the location, the Builder
points to.
+ /// @param Stmt The statement to code generate.
+ /// @param GlobalMap A map that defines for certain Values
referenced from the
+ /// original code new Values they should be replaced with.
+ /// @param P A reference to the pass this function is called from.
+ /// The pass is needed to update other analysis.
+ static void generateBlock(IRBuilder<> &Builder, ScopStmt &Stmt,
+ ValueMapT &GlobalMap, Pass *P) {
+ BlockGenerator Generator(Builder, Stmt, P);
+
+ BasicBlock *BB = Generator.Statement.getBasicBlock();
+ BasicBlock *CopyBB = SplitBlock(Builder.GetInsertBlock(),
+ Builder.GetInsertPoint(), P);
+ CopyBB->setName("polly.stmt." + BB->getName());
+ Builder.SetInsertPoint(CopyBB->begin());
+
+ ValueMapT BBMap;
+
+ // To generate code for finder grain statement, we need to remeber the
+ // underlying instruction of the memory access.
+ // typedef ScopStmt::memacc_iterator acc_it;
+ // for (acc_it I = Stmt.memacc_begin(), E = Stmt.memacc_end(); I != E; ++I)
+ // Generate code for access I.
+
+ typedef BasicBlock::const_iterator it;
+ for (it II = BB->begin(), IE = BB->end(); II != IE; ++II) {
+ const Instruction *Inst = II;
+ if (MemoryAccess *MA = Stmt.lookupAccessFor(Inst))
+ Generator.generateMemoryAccess(MA, Inst, GlobalMap, BBMap);
+ }
+ }
+
+
+ void generateMemoryAccess(MemoryAccess *MA, const Instruction *Inst,
+ ValueMapT &GlobalMap, ValueMapT &BBMap) {
+ isl_map *CurrentAccessRelation = MA->getAccessRelation();
+ isl_map *NewAccessRelation = MA->getNewAccessRelation();
+
+ assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation)
+ && "Current and new access function use different spaces");
+
+ const Value *PointerOperand = MA->isRead() ?
+ cast<LoadInst>(Inst)->getPointerOperand() :
+ cast<StoreInst>(Inst)->getPointerOperand();
+
+ // Do we need to generate the address from new access relation?
+ if (NewAccessRelation) {
+ Value *BaseAddress = const_cast<Value*>(MA->getBaseAddr());
+ Value *NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress,
+ BBMap, GlobalMap);
+ BBMap[PointerOperand] = NewPointer;
+ }
+
+ cloneInstrTree(Inst, BBMap, GlobalMap);
+
+ // Free the context.
+ isl_map_free(CurrentAccessRelation);
+ if (NewAccessRelation) {
+ BBMap.erase(PointerOperand);
+ isl_map_free(NewAccessRelation);
+ }
+ }
+
protected:
IRBuilder<> &Builder;
ScopStmt &Statement;
@@ -280,11 +346,122 @@ protected:
/// (for values recalculated in the new ScoP, but not
/// within this basic block).
void copyBB(ValueMapT &GlobalMap);
+
+ static Value *castOperandType(Value *NewOperand, Type *DstTy,
+ Instruction *InsertPos) {
+ unsigned OldSize = DstTy->getScalarSizeInBits();
+ unsigned NewSize = NewOperand->getType()->getScalarSizeInBits();
+ // Insert a cast if types are different
+ // FIXME: Use IRBuilder, so we have chance to fold the cast.
+ if (OldSize < NewSize)
+ return CastInst::CreateTruncOrBitCast(NewOperand, DstTy,
+ NewOperand->getName() + "_c",
+ InsertPos);
+
+ return NewOperand;
+ }
+
+ /// @brief Clone the Instruction and its dependents recursively until the
+ /// instuction appears in the value map.
+ ///
+ /// @param Root The instruction need to be cloned.
+ /// @param BB The BasicBlock to hold the instruction.
+ ///
+ /// @return The newly cloned instruction.
+ Instruction *cloneInstrTree(const Instruction *Root, ValueMapT &BBMap,
+ ValueMapT &GlobalMap, const Twine
&NameSuffix="");
};
BlockGenerator::BlockGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P):
Builder(B), Statement(Stmt), P(P) {}
+Instruction *BlockGenerator::cloneInstrTree(const Instruction *Root,
+ ValueMapT &BBMap,
+ ValueMapT &GlobalMap,
+ const Twine &NameSuffix) {
+ // Clone the incoming instruction.
+ Instruction *NewI = Root->clone();
+ const BasicBlock *OldBB = Root->getParent();
+ if (!NewI->getType()->isVoidTy()) NewI->setName(Root->getName() +
NameSuffix);
+ // Insert it to the current bb and remember we already copy this instruction.
+ Builder.Insert(NewI);
+ // Remember we cloned this instruction.
+ BBMap[Root] = NewI;
+
+ // Depth first traverse the operand tree (or operand dag, because we will
+ // stop at PHINodes, so there are no cycle).
+ typedef Instruction::op_iterator ChildIt;
+ std::vector<std::pair<Instruction*, ChildIt> > WorkStack;
+
+ WorkStack.push_back(std::make_pair(NewI, NewI->op_begin()));
+
+ while (!WorkStack.empty()) {
+ Instruction *CurInst = WorkStack.back().first;
+ ChildIt It = WorkStack.back().second;
+ DEBUG(dbgs() << "Checking Operand of Node:\n" << *CurInst <<
"\n------>\n");
+ if (It == CurInst->op_end()) {
+ DEBUG(dbgs() << "Going to insert new inst: " << *CurInst << '\n');
+ // Insert the new instructions in topological order by insert the operand
+ // tree before the root.
+ // FIXME: Use IRBuilder?
+ if (!CurInst->getParent())
+ CurInst->insertBefore(NewI);
+
+ WorkStack.pop_back();
+ } else {
+ // for each node N,
+ Value *Operand = *It;
+ ++WorkStack.back().second;
+
+ DEBUG(dbgs() << "For Operand:\n" << *Operand << ' ' << Operand
<< "\n--->");
+
+ if (Value *NewParam = GlobalMap.lookup(Operand)) {
+ assert(Operand->getType() == NewParam->getType()
+ && "The type of parameter not match!");
+ DEBUG(dbgs() << "Replace parameter" << *Operand << " by "
+ << *NewParam << ".\n");
+ It->set(NewParam);
+ // If a value appeared in parameter map, it should not
appeared in local
+ // map
+ assert(!BBMap.count(Operand) && "Parameter in local map!");
+ continue;
+ }
+
+ Instruction *OpInst = dyn_cast<Instruction>(Operand);
+ // Do not clone the constant or parameters not in the parameters map.
+ if (OpInst == 0) continue;
+
+ // Now we need to clone Operand to CurBB.
+ // Check if we already clone it.
+ if (Value *Cloned = BBMap.lookup(OpInst)) {
+ DEBUG(dbgs() << "already cloned: " << *Cloned << ".\n");
+ It->set(castOperandType(Cloned, OpInst->getType(), NewI));
+ // Skip all its children as we already processed them.
+ continue;
+ }
+
+ // Ignore the parameter not in the subsitution map.
+ // FIXME: This is incorrect after IndependentBlocks pass is removed.
+ if (OldBB != OpInst->getParent()) continue;
+
+ // Else just clone the instruction.
+ // Note that NewOp is not inserted in any BB now, we will insert it when
+ // it popped form the work stack, so it will be inserted in topological
+ // order.
+ Instruction *NewOp = OpInst->clone();
+ NewOp->setName("p_" + OpInst->getName());
+ DEBUG(dbgs() << "Move to " << *NewOp << "\n");
+ It->set(NewOp);
+ // Insert it to the subsitiuation table.
+ BBMap[OpInst] = NewOp;
+ // Process its operands.
+ WorkStack.push_back(std::make_pair(NewOp, NewOp->op_begin()));
+ }
+ }
+
+ return NewI;
+}
+
Value *BlockGenerator::getNewValue(const Value *Old, ValueMapT &BBMap,
ValueMapT &GlobalMap) {
// We assume constants never change.
@@ -1197,7 +1374,7 @@ void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
int VectorDimensions = IVS ? IVS->size() : 1;
if (VectorDimensions == 1) {
- BlockGenerator::generate(Builder, *Statement, ValueMap, P);
+ BlockGenerator::generateBlock(Builder, *Statement, ValueMap, P);
I will guard this with a command line operation when i commit the
patch, so that the new block generate function is disable by default.
return;
}
--
1.7.5.4
this is a up to date patch.
best regards
ether
---
include/polly/CodeGen/BlockGenerators.h | 59 +++++++++++
lib/CodeGen/BlockGenerators.cpp | 165 +++++++++++++++++++++++++++++++
lib/CodeGen/CodeGeneration.cpp | 2 +-
3 files changed, 225 insertions(+), 1 deletions(-)
diff --git a/include/polly/CodeGen/BlockGenerators.h
b/include/polly/CodeGen/BlockGenerators.h
index d3521e1..daa37e1 100644
--- a/include/polly/CodeGen/BlockGenerators.h
+++ b/include/polly/CodeGen/BlockGenerators.h
@@ -238,6 +238,65 @@ private:
void copyBB();
};
+/// @brief Generate a new basic block for a polyhedral statement.
+///
+class TreeCopyStmtGenerator : public BlockGenerator {
+public:
+ /// @brief Generate a new BasicBlock for a ScopStmt.
+ ///
+ /// @param Builder The LLVM-IR Builder used to generate the statement. The
+ /// code is generated at the location, the Builder
points to.
+ /// @param Stmt The statement to code generate.
+ /// @param GlobalMap A map that defines for certain Values
referenced from the
+ /// original code new Values they should be replaced with.
+ /// @param P A reference to the pass this function is called from.
+ /// The pass is needed to update other analysis.
+ static void codegen(IRBuilder<> &Builder, ScopStmt &Stmt,
+ ValueMapT &GlobalMap, Pass *P);
+
+protected:
+ TreeCopyStmtGenerator(IRBuilder<> &B, ScopStmt &Stmt, Pass *P)
+ : BlockGenerator(B, Stmt, P) {}
+
+ /// @brief Cast the type of the operand.
+ ///
+ /// @param NewOperand The value need to cast.
+ /// @param DstTy The destinated type.
+ /// @param InsertPos The position to insert the cast instruction.
+ ///
+ /// @return The casted value if the type of NewOperand do not match DstTy, or
+ /// the simply NewOperand otherwise.
+ static Value *castOperandType(Value *NewOperand, Type *DstTy,
+ Instruction *InsertPos);
+
+ /// @brief Generate code for memory access in ScopStmt.
+ ///
+ /// @param MA The memory access to generate code for.
+ /// @param Inst The underlying instruction that access the memory.
+ /// @param BBMap A mapping from old values to their new values
+ /// (for values recalculated within this basic block).
+ /// @param GlobalMap A mapping from old values to their new values
+ /// (for values recalculated in the new ScoP, but not
+ /// within this basic block).
+ void generateMemoryAccess(MemoryAccess *MA, const Instruction *Inst,
+ ValueMapT &GlobalMap, ValueMapT &BBMap);
+
+ /// @brief Clone the Instruction and its dependents recursively until the
+ /// instuction appears in the value map.
+ ///
+ /// @param Root The instruction need to be cloned.
+ /// @param BBMap A mapping from old values to their new values
+ /// (for values recalculated within this basic block).
+ /// @param GlobalMap A mapping from old values to their new values
+ /// (for values recalculated in the new ScoP, but not
+ /// within this basic block).
+ /// @param NameSuffix The name suffix of the newly cloned instruction.
+ ///
+ /// @return The newly cloned instruction.
+ Instruction *cloneInstrTree(const Instruction *Root, ValueMapT &BBMap,
+ ValueMapT &GlobalMap, const Twine
&NameSuffix="");
+};
+
}
#endif
diff --git a/lib/CodeGen/BlockGenerators.cpp b/lib/CodeGen/BlockGenerators.cpp
index 95b8279..5c0af25 100644
--- a/lib/CodeGen/BlockGenerators.cpp
+++ b/lib/CodeGen/BlockGenerators.cpp
@@ -19,6 +19,8 @@
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/CommandLine.h"
+#define DEBUG_TYPE "polly-block-generators"
+#include "llvm/Support/Debug.h"
#include "isl/aff.h"
#include "isl/set.h"
@@ -645,3 +647,166 @@ void VectorBlockGenerator::copyBB() {
II != IE; ++II)
copyInstruction(II, VectorBlockMap, ScalarBlockMap);
}
+
+
+Value *TreeCopyStmtGenerator::castOperandType(Value *NewOperand, Type *DstTy,
+ Instruction *InsertPos) {
+ unsigned OldSize = DstTy->getScalarSizeInBits();
+ unsigned NewSize = NewOperand->getType()->getScalarSizeInBits();
+ // Insert a cast if types are different
+ // FIXME: Use IRBuilder, so we have chance to fold the cast.
+ if (OldSize < NewSize)
+ return CastInst::CreateTruncOrBitCast(NewOperand, DstTy,
+ NewOperand->getName() + "_c",
+ InsertPos);
+ else
+ assert(OldSize == NewSize && "Unexpect OldSize bigger than NewSize!");
+
+ return NewOperand;
+}
+
+void TreeCopyStmtGenerator::codegen(IRBuilder<> &Builder, ScopStmt &Stmt,
+ ValueMapT &GlobalMap, Pass *P) {
+ TreeCopyStmtGenerator Generator(Builder, Stmt, P);
+
+ BasicBlock *BB = Generator.Statement.getBasicBlock();
+ BasicBlock *CopyBB = SplitBlock(Builder.GetInsertBlock(),
+ Builder.GetInsertPoint(), P);
+ CopyBB->setName("polly.stmt." + BB->getName());
+ Builder.SetInsertPoint(CopyBB->begin());
+
+ ValueMapT BBMap;
+
+ // To generate code for finder grain statement, we need to remeber the
+ // underlying instruction of the memory access.
+ // typedef ScopStmt::memacc_iterator acc_it;
+ // for (acc_it I = Stmt.memacc_begin(), E = Stmt.memacc_end(); I != E; ++I)
+ // Generate code for access I.
+
+ typedef BasicBlock::const_iterator it;
+ for (it II = BB->begin(), IE = BB->end(); II != IE; ++II) {
+ const Instruction *Inst = II;
+ if (MemoryAccess *MA = Stmt.lookupAccessFor(Inst))
+ Generator.generateMemoryAccess(MA, Inst, GlobalMap, BBMap);
+ }
+}
+
+void TreeCopyStmtGenerator::generateMemoryAccess(MemoryAccess *MA,
+ const Instruction *Inst,
+ ValueMapT &GlobalMap,
+ ValueMapT &BBMap) {
+ isl_map *CurrentAccessRelation = MA->getAccessRelation();
+ isl_map *NewAccessRelation = MA->getNewAccessRelation();
+
+ assert(isl_map_has_equal_space(CurrentAccessRelation, NewAccessRelation)
+ && "Current and new access function use different spaces");
+
+ const Value *PointerOperand = MA->isRead() ?
+ cast<LoadInst>(Inst)->getPointerOperand() :
+ cast<StoreInst>(Inst)->getPointerOperand();
+
+ // Do we need to generate the address from new access relation?
+ if (NewAccessRelation) {
+ Value *BaseAddress = const_cast<Value*>(MA->getBaseAddr());
+ Value *NewPointer = getNewAccessOperand(NewAccessRelation, BaseAddress,
+ BBMap, GlobalMap);
+ BBMap[PointerOperand] = NewPointer;
+ }
+
+ cloneInstrTree(Inst, GlobalMap, BBMap);
+
+ // Free the context.
+ isl_map_free(CurrentAccessRelation);
+ if (NewAccessRelation) {
+ BBMap.erase(PointerOperand);
+ isl_map_free(NewAccessRelation);
+ }
+}
+
+Instruction *TreeCopyStmtGenerator::cloneInstrTree(const Instruction *Root,
+ ValueMapT &GlobalMap,
+ ValueMapT &BBMap,
+ const Twine &NameSuffix) {
+ // Clone the incoming instruction.
+ Instruction *NewI = Root->clone();
+ const BasicBlock *OldBB = Root->getParent();
+ if (!NewI->getType()->isVoidTy())
+ NewI->setName(Root->getName() + NameSuffix);
diff --git a/lib/CodeGen/CodeGeneration.cpp b/lib/CodeGen/CodeGeneration.cpp
index 4f46c95..55cb2c0 100644
--- a/lib/CodeGen/CodeGeneration.cpp
+++ b/lib/CodeGen/CodeGeneration.cpp
@@ -375,7 +375,7 @@ void ClastStmtCodeGen::codegen(const clast_user_stmt *u,
int VectorDimensions = IVS ? IVS->size() : 1;
if (VectorDimensions == 1) {
- BlockGenerator::generate(Builder, *Statement, ValueMap, P);
+ TreeCopyStmtGenerator::codegen(Builder, *Statement, ValueMap, P);
return;
}
--
1.7.5.4