[llvm-commits] [llvm] r62905 - /llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp

Bill Wendling isanbard at gmail.com
Fri Jan 23 17:16:14 PST 2009


Author: void
Date: Fri Jan 23 19:16:14 2009
New Revision: 62905

URL: http://llvm.org/viewvc/llvm-project?rev=62905&view=rev
Log:
Pull r62904 into Dib:

Make InstCombineStoreToCast handle aggregates more aggressively,
handling the case in Transforms/InstCombine/cast-store-gep.ll, which
is a heavily reduced testcase from Clang on x86-64.

Modified:
    llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp

Modified: llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp?rev=62905&r1=62904&r2=62905&view=diff

==============================================================================
--- llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp Fri Jan 23 19:16:14 2009
@@ -7700,12 +7700,12 @@
 
 /// FindElementAtOffset - Given a type and a constant offset, determine whether
 /// or not there is a sequence of GEP indices into the type that will land us at
-/// the specified offset.  If so, fill them into NewIndices and return true,
-/// otherwise return false.
-static bool FindElementAtOffset(const Type *Ty, int64_t Offset, 
-                                SmallVectorImpl<Value*> &NewIndices,
-                                const TargetData *TD) {
-  if (!Ty->isSized()) return false;
+/// the specified offset.  If so, fill them into NewIndices and return the
+/// resultant element type, otherwise return null.
+static const Type *FindElementAtOffset(const Type *Ty, int64_t Offset, 
+                                       SmallVectorImpl<Value*> &NewIndices,
+                                       const TargetData *TD) {
+  if (!Ty->isSized()) return 0;
   
   // Start with the index over the outer type.  Note that the type size
   // might be zero (even if the offset isn't zero) if the indexed type
@@ -7731,7 +7731,7 @@
   while (Offset) {
     // Indexing into tail padding between struct/array elements.
     if (uint64_t(Offset*8) >= TD->getTypeSizeInBits(Ty))
-      return false;
+      return 0;
     
     if (const StructType *STy = dyn_cast<StructType>(Ty)) {
       const StructLayout *SL = TD->getStructLayout(STy);
@@ -7751,11 +7751,11 @@
       Ty = AT->getElementType();
     } else {
       // Otherwise, we can't index into the middle of this atomic type, bail.
-      return false;
+      return 0;
     }
   }
   
-  return true;
+  return Ty;
 }
 
 /// @brief Implement the transforms for cast of pointer (bitcast/ptrtoint)
@@ -11139,7 +11139,8 @@
 }
 
 /// InstCombineStoreToCast - Fold store V, (cast P) -> store (cast V), P
-/// when possible.
+/// when possible.  This makes it generally easy to do alias analysis and/or
+/// SROA/mem2reg of the memory object.
 static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
   User *CI = cast<User>(SI.getOperand(1));
   Value *CastOp = CI->getOperand(0);
@@ -11153,18 +11154,34 @@
   if (!DestPTy->isInteger() && !isa<PointerType>(DestPTy))
     return 0;
   
+  /// NewGEPIndices - If SrcPTy is an aggregate type, we can emit a "noop gep"
+  /// to its first element.  This allows us to handle things like:
+  ///   store i32 xxx, (bitcast {foo*, float}* %P to i32*)
+  /// on 32-bit hosts.
+  SmallVector<Value*, 4> NewGEPIndices;
+  
   // If the source is an array, the code below will not succeed.  Check to
   // see if a trivial 'gep P, 0, 0' will help matters.  Only do this for
   // constants.
-  if (const ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
-    if (Constant *CSrc = dyn_cast<Constant>(CastOp))
-      if (ASrcTy->getNumElements() != 0) {
-        Value* Idxs[2];
-        Idxs[0] = Idxs[1] = Constant::getNullValue(Type::Int32Ty);
-        CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs, 2);
-        SrcTy = cast<PointerType>(CastOp->getType());
-        SrcPTy = SrcTy->getElementType();
+  if (isa<ArrayType>(SrcPTy) || isa<StructType>(SrcPTy)) {
+    // Index through pointer.
+    Constant *Zero = Constant::getNullValue(Type::Int32Ty);
+    NewGEPIndices.push_back(Zero);
+    
+    while (1) {
+      if (const StructType *STy = dyn_cast<StructType>(SrcPTy)) {
+        NewGEPIndices.push_back(Zero);
+        SrcPTy = STy->getElementType(0);
+      } else if (const ArrayType *ATy = dyn_cast<ArrayType>(SrcPTy)) {
+        NewGEPIndices.push_back(Zero);
+        SrcPTy = ATy->getElementType();
+      } else {
+        break;
       }
+    }
+    
+    SrcTy = PointerType::get(SrcPTy, SrcTy->getAddressSpace());
+  }
 
   if (!SrcPTy->isInteger() && !isa<PointerType>(SrcPTy))
     return 0;
@@ -11192,6 +11209,19 @@
     if (isa<PointerType>(SIOp0->getType()))
       opcode = Instruction::PtrToInt;
   }
+  
+  // SIOp0 is a pointer to aggregate and this is a store to the first field,
+  // emit a GEP to index into its first field.
+  if (!NewGEPIndices.empty()) {
+    if (Constant *C = dyn_cast<Constant>(CastOp))
+      CastOp = ConstantExpr::getGetElementPtr(C, &NewGEPIndices[0], 
+                                              NewGEPIndices.size());
+    else
+      CastOp = IC.InsertNewInstBefore(
+              GetElementPtrInst::Create(CastOp, NewGEPIndices.begin(),
+                                        NewGEPIndices.end()), SI);
+  }
+  
   if (Constant *C = dyn_cast<Constant>(SIOp0))
     NewCast = ConstantExpr::getCast(opcode, C, CastDstTy);
   else





More information about the llvm-commits mailing list