[llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp

Chris Lattner sabre at nondot.org
Sun Mar 4 23:53:14 PST 2007



Changes in directory llvm/lib/Transforms/Scalar:

ScalarReplAggregates.cpp updated: 1.75 -> 1.76
---
Log message:

This is the first major step of implementing PR1226: http://llvm.org/PR1226 .  We now successfully
scalarrepl things down to elements, but mem2reg can't promote elements that
are memset/memcpy'd.  Until then, the code is disabled "0 &&".



---
Diffs of the changes:  (+156 -5)

 ScalarReplAggregates.cpp |  161 +++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 156 insertions(+), 5 deletions(-)


Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.75 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.76
--- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.75	Wed Feb 14 21:39:18 2007
+++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp	Mon Mar  5 01:52:57 2007
@@ -24,8 +24,9 @@
 #include "llvm/Constants.h"
 #include "llvm/DerivedTypes.h"
 #include "llvm/Function.h"
-#include "llvm/Pass.h"
 #include "llvm/Instructions.h"
+#include "llvm/IntrinsicInst.h"
+#include "llvm/Pass.h"
 #include "llvm/Analysis/Dominators.h"
 #include "llvm/Target/TargetData.h"
 #include "llvm/Transforms/Utils/PromoteMemToReg.h"
@@ -60,11 +61,15 @@
 
   private:
     int isSafeElementUse(Value *Ptr);
-    int isSafeUseOfAllocation(Instruction *User);
+    int isSafeUseOfAllocation(Instruction *User, AllocationInst *AI);
+    bool isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocationInst *AI);
     int isSafeAllocaToScalarRepl(AllocationInst *AI);
     void CanonicalizeAllocaUsers(AllocationInst *AI);
     AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base);
     
+    void RewriteBitCastUserOfAlloca(BitCastInst *BCInst, AllocationInst *AI,
+                                    SmallVector<AllocaInst*, 32> &NewElts);
+    
     const Type *CanConvertToScalar(Value *V, bool &IsNotTrivial);
     void ConvertToScalar(AllocationInst *AI, const Type *Ty);
     void ConvertUsesToScalar(Value *Ptr, AllocaInst *NewAI, unsigned Offset);
@@ -180,7 +185,7 @@
     DOUT << "Found inst to xform: " << *AI;
     Changed = true;
 
