diff options
author | Chris Lattner <sabre@nondot.org> | 2001-11-03 21:08:59 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2001-11-03 21:08:59 +0000 |
commit | 5b497ee7c24b0cff0b5b5064b086d2ad4b190b6f (patch) | |
tree | 650dbd3c801a5f4dc8e979687238a0c45f714f5f /lib/Transforms | |
parent | 3bf04d5b99db505b07d55b42a348c6c642546d8c (diff) | |
download | external_llvm-5b497ee7c24b0cff0b5b5064b086d2ad4b190b6f.zip external_llvm-5b497ee7c24b0cff0b5b5064b086d2ad4b190b6f.tar.gz external_llvm-5b497ee7c24b0cff0b5b5064b086d2ad4b190b6f.tar.bz2 |
Add new cleanup pass:
// 1. PHI nodes with multiple entries for the same predecessor. GCC sometimes
// generates code that looks like this:
//
// bb7: br bool %cond1004, label %bb8, label %bb8
// bb8: %reg119 = phi uint [ 0, %bb7 ], [ 1, %bb7 ]
//
// which is completely illegal LLVM code. To compensate for this, we insert
// an extra basic block, and convert the code to look like this:
//
// bb7: br bool %cond1004, label %bbX, label %bb8
// bbX: br label bb8
// bb8: %reg119 = phi uint [ 0, %bbX ], [ 1, %bb7 ]
//
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1114 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/IPO/DeadTypeElimination.cpp | 80 |
1 files changed, 73 insertions, 7 deletions
diff --git a/lib/Transforms/IPO/DeadTypeElimination.cpp b/lib/Transforms/IPO/DeadTypeElimination.cpp index c83eba3..79f8c0d 100644 --- a/lib/Transforms/IPO/DeadTypeElimination.cpp +++ b/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -20,6 +20,7 @@ #include "llvm/DerivedTypes.h" #include "llvm/iOther.h" #include "llvm/iMemory.h" +#include "llvm/iTerminators.h" #include <map> #include <algorithm> @@ -354,16 +355,54 @@ bool CleanupGCCOutput::doOneCleanupPass(Method *M) { +// RefactorPredecessor - When we find out that a basic block is a repeated +// predecessor in a PHI node, we have to refactor the method until there is at +// most a single instance of a basic block in any predecessor list. +// +static inline void RefactorPredecessor(BasicBlock *BB, BasicBlock *Pred) { + Method *M = BB->getParent(); + assert(find(BB->pred_begin(), BB->pred_end(), Pred) != BB->pred_end() && + "Pred is not a predecessor of BB!"); + + // Create a new basic block, adding it to the end of the method. + BasicBlock *NewBB = new BasicBlock("", M); + + // Add an unconditional branch to BB to the new block. + NewBB->getInstList().push_back(new BranchInst(BB)); + + // Get the terminator that causes a branch to BB from Pred. + TerminatorInst *TI = Pred->getTerminator(); + + // Find the first use of BB in the terminator... + User::op_iterator OI = find(TI->op_begin(), TI->op_end(), BB); + assert(OI != TI->op_end() && "Pred does not branch to BB!!!"); + + // Change the use of BB to point to the new stub basic block + *OI = NewBB; + + // Now we need to loop through all of the PHI nodes in BB and convert their + // first incoming value for Pred to reference the new basic block instead. + // + for (BasicBlock::iterator I = BB->begin(); + PHINode *PN = dyn_cast<PHINode>(*I); ++I) { + int BBIdx = PN->getBasicBlockIndex(Pred); + assert(BBIdx != -1 && "PHI node doesn't have an entry for Pred!"); + + // The value that used to look like it came from Pred now comes from NewBB + PN->setIncomingBlock((unsigned)BBIdx, NewBB); + } +} + + // CheckIncomingValueFor - Make sure that the specified PHI node has an entry // for the provided basic block. If it doesn't, add one and return true. // -static inline bool CheckIncomingValueFor(PHINode *PN, BasicBlock *BB) { - unsigned NumArgs = PN->getNumIncomingValues(); - for (unsigned i = 0; i < NumArgs; ++i) - if (PN->getIncomingBlock(i) == BB) return false; // Already has value +static inline void CheckIncomingValueFor(PHINode *PN, BasicBlock *BB) { + if (PN->getBasicBlockIndex(BB) != -1) return; // Already has value Value *NewVal = 0; const Type *Ty = PN->getType(); + if (const PointerType *PT = dyn_cast<PointerType>(Ty)) NewVal = ConstPoolPointerNull::get(PT); else if (Ty == Type::BoolTy) @@ -375,13 +414,24 @@ static inline bool CheckIncomingValueFor(PHINode *PN, BasicBlock *BB) { assert(NewVal && "Unknown PHI node type!"); PN->addIncoming(NewVal, BB); - return true; } // fixLocalProblems - Loop through the method and fix problems with the PHI // nodes in the current method. The two problems that are handled are: // -// 1. PHI nodes with multiple entries for the same predecessor. +// 1. PHI nodes with multiple entries for the same predecessor. GCC sometimes +// generates code that looks like this: +// +// bb7: br bool %cond1004, label %bb8, label %bb8 +// bb8: %reg119 = phi uint [ 0, %bb7 ], [ 1, %bb7 ] +// +// which is completely illegal LLVM code. To compensate for this, we insert +// an extra basic block, and convert the code to look like this: +// +// bb7: br bool %cond1004, label %bbX, label %bb8 +// bbX: br label bb8 +// bb8: %reg119 = phi uint [ 0, %bbX ], [ 1, %bb7 ] +// // // 2. PHI nodes with fewer arguments than predecessors. // These can be generated by GCC if a variable is uninitalized over a path @@ -404,6 +454,21 @@ static bool fixLocalProblems(Method *M) { if (isa<PHINode>(BB->front())) { const vector<BasicBlock*> Preds(BB->pred_begin(), BB->pred_end()); + // Handle Problem #1. Sort the list of predecessors so that it is easy to + // decide whether or not duplicate predecessors exist. + vector<BasicBlock*> SortedPreds(Preds); + sort(SortedPreds.begin(), SortedPreds.end()); + + // Loop over the predecessors, looking for adjacent BB's that are equal. + BasicBlock *LastOne = 0; + for (unsigned i = 0; i < Preds.size(); ++i) { + if (SortedPreds[i] == LastOne) { // Found a duplicate. + RefactorPredecessor(BB, SortedPreds[i]); + Changed = true; + } + LastOne = SortedPreds[i]; + } + // Loop over all of the PHI nodes in the current BB. These PHI nodes are // guaranteed to be at the beginning of the basic block. // @@ -415,7 +480,8 @@ static bool fixLocalProblems(Method *M) { assert(PN->getNumIncomingValues() <= Preds.size() && "Can't handle extra arguments to PHI nodes!"); for (unsigned i = 0; i < Preds.size(); ++i) - Changed |= CheckIncomingValueFor(PN, Preds[i]); + CheckIncomingValueFor(PN, Preds[i]); + Changed = true; } } } |