aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2001-11-03 21:08:59 +0000
committerChris Lattner <sabre@nondot.org>2001-11-03 21:08:59 +0000
commit5b497ee7c24b0cff0b5b5064b086d2ad4b190b6f (patch)
tree650dbd3c801a5f4dc8e979687238a0c45f714f5f /lib/Transforms
parent3bf04d5b99db505b07d55b42a348c6c642546d8c (diff)
downloadexternal_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.cpp80
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;
}
}
}