mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-30 07:00:45 +00:00
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
This commit is contained in:
parent
3bf04d5b99
commit
5b497ee7c2
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user