[llvm-commits] [parallel] CVS: llvm/lib/Transforms/IPO/GlobalConstifier.cpp DeadArgumentElimination.cpp DeadTypeElimination.cpp FunctionResolution.cpp LowerSetJmp.cpp MutateStructTypes.cpp Parallelize.cpp PruneEH.cpp SimpleStructMutation.cpp
Misha Brukman
brukman at cs.uiuc.edu
Mon Mar 1 18:04:04 PST 2004
Changes in directory llvm/lib/Transforms/IPO:
GlobalConstifier.cpp added (r1.2.2.1)
DeadArgumentElimination.cpp updated: 1.14 -> 1.14.4.1
DeadTypeElimination.cpp updated: 1.48 -> 1.48.4.1
FunctionResolution.cpp updated: 1.45 -> 1.45.4.1
LowerSetJmp.cpp updated: 1.14 -> 1.14.4.1
MutateStructTypes.cpp updated: 1.44 -> 1.44.2.1
Parallelize.cpp updated: 1.12 -> 1.12.4.1
PruneEH.cpp updated: 1.9 -> 1.9.4.1
SimpleStructMutation.cpp updated: 1.24 -> 1.24.4.1
---
Log message:
Merge from trunk
---
Diffs of the changes: (+270 -219)
Index: llvm/lib/Transforms/IPO/GlobalConstifier.cpp
diff -c /dev/null llvm/lib/Transforms/IPO/GlobalConstifier.cpp:1.2.2.1
*** /dev/null Mon Mar 1 17:58:28 2004
--- llvm/lib/Transforms/IPO/GlobalConstifier.cpp Mon Mar 1 17:58:16 2004
***************
*** 0 ****
--- 1,82 ----
+ //===- GlobalConstifier.cpp - Mark read-only globals constant -------------===//
+ //
+ // The LLVM Compiler Infrastructure
+ //
+ // This file was developed by the LLVM research group and is distributed under
+ // the University of Illinois Open Source License. See LICENSE.TXT for details.
+ //
+ //===----------------------------------------------------------------------===//
+ //
+ // This pass loops over the non-constant internal global variables in the
+ // program. If it can prove that they are never written to, it marks them
+ // constant.
+ //
+ // NOTE: this should eventually use the alias analysis interfaces to do the
+ // transformation, but for now we just stick with a simple solution. DSA in
+ // particular could give a much more accurate answer to the mod/ref query, but
+ // it's not quite ready for this.
+ //
+ //===----------------------------------------------------------------------===//
+
+ #include "llvm/Transforms/IPO.h"
+ #include "llvm/Constants.h"
+ #include "llvm/Instructions.h"
+ #include "llvm/Module.h"
+ #include "llvm/Pass.h"
+ #include "Support/Debug.h"
+ #include "Support/Statistic.h"
+ using namespace llvm;
+
+ namespace {
+ Statistic<> NumMarked("constify", "Number of globals marked constant");
+
+ struct Constifier : public Pass {
+ bool run(Module &M);
+ };
+
+ RegisterOpt<Constifier> X("constify", "Global Constifier");
+ }
+
+ Pass *llvm::createGlobalConstifierPass() { return new Constifier(); }
+
+ /// isStoredThrough - Return false if the specified pointer is provably never
+ /// stored through. If we can't tell, we must conservatively assume it might.
+ ///
+ static bool isStoredThrough(Value *V) {
+ for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
+ if (Constant *C = dyn_cast<Constant>(*UI)) {
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
+ if (isStoredThrough(CE))
+ return true;
+ } else if (ConstantPointerRef *CPR = dyn_cast<ConstantPointerRef>(C)) {
+ if (isStoredThrough(CPR)) return true;
+ } else {
+ // Must be an element of a constant array or something.
+ return true;
+ }
+ } else if (Instruction *I = dyn_cast<Instruction>(*UI)) {
+ if (I->getOpcode() == Instruction::GetElementPtr) {
+ if (isStoredThrough(I)) return true;
+ } else if (!isa<LoadInst>(*UI) && !isa<SetCondInst>(*UI))
+ return true; // Any other non-load instruction might store!
+ } else {
+ // Otherwise must be a global or some other user.
+ return true;
+ }
+
+ return false;
+ }
+
+ bool Constifier::run(Module &M) {
+ bool Changed = false;
+ for (Module::giterator GV = M.gbegin(), E = M.gend(); GV != E; ++GV)
+ if (!GV->isConstant() && GV->hasInternalLinkage() && GV->hasInitializer()) {
+ if (!isStoredThrough(GV)) {
+ DEBUG(std::cerr << "MARKING CONSTANT: " << *GV << "\n");
+ GV->setConstant(true);
+ ++NumMarked;
+ Changed = true;
+ }
+ }
+ return Changed;
+ }
Index: llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp
diff -u llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.14 llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.14.4.1
--- llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp:1.14 Fri Nov 21 15:54:21 2003
+++ llvm/lib/Transforms/IPO/DeadArgumentElimination.cpp Mon Mar 1 17:58:16 2004
@@ -101,7 +101,7 @@
virtual bool ShouldHackArguments() const { return true; }
};
RegisterPass<DAH> Y("deadarghaX0r",
- "Dead Argument Hacking (bugpoint usage only)");
+ "Dead Argument Hacking (BUGPOINT USE ONLY; DO NOT USE)");
}
/// createDeadArgEliminationPass - This pass removes arguments from functions
@@ -424,7 +424,7 @@
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
- New = new InvokeInst(NF, II->getNormalDest(), II->getExceptionalDest(),
+ New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
Args, "", Call);
} else {
New = new CallInst(NF, Args, "", Call);
Index: llvm/lib/Transforms/IPO/DeadTypeElimination.cpp
diff -u llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.48 llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.48.4.1
--- llvm/lib/Transforms/IPO/DeadTypeElimination.cpp:1.48 Fri Nov 21 15:54:21 2003
+++ llvm/lib/Transforms/IPO/DeadTypeElimination.cpp Mon Mar 1 17:58:16 2004
@@ -49,12 +49,12 @@
// ShouldNukeSymtabEntry - Return true if this module level symbol table entry
// should be eliminated.
//
-static inline bool ShouldNukeSymtabEntry(const std::pair<std::string,Value*>&E){
+static inline bool ShouldNukeSymtabEntry(const Type *Ty){
// Nuke all names for primitive types!
- if (cast<Type>(E.second)->isPrimitiveType()) return true;
+ if (Ty->isPrimitiveType()) return true;
// Nuke all pointers to primitive types as well...
- if (const PointerType *PT = dyn_cast<PointerType>(E.second))
+ if (const PointerType *PT = dyn_cast<PointerType>(Ty))
if (PT->getElementType()->isPrimitiveType()) return true;
return false;
@@ -69,8 +69,7 @@
bool Changed = false;
SymbolTable &ST = M.getSymbolTable();
- const std::set<const Type *> &UsedTypes =
- getAnalysis<FindUsedTypes>().getTypes();
+ std::set<const Type *> UsedTypes = getAnalysis<FindUsedTypes>().getTypes();
// Check the symbol table for superfluous type entries...
//
@@ -79,18 +78,20 @@
if (STI != ST.end()) {
// Loop over all entries in the type plane...
SymbolTable::VarMap &Plane = STI->second;
- for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();)
+ for (SymbolTable::VarMap::iterator PI = Plane.begin(); PI != Plane.end();) {
// If this entry should be unconditionally removed, or if we detect that
// the type is not used, remove it.
- if (ShouldNukeSymtabEntry(*PI) ||
- !UsedTypes.count(cast<Type>(PI->second))) {
- SymbolTable::VarMap::iterator PJ = PI++;
- Plane.erase(PJ);
+ const Type *RHS = cast<Type>(PI->second);
+ if (ShouldNukeSymtabEntry(RHS) || !UsedTypes.count(RHS)) {
+ Plane.erase(PI++);
++NumKilled;
Changed = true;
} else {
++PI;
+ // We only need to leave one name for each type.
+ UsedTypes.erase(RHS);
}
+ }
}
return Changed;
Index: llvm/lib/Transforms/IPO/FunctionResolution.cpp
diff -u llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.45 llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.45.4.1
--- llvm/lib/Transforms/IPO/FunctionResolution.cpp:1.45 Thu Nov 20 15:21:31 2003
+++ llvm/lib/Transforms/IPO/FunctionResolution.cpp Mon Mar 1 17:58:16 2004
@@ -58,7 +58,7 @@
const FunctionType *OldMT = Old->getFunctionType();
const FunctionType *ConcreteMT = Concrete->getFunctionType();
- if (OldMT->getParamTypes().size() > ConcreteMT->getParamTypes().size() &&
+ if (OldMT->getNumParams() > ConcreteMT->getNumParams() &&
!ConcreteMT->isVarArg())
if (!Old->use_empty()) {
std::cerr << "WARNING: Linking function '" << Old->getName()
@@ -73,14 +73,14 @@
// Check to make sure that if there are specified types, that they
// match...
//
- unsigned NumArguments = std::min(OldMT->getParamTypes().size(),
- ConcreteMT->getParamTypes().size());
+ unsigned NumArguments = std::min(OldMT->getNumParams(),
+ ConcreteMT->getNumParams());
if (!Old->use_empty() && !Concrete->use_empty())
for (unsigned i = 0; i < NumArguments; ++i)
- if (OldMT->getParamTypes()[i] != ConcreteMT->getParamTypes()[i])
- if (OldMT->getParamTypes()[i]->getPrimitiveID() !=
- ConcreteMT->getParamTypes()[i]->getPrimitiveID()) {
+ if (OldMT->getParamType(i) != ConcreteMT->getParamType(i))
+ if (OldMT->getParamType(i)->getPrimitiveID() !=
+ ConcreteMT->getParamType(i)->getPrimitiveID()) {
std::cerr << "WARNING: Function [" << Old->getName()
<< "]: Parameter types conflict for: '";
WriteTypeSymbolic(std::cerr, OldMT, &M);
@@ -231,7 +231,7 @@
if ((ConcreteF->getReturnType() == OtherF->getReturnType() ||
CallersAllIgnoreReturnValue(*OtherF)) &&
OtherF->getFunctionType()->isVarArg() &&
- OtherF->getFunctionType()->getParamTypes().empty())
+ OtherF->getFunctionType()->getNumParams() == 0)
DontPrintWarning = true;
// Otherwise, if the non-concrete global is a global array variable with a
Index: llvm/lib/Transforms/IPO/LowerSetJmp.cpp
diff -u llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.14 llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.14.4.1
--- llvm/lib/Transforms/IPO/LowerSetJmp.cpp:1.14 Fri Nov 21 15:54:22 2003
+++ llvm/lib/Transforms/IPO/LowerSetJmp.cpp Mon Mar 1 17:58:16 2004
@@ -413,11 +413,6 @@
SetJmpContBlock->setName("SetJmpContBlock");
- // Reposition the split BB in the BB list to make things tidier.
- Func->getBasicBlockList().remove(SetJmpContBlock);
- Func->getBasicBlockList().insert(++Function::iterator(ABlock),
- SetJmpContBlock);
-
// This PHI node will be in the new block created from the
// splitBasicBlock call.
PHINode* PHI = new PHINode(Type::IntTy, "SetJmpReturn", Inst);
@@ -460,10 +455,7 @@
assert(NewBB && "Couldn't split BB of \"call\" instruction!!");
NewBB->setName("Call2Invoke");
- // Reposition the split BB in the BB list to make things tidier.
Function* Func = OldBB->getParent();
- Func->getBasicBlockList().remove(NewBB);
- Func->getBasicBlockList().insert(++Function::iterator(OldBB), NewBB);
// Construct the new "invoke" instruction.
TerminatorInst* Term = OldBB->getTerminator();
@@ -497,7 +489,7 @@
if (!DFSBlocks.count(BB)) return;
BasicBlock* NormalBB = II.getNormalDest();
- BasicBlock* ExceptBB = II.getExceptionalDest();
+ BasicBlock* ExceptBB = II.getUnwindDest();
Function* Func = BB->getParent();
BasicBlock* NewExceptBB = new BasicBlock("InvokeExcept", Func);
@@ -511,7 +503,7 @@
new BranchInst(PrelimBBMap[Func], ExceptBB, IsLJExcept, NewExceptBB);
- II.setExceptionalDest(NewExceptBB);
+ II.setUnwindDest(NewExceptBB);
++InvokesTransformed;
}
Index: llvm/lib/Transforms/IPO/MutateStructTypes.cpp
diff -u llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.44 llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.44.2.1
--- llvm/lib/Transforms/IPO/MutateStructTypes.cpp:1.44 Fri Jan 9 00:02:51 2004
+++ llvm/lib/Transforms/IPO/MutateStructTypes.cpp Mon Mar 1 17:58:16 2004
@@ -60,8 +60,8 @@
const Type *RetTy = ConvertType(FT->getReturnType());
std::vector<const Type*> ArgTypes;
- for (FunctionType::ParamTypes::const_iterator I = FT->getParamTypes().begin(),
- E = FT->getParamTypes().end(); I != E; ++I)
+ for (FunctionType::param_iterator I = FT->param_begin(),
+ E = FT->param_end(); I != E; ++I)
ArgTypes.push_back(ConvertType(*I));
DestTy = FunctionType::get(RetTy, ArgTypes, FT->isVarArg());
@@ -69,11 +69,10 @@
}
case Type::StructTyID: {
const StructType *ST = cast<StructType>(Ty);
- const StructType::ElementTypes &El = ST->getElementTypes();
std::vector<const Type *> Types;
- for (StructType::ElementTypes::const_iterator I = El.begin(), E = El.end();
- I != E; ++I)
+ for (StructType::element_iterator I = ST->element_begin(),
+ E = ST->element_end(); I != E; ++I)
Types.push_back(ConvertType(*I));
DestTy = StructType::get(Types);
break;
@@ -115,7 +114,7 @@
if (const StructType *OldST = dyn_cast<StructType>(OldTy)) {
// Figure out what the current index is...
unsigned ElNum = cast<ConstantUInt>(Idx[i])->getValue();
- assert(ElNum < OldST->getElementTypes().size());
+ assert(ElNum < OldST->getNumElements());
std::map<const StructType*, TransformType>::iterator
I = Transforms.find(OldST);
@@ -198,7 +197,7 @@
const StructType *OldTy = I->first;
const std::vector<int> &InVec = I->second;
- assert(OldTy->getElementTypes().size() == InVec.size() &&
+ assert(OldTy->getNumElements() == InVec.size() &&
"Action not specified for every element of structure type!");
std::vector<const Type *> NewType;
Index: llvm/lib/Transforms/IPO/Parallelize.cpp
diff -u llvm/lib/Transforms/IPO/Parallelize.cpp:1.12 llvm/lib/Transforms/IPO/Parallelize.cpp:1.12.4.1
--- llvm/lib/Transforms/IPO/Parallelize.cpp:1.12 Fri Nov 21 15:54:22 2003
+++ llvm/lib/Transforms/IPO/Parallelize.cpp Mon Mar 1 17:58:16 2004
@@ -91,10 +91,7 @@
// Code generation pass that transforms code to identify where Cilk keywords
// should be inserted. This relies on `llvm-dis -c' to print out the keywords.
//----------------------------------------------------------------------------
-
-
-class Cilkifier: public InstVisitor<Cilkifier>
-{
+class Cilkifier: public InstVisitor<Cilkifier> {
Function* DummySyncFunc;
// Data used when transforming each function.
@@ -124,16 +121,14 @@
};
-Cilkifier::Cilkifier(Module& M)
-{
+Cilkifier::Cilkifier(Module& M) {
// create the dummy Sync function and add it to the Module
DummySyncFunc = M.getOrInsertFunction(DummySyncFuncName, Type::VoidTy, 0);
}
void Cilkifier::TransformFunc(Function* F,
const hash_set<Function*>& _cilkFunctions,
- PgmDependenceGraph& _depGraph)
-{
+ PgmDependenceGraph& _depGraph) {
// Memoize the information for this function
cilkFunctions = &_cilkFunctions;
depGraph = &_depGraph;
@@ -159,37 +154,35 @@
stmtsVisited.insert(I);
// If there is a dependence from root to I, insert Sync and return
- if (depsOfRoot.find(I) != depsOfRoot.end())
- { // Insert a sync before I and stop searching along this path.
- // If I is a Phi instruction, the dependence can only be an SSA dep.
- // and we need to insert the sync in the predecessor on the appropriate
- // incoming edge!
- CallInst* syncI = 0;
- if (PHINode* phiI = dyn_cast<PHINode>(I))
- { // check all operands of the Phi and insert before each one
- for (unsigned i = 0, N = phiI->getNumIncomingValues(); i < N; ++i)
- if (phiI->getIncomingValue(i) == root)
- syncI = new CallInst(DummySyncFunc, std::vector<Value*>(), "",
- phiI->getIncomingBlock(i)->getTerminator());
- }
- else
- syncI = new CallInst(DummySyncFunc, std::vector<Value*>(), "", I);
+ if (depsOfRoot.find(I) != depsOfRoot.end()) {
+ // Insert a sync before I and stop searching along this path.
+ // If I is a Phi instruction, the dependence can only be an SSA dep.
+ // and we need to insert the sync in the predecessor on the appropriate
+ // incoming edge!
+ CallInst* syncI = 0;
+ if (PHINode* phiI = dyn_cast<PHINode>(I)) {
+ // check all operands of the Phi and insert before each one
+ for (unsigned i = 0, N = phiI->getNumIncomingValues(); i < N; ++i)
+ if (phiI->getIncomingValue(i) == root)
+ syncI = new CallInst(DummySyncFunc, std::vector<Value*>(), "",
+ phiI->getIncomingBlock(i)->getTerminator());
+ } else
+ syncI = new CallInst(DummySyncFunc, std::vector<Value*>(), "", I);
- // Remember the sync for each spawn to eliminate redundant ones later
- spawnToSyncsMap[cast<CallInst>(root)].insert(syncI);
+ // Remember the sync for each spawn to eliminate redundant ones later
+ spawnToSyncsMap[cast<CallInst>(root)].insert(syncI);
- return;
- }
+ return;
+ }
// else visit unvisited successors
- if (BranchInst* brI = dyn_cast<BranchInst>(I))
- { // visit first instruction in each successor BB
- for (unsigned i = 0, N = brI->getNumSuccessors(); i < N; ++i)
- if (stmtsVisited.find(&brI->getSuccessor(i)->front())
- == stmtsVisited.end())
- DFSVisitInstr(&brI->getSuccessor(i)->front(), root, depsOfRoot);
- }
- else
+ if (BranchInst* brI = dyn_cast<BranchInst>(I)) {
+ // visit first instruction in each successor BB
+ for (unsigned i = 0, N = brI->getNumSuccessors(); i < N; ++i)
+ if (stmtsVisited.find(&brI->getSuccessor(i)->front())
+ == stmtsVisited.end())
+ DFSVisitInstr(&brI->getSuccessor(i)->front(), root, depsOfRoot);
+ } else
if (Instruction* nextI = I->getNext())
if (stmtsVisited.find(nextI) == stmtsVisited.end())
DFSVisitInstr(nextI, root, depsOfRoot);
@@ -214,44 +207,37 @@
std::vector<const PHINode*> phiUsers;
hash_set<const PHINode*> phisSeen; // ensures we don't visit a phi twice
for (Value::use_iterator UI=CI.use_begin(), UE=CI.use_end(); UI != UE; ++UI)
- if (const PHINode* phiUser = dyn_cast<PHINode>(*UI))
- {
- if (phisSeen.find(phiUser) == phisSeen.end())
- {
- phiUsers.push_back(phiUser);
- phisSeen.insert(phiUser);
- }
+ if (const PHINode* phiUser = dyn_cast<PHINode>(*UI)) {
+ if (phisSeen.find(phiUser) == phisSeen.end()) {
+ phiUsers.push_back(phiUser);
+ phisSeen.insert(phiUser);
}
+ }
else
depsOfRoot.insert(cast<Instruction>(*UI));
// Now we've found the non-Phi users and immediate phi users.
// Recursively walk the phi users and add their non-phi users.
- for (const PHINode* phiUser; !phiUsers.empty(); phiUsers.pop_back())
- {
- phiUser = phiUsers.back();
- for (Value::use_const_iterator UI=phiUser->use_begin(),
- UE=phiUser->use_end(); UI != UE; ++UI)
- if (const PHINode* pn = dyn_cast<PHINode>(*UI))
- {
- if (phisSeen.find(pn) == phisSeen.end())
- {
- phiUsers.push_back(pn);
- phisSeen.insert(pn);
- }
- }
- else
- depsOfRoot.insert(cast<Instruction>(*UI));
- }
+ for (const PHINode* phiUser; !phiUsers.empty(); phiUsers.pop_back()) {
+ phiUser = phiUsers.back();
+ for (Value::use_const_iterator UI=phiUser->use_begin(),
+ UE=phiUser->use_end(); UI != UE; ++UI)
+ if (const PHINode* pn = dyn_cast<PHINode>(*UI)) {
+ if (phisSeen.find(pn) == phisSeen.end()) {
+ phiUsers.push_back(pn);
+ phisSeen.insert(pn);
+ }
+ } else
+ depsOfRoot.insert(cast<Instruction>(*UI));
+ }
// Walk paths of the CFG starting at the call instruction and insert
// one sync before the first dependence on each path, if any.
- if (! depsOfRoot.empty())
- {
- stmtsVisited.clear(); // start a new DFS for this CallInst
- assert(CI.getNext() && "Call instruction cannot be a terminator!");
- DFSVisitInstr(CI.getNext(), &CI, depsOfRoot);
- }
+ if (! depsOfRoot.empty()) {
+ stmtsVisited.clear(); // start a new DFS for this CallInst
+ assert(CI.getNext() && "Call instruction cannot be a terminator!");
+ DFSVisitInstr(CI.getNext(), &CI, depsOfRoot);
+ }
// Now, eliminate all users of the SSA value of the CallInst, i.e.,
// if the call instruction returns a value, delete the return value
@@ -304,31 +290,28 @@
// Now we've found all CallInsts reachable from each CallInst.
// Find those CallInsts that are parallel with at least one other CallInst
// by counting total inEdges and outEdges.
- //
unsigned long totalNumCalls = completed.size();
- if (totalNumCalls == 1)
- { // Check first for the special case of a single call instruction not
- // in any loop. It is not parallel, even if it has no dependences
- // (this is why it is a special case).
- //
- // FIXME:
- // THIS CASE IS NOT HANDLED RIGHT NOW, I.E., THERE IS NO
- // PARALLELISM FOR CALLS IN DIFFERENT ITERATIONS OF A LOOP.
- //
- return;
- }
+ if (totalNumCalls == 1) {
+ // Check first for the special case of a single call instruction not
+ // in any loop. It is not parallel, even if it has no dependences
+ // (this is why it is a special case).
+ //
+ // FIXME:
+ // THIS CASE IS NOT HANDLED RIGHT NOW, I.E., THERE IS NO
+ // PARALLELISM FOR CALLS IN DIFFERENT ITERATIONS OF A LOOP.
+ return;
+ }
hash_map<CallInst*, unsigned long> numDeps;
for (hash_map<CallInst*, DependentsSet>::iterator II = dependents.begin(),
- IE = dependents.end(); II != IE; ++II)
- {
- CallInst* fromCI = II->first;
- numDeps[fromCI] += II->second.size();
- for (Dependents_iterator DI = II->second.begin(), DE = II->second.end();
- DI != DE; ++DI)
- numDeps[*DI]++; // *DI can be reached from II->first
- }
+ IE = dependents.end(); II != IE; ++II) {
+ CallInst* fromCI = II->first;
+ numDeps[fromCI] += II->second.size();
+ for (Dependents_iterator DI = II->second.begin(), DE = II->second.end();
+ DI != DE; ++DI)
+ numDeps[*DI]++; // *DI can be reached from II->first
+ }
for (hash_map<CallInst*, DependentsSet>::iterator
II = dependents.begin(), IE = dependents.end(); II != IE; ++II)
@@ -347,36 +330,31 @@
stmtsVisited.insert(I);
if (CallInst* CI = dyn_cast<CallInst>(I))
-
// FIXME: Ignoring parallelism in a loop. Here we're actually *ignoring*
// a self-dependence in order to get the count comparison right above.
// When we include loop parallelism, self-dependences should be included.
- //
- if (CI != root)
-
- { // CallInst root has a path to CallInst I and any calls reachable from I
- depsOfRoot.insert(CI);
- if (completed[CI])
- { // We have already visited I so we know all nodes it can reach!
- DependentsSet& depsOfI = dependents[CI];
- depsOfRoot.insert(depsOfI.begin(), depsOfI.end());
- return;
- }
+ if (CI != root) {
+ // CallInst root has a path to CallInst I and any calls reachable from I
+ depsOfRoot.insert(CI);
+ if (completed[CI]) {
+ // We have already visited I so we know all nodes it can reach!
+ DependentsSet& depsOfI = dependents[CI];
+ depsOfRoot.insert(depsOfI.begin(), depsOfI.end());
+ return;
}
+ }
// If we reach here, we need to visit all children of I
for (PgmDependenceGraph::iterator DI = depGraph.outDepBegin(*I);
- ! DI.fini(); ++DI)
- {
- Instruction* sink = &DI->getSink()->getInstr();
- if (stmtsVisited.find(sink) == stmtsVisited.end())
- VisitOutEdges(sink, root, depsOfRoot);
- }
+ ! DI.fini(); ++DI) {
+ Instruction* sink = &DI->getSink()->getInstr();
+ if (stmtsVisited.find(sink) == stmtsVisited.end())
+ VisitOutEdges(sink, root, depsOfRoot);
+ }
}
-void FindParallelCalls::visitCallInst(CallInst& CI)
-{
+void FindParallelCalls::visitCallInst(CallInst& CI) {
if (completed[&CI])
return;
stmtsVisited.clear(); // clear flags to do a fresh DFS
@@ -384,12 +362,11 @@
// Visit all children of CI using a recursive walk through dep graph
DependentsSet& depsOfRoot = dependents[&CI];
for (PgmDependenceGraph::iterator DI = depGraph.outDepBegin(CI);
- ! DI.fini(); ++DI)
- {
- Instruction* sink = &DI->getSink()->getInstr();
- if (stmtsVisited.find(sink) == stmtsVisited.end())
- VisitOutEdges(sink, &CI, depsOfRoot);
- }
+ ! DI.fini(); ++DI) {
+ Instruction* sink = &DI->getSink()->getInstr();
+ if (stmtsVisited.find(sink) == stmtsVisited.end())
+ VisitOutEdges(sink, &CI, depsOfRoot);
+ }
completed[&CI] = true;
}
@@ -411,8 +388,7 @@
//----------------------------------------------------------------------------
namespace {
- class Parallelize: public Pass
- {
+ class Parallelize: public Pass {
public:
/// Driver functions to transform a program
///
@@ -433,68 +409,50 @@
}
-static Function* FindMain(Module& M)
-{
- for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
- if (FI->getName() == std::string("main"))
- return FI;
- return NULL;
-}
-
-
-bool Parallelize::run(Module& M)
-{
+bool Parallelize::run(Module& M) {
hash_set<Function*> parallelFunctions;
hash_set<Function*> safeParallelFunctions;
hash_set<const GlobalValue*> indirectlyCalled;
// If there is no main (i.e., for an incomplete program), we can do nothing.
// If there is a main, mark main as a parallel function.
- //
- Function* mainFunc = FindMain(M);
+ Function* mainFunc = M.getMainFunction();
if (!mainFunc)
return false;
// (1) Find candidate parallel functions and mark them as Cilk functions
- //
for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI)
- if (! FI->isExternal())
- {
- Function* F = FI;
- DSGraph& tdg = getAnalysis<TDDataStructures>().getDSGraph(*F);
-
- // All the hard analysis work gets done here!
- //
- FindParallelCalls finder(*F,
- getAnalysis<PgmDependenceGraph>().getGraph(*F));
- /* getAnalysis<MemoryDepAnalysis>().getGraph(*F)); */
-
- // Now we know which call instructions are useful to parallelize.
- // Remember those callee functions.
- //
- for (std::vector<CallInst*>::iterator
- CII = finder.parallelCalls.begin(),
- CIE = finder.parallelCalls.end(); CII != CIE; ++CII)
- {
- // Check if this is a direct call...
- if ((*CII)->getCalledFunction() != NULL)
- { // direct call: if this is to a non-external function,
- // mark it as a parallelizable function
- if (! (*CII)->getCalledFunction()->isExternal())
- parallelFunctions.insert((*CII)->getCalledFunction());
- }
- else
- { // Indirect call: mark all potential callees as bad
- std::vector<GlobalValue*> callees =
- tdg.getNodeForValue((*CII)->getCalledValue())
- .getNode()->getGlobals();
- indirectlyCalled.insert(callees.begin(), callees.end());
- }
- }
+ if (! FI->isExternal()) {
+ Function* F = FI;
+ DSGraph& tdg = getAnalysis<TDDataStructures>().getDSGraph(*F);
+
+ // All the hard analysis work gets done here!
+ FindParallelCalls finder(*F,
+ getAnalysis<PgmDependenceGraph>().getGraph(*F));
+ /* getAnalysis<MemoryDepAnalysis>().getGraph(*F)); */
+
+ // Now we know which call instructions are useful to parallelize.
+ // Remember those callee functions.
+ for (std::vector<CallInst*>::iterator
+ CII = finder.parallelCalls.begin(),
+ CIE = finder.parallelCalls.end(); CII != CIE; ++CII) {
+ // Check if this is a direct call...
+ if ((*CII)->getCalledFunction() != NULL) {
+ // direct call: if this is to a non-external function,
+ // mark it as a parallelizable function
+ if (! (*CII)->getCalledFunction()->isExternal())
+ parallelFunctions.insert((*CII)->getCalledFunction());
+ } else {
+ // Indirect call: mark all potential callees as bad
+ std::vector<GlobalValue*> callees =
+ tdg.getNodeForValue((*CII)->getCalledValue())
+ .getNode()->getGlobals();
+ indirectlyCalled.insert(callees.begin(), callees.end());
+ }
}
+ }
// Remove all indirectly called functions from the list of Cilk functions.
- //
for (hash_set<Function*>::iterator PFI = parallelFunctions.begin(),
PFE = parallelFunctions.end(); PFI != PFE; ++PFI)
if (indirectlyCalled.count(*PFI) == 0)
@@ -524,15 +482,13 @@
// This should identify both functions and calls to such functions
// to the code generator.
// (4) Also, insert calls to sync at appropriate points.
- //
Cilkifier cilkifier(M);
for (hash_set<Function*>::iterator CFI = safeParallelFunctions.begin(),
- CFE = safeParallelFunctions.end(); CFI != CFE; ++CFI)
- {
- cilkifier.TransformFunc(*CFI, safeParallelFunctions,
- getAnalysis<PgmDependenceGraph>().getGraph(**CFI));
- /* getAnalysis<MemoryDepAnalysis>().getGraph(**CFI)); */
- }
+ CFE = safeParallelFunctions.end(); CFI != CFE; ++CFI) {
+ cilkifier.TransformFunc(*CFI, safeParallelFunctions,
+ getAnalysis<PgmDependenceGraph>().getGraph(**CFI));
+ /* getAnalysis<MemoryDepAnalysis>().getGraph(**CFI)); */
+ }
return true;
}
Index: llvm/lib/Transforms/IPO/PruneEH.cpp
diff -u llvm/lib/Transforms/IPO/PruneEH.cpp:1.9 llvm/lib/Transforms/IPO/PruneEH.cpp:1.9.4.1
--- llvm/lib/Transforms/IPO/PruneEH.cpp:1.9 Fri Nov 21 20:26:17 2003
+++ llvm/lib/Transforms/IPO/PruneEH.cpp Mon Mar 1 17:58:16 2004
@@ -51,19 +51,41 @@
// obviously the SCC might throw.
//
bool SCCMightThrow = false;
- for (unsigned i = 0, e = SCC.size(); i != e; ++i)
- if (!DoesNotThrow.count(SCC[i]) && // Calls maybe throwing fn
- // Make sure this is not one of the fn's in the SCC.
- std::find(SCC.begin(), SCC.end(), SCC[i]) == SCC.end()) {
- SCCMightThrow = true; break;
- } else if (Function *F = SCC[i]->getFunction())
- if (F->isExternal()) {
- SCCMightThrow = true; break;
+ for (unsigned i = 0, e = SCC.size(); !SCCMightThrow && i != e; ++i)
+ if (Function *F = SCC[i]->getFunction())
+ if (F->isExternal() && !F->getIntrinsicID()) {
+ SCCMightThrow = true;
} else {
- for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I)
- if (isa<UnwindInst>(I->getTerminator())) { // Uses unwind!
- SCCMightThrow = true; break;
+ // Check to see if this function performs an unwind or calls an
+ // unwinding function.
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ if (isa<UnwindInst>(BB->getTerminator())) { // Uses unwind!
+ SCCMightThrow = true;
+ break;
}
+
+ // Invoke instructions don't allow unwinding to continue, so we are
+ // only interested in call instructions.
+ for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+ if (CallInst *CI = dyn_cast<CallInst>(I)) {
+ if (Function *Callee = CI->getCalledFunction()) {
+ CallGraphNode *CalleeNode = CG[Callee];
+ // If the callee is outside our current SCC, or if it is not
+ // known to throw, then we might throw also.
+ if (std::find(SCC.begin(), SCC.end(), CalleeNode) == SCC.end()&&
+ !DoesNotThrow.count(CalleeNode)) {
+ SCCMightThrow = true;
+ break;
+ }
+
+ } else {
+ // Indirect call, it might throw.
+ SCCMightThrow = true;
+ break;
+ }
+ }
+ if (SCCMightThrow) break;
+ }
}
bool MadeChange = false;
@@ -91,7 +113,7 @@
// Anything that used the value produced by the invoke instruction
// now uses the value produced by the call instruction.
II->replaceAllUsesWith(Call);
- II->getExceptionalDest()->removePredecessor(II->getParent());
+ II->getUnwindDest()->removePredecessor(II->getParent());
// Insert a branch to the normal destination right before the
// invoke.
Index: llvm/lib/Transforms/IPO/SimpleStructMutation.cpp
diff -u llvm/lib/Transforms/IPO/SimpleStructMutation.cpp:1.24 llvm/lib/Transforms/IPO/SimpleStructMutation.cpp:1.24.4.1
--- llvm/lib/Transforms/IPO/SimpleStructMutation.cpp:1.24 Fri Nov 21 15:52:10 2003
+++ llvm/lib/Transforms/IPO/SimpleStructMutation.cpp Mon Mar 1 17:58:16 2004
@@ -90,7 +90,7 @@
//
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
I != E; ++I) {
- if (!isa<PointerType>(*I))
+ if (!isa<PointerType>(I->get()))
PruneTypes(*I, TypesToModify, ProcessedTypes);
}
}
@@ -109,7 +109,7 @@
static inline void GetTransformation(const TargetData &TD, const StructType *ST,
std::vector<int> &Transform,
enum SimpleStructMutation::Transform XForm) {
- unsigned NumElements = ST->getElementTypes().size();
+ unsigned NumElements = ST->getNumElements();
Transform.reserve(NumElements);
switch (XForm) {
@@ -124,8 +124,7 @@
// Build mapping from index to size
for (unsigned i = 0; i < NumElements; ++i)
- ElList.push_back(
- std::make_pair(i, TD.getTypeSize(ST->getElementTypes()[i])));
+ ElList.push_back(std::make_pair(i,TD.getTypeSize(ST->getElementType(i))));
sort(ElList.begin(), ElList.end(), ptr_fun(FirstLess));
More information about the llvm-commits
mailing list