-    std::vector<AllocaInst*> ElementAllocas;
+    SmallVector<AllocaInst*, 32> ElementAllocas;
     if (const StructType *ST = dyn_cast<StructType>(AI->getAllocatedType())) {
       ElementAllocas.reserve(ST->getNumContainedTypes());
       for (unsigned i = 0, e = ST->getNumContainedTypes(); i != e; ++i) {
@@ -207,6 +212,11 @@
     //
     while (!AI->use_empty()) {
       Instruction *User = cast<Instruction>(AI->use_back());
+      if (BitCastInst *BCInst = dyn_cast<BitCastInst>(User)) {
+        RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas);
+        continue;
+      }
+      
       GetElementPtrInst *GEPI = cast<GetElementPtrInst>(User);
       // We now know that the GEP is of the form: GEP <ptr>, 0, <cst>
       unsigned Idx =
@@ -291,7 +301,9 @@
 /// isSafeUseOfAllocation - Check to see if this user is an allowed use for an
 /// aggregate allocation.
 ///
-int SROA::isSafeUseOfAllocation(Instruction *User) {
+int SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI) {
+  if (BitCastInst *C = dyn_cast<BitCastInst>(User))
+    return 0 && (isSafeUseOfBitCastedAllocation(C, AI) ? 3 : 0);
   if (!isa<GetElementPtrInst>(User)) return 0;
 
   GetElementPtrInst *GEPI = cast<GetElementPtrInst>(User);
@@ -352,6 +364,145 @@
   return isSafeElementUse(GEPI);
 }
 
+/// isSafeUseOfBitCastedAllocation - Return true if all users of this bitcast
+/// are 
+bool SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocationInst *AI) {
+  for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end();
+       UI != E; ++UI) {
+    if (BitCastInst *BCU = dyn_cast<BitCastInst>(UI)) {
+      if (!isSafeUseOfBitCastedAllocation(BCU, AI)) 
+        return false;
+    } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(UI)) {
+      // If not constant length, give up.
+      ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
+      if (!Length) return false;
+
+      // If not the whole aggregate, give up.
+      const TargetData &TD = getAnalysis<TargetData>();
+      if (Length->getZExtValue() != 
+          TD.getTypeSize(AI->getType()->getElementType()))
+        return false;
+      
+      // We only know about memcpy/memset/memmove.
+      if (!isa<MemCpyInst>(MI) && !isa<MemSetInst>(MI) &&
+          !isa<MemMoveInst>(MI))
+        return false;
+      // Otherwise, we can transform it.
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+/// RewriteBitCastUserOfAlloca - BCInst (transitively) casts AI.  Transform
+/// users of the cast to use the new values instead.
+void SROA::RewriteBitCastUserOfAlloca(BitCastInst *BCInst, AllocationInst *AI,
+                                      SmallVector<AllocaInst*, 32> &NewElts) {
+  Constant *Zero = Constant::getNullValue(Type::Int32Ty);
+  const TargetData &TD = getAnalysis<TargetData>();
+  while (!BCInst->use_empty()) {
+    if (BitCastInst *BCU = dyn_cast<BitCastInst>(BCInst->use_back())) {
+      RewriteBitCastUserOfAlloca(BCU, AI, NewElts);
+      continue;
+    }
+
+    // Otherwise, must be memcpy/memmove/memset of the entire aggregate.  Split
+    // into one per element.
+    MemIntrinsic *MI = cast<MemIntrinsic>(BCInst->use_back());
+    
+    // If this is a memcpy/memmove, construct the other pointer as the
+    // appropriate type.
+    Value *OtherPtr = 0;
+    if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(MI)) {
+      if (BCInst == MCI->getRawDest())
+        OtherPtr = MCI->getRawSource();
+      else {
+        assert(BCInst == MCI->getRawSource());
+        OtherPtr = MCI->getRawDest();
+      }
+    } else if (MemMoveInst *MMI = dyn_cast<MemMoveInst>(MI)) {
+      if (BCInst == MMI->getRawDest())
+        OtherPtr = MMI->getRawSource();
+      else {
+        assert(BCInst == MMI->getRawSource());
+        OtherPtr = MMI->getRawDest();
+      }
+    }
+    
+    // If there is an other pointer, we want to convert it to the same pointer
+    // type as AI has, so we can GEP through it.
+    if (OtherPtr) {
+      // It is likely that OtherPtr is a bitcast, if so, remove it.
+      if (BitCastInst *BC = dyn_cast<BitCastInst>(OtherPtr))
+        OtherPtr = BC->getOperand(0);
+      if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr))
+        if (BCE->getOpcode() == Instruction::BitCast)
+          OtherPtr = BCE->getOperand(0);
+      
+      // If the pointer is not the right type, insert a bitcast to the right
+      // type.
+      if (OtherPtr->getType() != AI->getType())
+        OtherPtr = new BitCastInst(OtherPtr, AI->getType(), OtherPtr->getName(),
+                                   MI);
+    }
+
+    // Process each element of the aggregate.
+    Value *TheFn = MI->getOperand(0);
+    const Type *BytePtrTy = MI->getRawDest()->getType();
+    bool SROADest = MI->getRawDest() == BCInst;
+
+    for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {
+      // If this is a memcpy/memmove, emit a GEP of the other element address.
+      Value *OtherElt = 0;
+      if (OtherPtr) {
+        OtherElt = new GetElementPtrInst(OtherPtr, Zero,
+                                         ConstantInt::get(Type::Int32Ty, i),
+                                         OtherPtr->getNameStr()+"."+utostr(i),
+                                         MI);
+        if (OtherElt->getType() != BytePtrTy)
+          OtherElt = new BitCastInst(OtherElt, BytePtrTy,OtherElt->getNameStr(),
+                                     MI);
+      }
+
+      Value *EltPtr = NewElts[i];
+      unsigned EltSize =
+        TD.getTypeSize(cast<PointerType>(EltPtr->getType())->getElementType());
+      
+      // Cast the element pointer to BytePtrTy.
+      if (EltPtr->getType() != BytePtrTy)
+        EltPtr = new BitCastInst(EltPtr, BytePtrTy, EltPtr->getNameStr(), MI);
+      
+      
+      // Finally, insert the meminst for this element.
+      if (isa<MemCpyInst>(MI) || isa<MemMoveInst>(MI)) {
+        Value *Ops[] = {
+          SROADest ? EltPtr : OtherElt,  // Dest ptr
+          SROADest ? OtherElt : EltPtr,  // Src ptr
+          ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size
+          Zero  // Align
+        };
+        new CallInst(TheFn, Ops, 4, "", MI);
+      } else if (isa<MemSetInst>(MI)) {
+        Value *Ops[] = {
+          EltPtr, MI->getOperand(2),  // Dest, Value,
+          ConstantInt::get(MI->getOperand(3)->getType(), EltSize), // Size
+          Zero  // Align
+        };
+        new CallInst(TheFn, Ops, 4, "", MI);
+      }
+   }
+
+    // Finally, MI is now dead, as we've modified its actions to occur on all of
+    // the elements of the aggregate.
+    MI->eraseFromParent();
+  }
+  
+  // The cast is dead, remove it.
+  BCInst->eraseFromParent();
+}
+
+
 /// isSafeStructAllocaToScalarRepl - Check to see if the specified allocation of
 /// an aggregate can be broken down into elements.  Return 0 if not, 3 if safe,
 /// or 1 if safe after canonicalization has been performed.
@@ -363,7 +514,7 @@
   int isSafe = 3;
   for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();
        I != E; ++I) {
-    isSafe &= isSafeUseOfAllocation(cast<Instruction>(*I));
+    isSafe &= isSafeUseOfAllocation(cast<Instruction>(*I), AI);
     if (isSafe == 0) {
       DOUT << "Cannot transform: " << *AI << "  due to user: " << **I;
       return 0;






More information about the llvm-commits mailing list