From 784c623efb9cf50f03e7adaeaad5602b56749417 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Sat, 3 Nov 2001 19:51:56 +0000 Subject: [PATCH] * Export method to merge identically named methods * Add code to fix PHI nodes that are missing arguments. These PHI nodes can be generated by GCC if there is an uninitialized variable flowing into a merge point. For example: int foo(int y) { int X; if (y) X = 1; return X; } llvm-svn: 1110 --- .../Transforms/IPO/DeadTypeElimination.cpp | 83 ++++++++++++++++++- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp b/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp index 13cc8d90af67..c83eba36110a 100644 --- a/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp +++ b/llvm/lib/Transforms/IPO/DeadTypeElimination.cpp @@ -118,7 +118,10 @@ static void ConvertCallTo(CallInst *CI, Method *Dest) { // because of the way things are declared in C. If this is the case, patch // things up. // -static bool PatchUpMethodReferences(SymbolTable *ST) { +bool CleanupGCCOutput::PatchUpMethodReferences(Module *M) { + SymbolTable *ST = M->getSymbolTable(); + if (!ST) return false; + map > Methods; // Loop over the entries in the symbol table. If an entry is a method pointer, @@ -149,6 +152,9 @@ static bool PatchUpMethodReferences(SymbolTable *ST) { Method *Implementation = 0; // Find the implementation Method *Concrete = 0; for (unsigned i = 0; i < Methods.size(); ++i) { + // TODO: Ignore methods that are never USED! DCE them. + // Remove their name. this should fix a majority of problems here. + if (!Methods[i]->isExternal()) { // Found an implementation assert(Implementation == 0 && "Multiple definitions of the same" " method. Case not handled yet!"); @@ -260,7 +266,7 @@ bool CleanupGCCOutput::doPassInitialization(Module *M) { // void "foo"(...) and void "foo"(int, int) because of the way things are // declared in C. If this is the case, patch things up. // - Changed |= PatchUpMethodReferences(ST); + Changed |= PatchUpMethodReferences(M); // If the module has a symbol table, they might be referring to the malloc @@ -348,11 +354,82 @@ bool CleanupGCCOutput::doOneCleanupPass(Method *M) { +// 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 + + Value *NewVal = 0; + const Type *Ty = PN->getType(); + if (const PointerType *PT = dyn_cast(Ty)) + NewVal = ConstPoolPointerNull::get(PT); + else if (Ty == Type::BoolTy) + NewVal = ConstPoolBool::True; + else if (Ty == Type::FloatTy || Ty == Type::DoubleTy) + NewVal = ConstPoolFP::get(Ty, 42); + else if (Ty->isIntegral()) + NewVal = ConstPoolInt::get(Ty, 42); + + 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. +// +// 2. PHI nodes with fewer arguments than predecessors. +// These can be generated by GCC if a variable is uninitalized over a path +// in the CFG. We fix this by adding an entry for the missing predecessors +// that is initialized to either 42 for a numeric/FP value, or null if it's +// a pointer value. This problem can be generated by code that looks like +// this: +// int foo(int y) { +// int X; +// if (y) X = 1; +// return X; +// } +// +static bool fixLocalProblems(Method *M) { + bool Changed = false; + // Don't use iterators because invalidation gets messy... + for (unsigned MI = 0; MI < M->size(); ++MI) { + BasicBlock *BB = M->getBasicBlocks()[MI]; + + if (isa(BB->front())) { + const vector Preds(BB->pred_begin(), BB->pred_end()); + + // 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. + // + for (BasicBlock::iterator I = BB->begin(); + PHINode *PN = dyn_cast(*I); ++I) { + + // Handle problem #2. + if (PN->getNumIncomingValues() != Preds.size()) { + 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]); + } + } + } + } + return Changed; +} + + + // doPerMethodWork - This method simplifies the specified method hopefully. // bool CleanupGCCOutput::doPerMethodWork(Method *M) { - bool Changed = false; + bool Changed = fixLocalProblems(M); while (doOneCleanupPass(M)) Changed = true; return Changed; }