Fix a major source of "type unsafety", where a cast is neccesary, but can
be put either before or after a load.  We chose to cast the value loaded
instead of the pointer to load from.

Fixes bug: test/Regression/Transforms/LevelRaise/2002-05-10-LoadPeephole.ll


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2621 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/LevelRaise.cpp b/lib/Transforms/LevelRaise.cpp
index af6555c..de45b0a 100644
--- a/lib/Transforms/LevelRaise.cpp
+++ b/lib/Transforms/LevelRaise.cpp
@@ -356,7 +356,6 @@
       }
 #endif
 
-#if 1
   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
     Value *Val     = SI->getOperand(0);
     Value *Pointer = SI->getPointerOperand();
@@ -396,6 +395,46 @@
             return true;
           }
 
+  } else if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
+    Value *Pointer = LI->getOperand(0);
+    const Type *PtrElType =
+      cast<PointerType>(Pointer->getType())->getElementType();
+    
+    // Peephole optimize the following instructions:
+    // %Val = cast <T1>* to <T2>*    ;; If T1 is losslessly convertable to T2
+    // %t = load <T2>* %P
+    //
+    // Into: 
+    // %t = load <T1>* %P
+    // %Val = cast <T1> to <T2>
+    //
+    // Note: This is not taken care of by expr conversion because there might
+    // not be a cast available for the store to convert the incoming value of.
+    // This code is basically here to make sure that pointers don't have casts
+    // if possible.
+    //
+    if (CastInst *CI = dyn_cast<CastInst>(Pointer))
+      if (Value *CastSrc = CI->getOperand(0)) // CSPT = CastSrcPointerType
+        if (PointerType *CSPT = dyn_cast<PointerType>(CastSrc->getType()))
+          // convertable types?
+          if (PtrElType->isLosslesslyConvertableTo(CSPT->getElementType()) &&
+              !LI->hasIndices()) {      // No subscripts yet!
+            PRINT_PEEPHOLE2("load-src-cast:in ", Pointer, LI);
+
+            // Create the new load instruction... loading the pre-casted value
+            LoadInst *NewLI = new LoadInst(CastSrc, LI->getName());
+            
+            // Insert the new T cast instruction... stealing old T's name
+            CastInst *NCI = new CastInst(NewLI, LI->getType(), CI->getName());
+            BI = BB->getInstList().insert(BI, NewLI)+1;
+
+            // Replace the old store with a new one!
+            ReplaceInstWithInst(BB->getInstList(), BI, NCI);
+            PRINT_PEEPHOLE3("load-src-cast:out", NCI, CastSrc, NewLI);
+            ++NumLoadStorePeepholes;
+            return true;
+          }
+
   } else if (I->getOpcode() == Instruction::Add &&
              isa<CastInst>(I->getOperand(1))) {
 
@@ -404,7 +443,6 @@
       ++NumGEPInstFormed;
       return true;
     }
-#endif
   }
 
   return false;