Add transformations for Load and GetElementPtr.  Fix broken transform with shr.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1118 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Transforms/LevelRaise.cpp b/lib/Transforms/LevelRaise.cpp
index 039bfd2..b5f7056 100644
--- a/lib/Transforms/LevelRaise.cpp
+++ b/lib/Transforms/LevelRaise.cpp
@@ -221,8 +221,48 @@
     return ExpressionConvertableToType(I->getOperand(0), Ty) &&
            ExpressionConvertableToType(I->getOperand(1), Ty);
   case Instruction::Shl:
-  case Instruction::Shr:
     return ExpressionConvertableToType(I->getOperand(0), Ty);
+  case Instruction::Shr:
+    if (Ty->isSigned() != V->getType()->isSigned()) return false;
+    return ExpressionConvertableToType(I->getOperand(0), Ty);
+
+  case Instruction::Load: {
+    LoadInst *LI = cast<LoadInst>(I);
+    if (LI->hasIndices()) return false;
+    return ExpressionConvertableToType(LI->getPtrOperand(),
+                                       PointerType::get(Ty));
+  }
+  case Instruction::GetElementPtr: {
+    // GetElementPtr's are directly convertable to a pointer type if they have
+    // a number of zeros at the end.  Because removing these values does not
+    // change the logical offset of the GEP, it is okay and fair to remove them.
+    // This can change this:
+    //   %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0  ; <%List **>
+    //   %t2 = cast %List * * %t1 to %List *
+    // into
+    //   %t2 = getelementptr %Hosp * %hosp, ubyte 4           ; <%List *>
+    // 
+    GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+    const PointerType *PTy = dyn_cast<PointerType>(Ty);
+    if (!PTy) return false;
+
+    // Check to see if there are zero elements that we can remove from the
+    // index array.  If there are, check to see if removing them causes us to
+    // get to the right type...
+    //
+    vector<ConstPoolVal*> Indices = GEP->getIndexVec();
+    const Type *BaseType = GEP->getPtrOperand()->getType();
+
+    while (Indices.size() &&
+           cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+      Indices.pop_back();
+      const Type *ElTy = GetElementPtrInst::getIndexedType(BaseType, Indices,
+                                                           true);
+      if (ElTy == PTy->getValueType())
+        return true;  // Found a match!!
+    }
+    break;   // No match, maybe next time.
+  }
   }
   return false;
 }
@@ -269,6 +309,50 @@
                         I->getOperand(1), Name);
     break;
 
+  case Instruction::Load: {
+    LoadInst *LI = cast<LoadInst>(I);
+    assert(!LI->hasIndices());
+    Res = new LoadInst(ConvertExpressionToType(LI->getPtrOperand(),
+                                               PointerType::get(Ty)), Name);
+    break;
+  }
+
+  case Instruction::GetElementPtr: {
+    // GetElementPtr's are directly convertable to a pointer type if they have
+    // a number of zeros at the end.  Because removing these values does not
+    // change the logical offset of the GEP, it is okay and fair to remove them.
+    // This can change this:
+    //   %t1 = getelementptr %Hosp * %hosp, ubyte 4, ubyte 0  ; <%List **>
+    //   %t2 = cast %List * * %t1 to %List *
+    // into
+    //   %t2 = getelementptr %Hosp * %hosp, ubyte 4           ; <%List *>
+    // 
+    GetElementPtrInst *GEP = cast<GetElementPtrInst>(I);
+
+    // Check to see if there are zero elements that we can remove from the
+    // index array.  If there are, check to see if removing them causes us to
+    // get to the right type...
+    //
+    vector<ConstPoolVal*> Indices = GEP->getIndexVec();
+    const Type *BaseType = GEP->getPtrOperand()->getType();
+    const Type *PVTy = cast<PointerType>(Ty)->getValueType();
+    Res = 0;
+    while (Indices.size() &&
+           cast<ConstPoolUInt>(Indices.back())->getValue() == 0) {
+      Indices.pop_back();
+      if (GetElementPtrInst::getIndexedType(BaseType, Indices, true) == PVTy) {
+        if (Indices.size() == 0) {
+          Res = new CastInst(GEP->getPtrOperand(), BaseType); // NOOP
+        } else {
+          Res = new GetElementPtrInst(GEP->getPtrOperand(), Indices, Name);
+        }
+        break;
+      }
+    }
+    assert(Res && "Didn't find match!");
+    break;   // No match, maybe next time.
+  }
+
   default:
     assert(0 && "Expression convertable, but don't know how to convert?");
     return 0;
@@ -458,6 +542,18 @@
 }
 
 
+// Peephole optimize the following instructions:
+//   %t1 = cast int (uint) * %reg111 to uint (...) *
+//   %t2 = call uint (...) * %cast111( uint %key )
+//
+// Into: %t3 = call int (uint) * %reg111( uint %key )
+//       %t2 = cast int %t3 to uint
+//
+static bool PeepholeCallInst(BasicBlock *BB, BasicBlock::iterator &BI) {
+  CallInst *CI = cast<CallInst>(*BI);
+  return false;
+}
+
 
 static bool PeepholeOptimize(BasicBlock *BB, BasicBlock::iterator &BI) {
   Instruction *I = *BI;
@@ -596,6 +692,9 @@
   } else if (MallocInst *MI = dyn_cast<MallocInst>(I)) {
     if (PeepholeMallocInst(BB, BI)) return true;
 
+  } else if (CallInst *CI = dyn_cast<CallInst>(I)) {
+    if (PeepholeCallInst(BB, BI)) return true;
+
   } else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
     Value *Val     = SI->getOperand(0);
     Value *Pointer = SI->getPtrOperand();