* Export method to merge identically named methods
authorChris Lattner <sabre@nondot.org>
Sat, 3 Nov 2001 19:51:56 +0000 (19:51 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 3 Nov 2001 19:51:56 +0000 (19:51 +0000)
* 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;
}

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1110 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/IPO/DeadTypeElimination.cpp

index 13cc8d90af671490c86eafac7737a5b27cde072d..c83eba36110a1dc87a529b1b6bf242a9f9523b16 100644 (file)
@@ -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<string, vector<Method*> > 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<PointerType>(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<PHINode>(BB->front())) {
+      const vector<BasicBlock*> 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<PHINode>(*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;
 }