<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">There was a 0-byte test case left, which caused a test suite error. File completely removed in r91277<div><br></div><div><div>
<span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-align: auto; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0; "><span class="Apple-style-span" style="border-collapse: separate; color: rgb(0, 0, 0); font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; "><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div>Shantonu</div><div><br class="webkit-block-placeholder"></div><div>Sent from my MacBook</div></div></span></span>
</div>
<div><br></div><span class="Apple-style-span" style="font-family: Times; "><pre><span class="stdout" style="font-family: 'Courier New', courier, monotype; ">UNRESOLVED: LLVM::Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (4776 of 4969)
******************** TEST 'LLVM::Transforms/ScalarRepl/2009-12-11-NeonTypes.ll' FAILED ********************
Test has no run line!
********************
</span></pre><div><font class="Apple-style-span" face="'Courier New', courier, monotype"><span class="Apple-style-span" style="white-space: pre;"><br></span></font></div></span><div><div>On Dec 13, 2009, at 9:11 PM, Chris Lattner wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: lattner<br>Date: Sun Dec 13 23:11:02 2009<br>New Revision: 91268<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=91268&view=rev">http://llvm.org/viewvc/llvm-project?rev=91268&view=rev</a><br>Log:<br>revert r91184, because it causes a crash on a .bc file I just<br>sent to Bob.<br><br>Modified:<br>    llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>    llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll<br><br>Modified: llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91268&r1=91267&r2=91268&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp?rev=91268&r1=91267&r2=91268&view=diff</a><br><br>==============================================================================<br>--- llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp (original)<br>+++ llvm/trunk/lib/Transforms/Scalar/ScalarReplAggregates.cpp Sun Dec 13 23:11:02 2009<br>@@ -102,27 +102,25 @@<br><br>     int isSafeAllocaToScalarRepl(AllocaInst *AI);<br><br>-    void isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,<br>-                             uint64_t ArrayOffset, AllocaInfo &Info);<br>-    void isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t &Offset,<br>-                   uint64_t &ArrayOffset, AllocaInfo &Info);<br>-    void isSafeMemAccess(AllocaInst *AI, uint64_t Offset, uint64_t ArrayOffset,<br>-                         uint64_t MemSize, const Type *MemOpType, bool isStore,<br>-                         AllocaInfo &Info);<br>-    bool TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size);<br>-    unsigned FindElementAndOffset(const Type *&T, uint64_t &Offset);<br>+    void isSafeUseOfAllocation(Instruction *User, AllocaInst *AI,<br>+                               AllocaInfo &Info);<br>+    void isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI,<br>+                          AllocaInfo &Info);<br>+    void isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI,<br>+                                        unsigned OpNo, AllocaInfo &Info);<br>+    void isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocaInst *AI,<br>+                                        AllocaInfo &Info);<br><br>     void DoScalarReplacement(AllocaInst *AI, <br>                              std::vector<AllocaInst*> &WorkList);<br>     void CleanupGEP(GetElementPtrInst *GEP);<br>-    void CleanupAllocaUsers(Value *V);<br>+    void CleanupAllocaUsers(AllocaInst *AI);<br>     AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocaInst *Base);<br><br>-    void RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,<br>-                              SmallVector<AllocaInst*, 32> &NewElts);<br>-    void RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,<br>-                    SmallVector<AllocaInst*, 32> &NewElts);<br>-    void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,<br>+    void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI,<br>+                                    SmallVector<AllocaInst*, 32> &NewElts);<br>+    <br>+    void RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,<br>                                       AllocaInst *AI,<br>                                       SmallVector<AllocaInst*, 32> &NewElts);<br>     void RewriteStoreUserOfWholeAlloca(StoreInst *SI, AllocaInst *AI,<br>@@ -362,12 +360,176 @@<br>     }<br>   }<br><br>-  // Now that we have created the new alloca instructions, rewrite all the<br>-  // uses of the old alloca.<br>-  RewriteForScalarRepl(AI, AI, 0, ElementAllocas);<br>+  // Now that we have created the alloca instructions that we want to use,<br>+  // expand the getelementptr instructions to use them.<br>+  while (!AI->use_empty()) {<br>+    Instruction *User = cast<Instruction>(AI->use_back());<br>+    if (BitCastInst *BCInst = dyn_cast<BitCastInst>(User)) {<br>+      RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas);<br>+      BCInst->eraseFromParent();<br>+      continue;<br>+    }<br>+    <br>+    // Replace:<br>+    //   %res = load { i32, i32 }* %alloc<br>+    // with:<br>+    //   %load.0 = load i32* %alloc.0<br>+    //   %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0 <br>+    //   %load.1 = load i32* %alloc.1<br>+    //   %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1 <br>+    // (Also works for arrays instead of structs)<br>+    if (LoadInst *LI = dyn_cast<LoadInst>(User)) {<br>+      Value *Insert = UndefValue::get(LI->getType());<br>+      for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) {<br>+        Value *Load = new LoadInst(ElementAllocas[i], "load", LI);<br>+        Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI);<br>+      }<br>+      LI->replaceAllUsesWith(Insert);<br>+      LI->eraseFromParent();<br>+      continue;<br>+    }<br>+<br>+    // Replace:<br>+    //   store { i32, i32 } %val, { i32, i32 }* %alloc<br>+    // with:<br>+    //   %val.0 = extractvalue { i32, i32 } %val, 0 <br>+    //   store i32 %val.0, i32* %alloc.0<br>+    //   %val.1 = extractvalue { i32, i32 } %val, 1 <br>+    //   store i32 %val.1, i32* %alloc.1<br>+    // (Also works for arrays instead of structs)<br>+    if (StoreInst *SI = dyn_cast<StoreInst>(User)) {<br>+      Value *Val = SI->getOperand(0);<br>+      for (unsigned i = 0, e = ElementAllocas.size(); i != e; ++i) {<br>+        Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI);<br>+        new StoreInst(Extract, ElementAllocas[i], SI);<br>+      }<br>+      SI->eraseFromParent();<br>+      continue;<br>+    }<br>+    <br>+    GetElementPtrInst *GEPI = cast<GetElementPtrInst>(User);<br>+    // We now know that the GEP is of the form: GEP <ptr>, 0, <cst><br>+    unsigned Idx =<br>+       (unsigned)cast<ConstantInt>(GEPI->getOperand(2))->getZExtValue();<br>+<br>+    assert(Idx < ElementAllocas.size() && "Index out of range?");<br>+    AllocaInst *AllocaToUse = ElementAllocas[Idx];<br>+<br>+    Value *RepValue;<br>+    if (GEPI->getNumOperands() == 3) {<br>+      // Do not insert a new getelementptr instruction with zero indices, only<br>+      // to have it optimized out later.<br>+      RepValue = AllocaToUse;<br>+    } else {<br>+      // We are indexing deeply into the structure, so we still need a<br>+      // getelement ptr instruction to finish the indexing.  This may be<br>+      // expanded itself once the worklist is rerun.<br>+      //<br>+      SmallVector<Value*, 8> NewArgs;<br>+      NewArgs.push_back(Constant::getNullValue(<br>+                                           Type::getInt32Ty(AI->getContext())));<br>+      NewArgs.append(GEPI->op_begin()+3, GEPI->op_end());<br>+      RepValue = GetElementPtrInst::Create(AllocaToUse, NewArgs.begin(),<br>+                                           NewArgs.end(), "", GEPI);<br>+      RepValue->takeName(GEPI);<br>+    }<br>+    <br>+    // If this GEP is to the start of the aggregate, check for memcpys.<br>+    if (Idx == 0 && GEPI->hasAllZeroIndices())<br>+      RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas);<br>+<br>+    // Move all of the users over to the new GEP.<br>+    GEPI->replaceAllUsesWith(RepValue);<br>+    // Delete the old GEP<br>+    GEPI->eraseFromParent();<br>+  }<br>+<br>+  // Finally, delete the Alloca instruction<br>+  AI->eraseFromParent();<br>   NumReplaced++;<br> }<br>-    <br>+<br>+/// isSafeElementUse - Check to see if this use is an allowed use for a<br>+/// getelementptr instruction of an array aggregate allocation.  isFirstElt<br>+/// indicates whether Ptr is known to the start of the aggregate.<br>+void SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocaInst *AI,<br>+                            AllocaInfo &Info) {<br>+  for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end();<br>+       I != E; ++I) {<br>+    Instruction *User = cast<Instruction>(*I);<br>+    switch (User->getOpcode()) {<br>+    case Instruction::Load:  break;<br>+    case Instruction::Store:<br>+      // Store is ok if storing INTO the pointer, not storing the pointer<br>+      if (User->getOperand(0) == Ptr) return MarkUnsafe(Info);<br>+      break;<br>+    case Instruction::GetElementPtr: {<br>+      GetElementPtrInst *GEP = cast<GetElementPtrInst>(User);<br>+      bool AreAllZeroIndices = isFirstElt;<br>+      if (GEP->getNumOperands() > 1 &&<br>+          (!isa<ConstantInt>(GEP->getOperand(1)) ||<br>+           !cast<ConstantInt>(GEP->getOperand(1))->isZero()))<br>+        // Using pointer arithmetic to navigate the array.<br>+        return MarkUnsafe(Info);<br>+      <br>+      // Verify that any array subscripts are in range.<br>+      for (gep_type_iterator GEPIt = gep_type_begin(GEP),<br>+           E = gep_type_end(GEP); GEPIt != E; ++GEPIt) {<br>+        // Ignore struct elements, no extra checking needed for these.<br>+        if (isa<StructType>(*GEPIt))<br>+          continue;<br>+<br>+        // This GEP indexes an array.  Verify that this is an in-range<br>+        // constant integer. Specifically, consider A[0][i]. We cannot know that<br>+        // the user isn't doing invalid things like allowing i to index an<br>+        // out-of-range subscript that accesses A[1].  Because of this, we have<br>+        // to reject SROA of any accesses into structs where any of the<br>+        // components are variables. <br>+        ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPIt.getOperand());<br>+        if (!IdxVal) return MarkUnsafe(Info);<br>+        <br>+        // Are all indices still zero?<br>+        AreAllZeroIndices &= IdxVal->isZero();<br>+        <br>+        if (const ArrayType *AT = dyn_cast<ArrayType>(*GEPIt)) {<br>+          if (IdxVal->getZExtValue() >= AT->getNumElements())<br>+            return MarkUnsafe(Info);<br>+        } else if (const VectorType *VT = dyn_cast<VectorType>(*GEPIt)) {<br>+          if (IdxVal->getZExtValue() >= VT->getNumElements())<br>+            return MarkUnsafe(Info);<br>+        }<br>+      }<br>+      <br>+      isSafeElementUse(GEP, AreAllZeroIndices, AI, Info);<br>+      if (Info.isUnsafe) return;<br>+      break;<br>+    }<br>+    case Instruction::BitCast:<br>+      if (isFirstElt) {<br>+        isSafeUseOfBitCastedAllocation(cast<BitCastInst>(User), AI, Info);<br>+        if (Info.isUnsafe) return;<br>+        break;<br>+      }<br>+      DEBUG(errs() << "  Transformation preventing inst: " << *User << '\n');<br>+      return MarkUnsafe(Info);<br>+    case Instruction::Call:<br>+      if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(User)) {<br>+        if (isFirstElt) {<br>+          isSafeMemIntrinsicOnAllocation(MI, AI, I.getOperandNo(), Info);<br>+          if (Info.isUnsafe) return;<br>+          break;<br>+        }<br>+      }<br>+      DEBUG(errs() << "  Transformation preventing inst: " << *User << '\n');<br>+      return MarkUnsafe(Info);<br>+    default:<br>+      DEBUG(errs() << "  Transformation preventing inst: " << *User << '\n');<br>+      return MarkUnsafe(Info);<br>+    }<br>+  }<br>+  return;  // All users look ok :)<br>+}<br>+<br> /// AllUsersAreLoads - Return true if all users of this value are loads.<br> static bool AllUsersAreLoads(Value *Ptr) {<br>   for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end();<br>@@ -377,116 +539,72 @@<br>   return true;<br> }<br><br>-/// isSafeForScalarRepl - Check if instruction I is a safe use with regard to<br>-/// performing scalar replacement of alloca AI.  The results are flagged in<br>-/// the Info parameter.  Offset and ArrayOffset indicate the position within<br>-/// AI that is referenced by this instruction.<br>-void SROA::isSafeForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,<br>-                               uint64_t ArrayOffset, AllocaInfo &Info) {<br>-  for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI!=E; ++UI) {<br>-    Instruction *User = cast<Instruction>(*UI);<br>-<br>-    if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) {<br>-      isSafeForScalarRepl(BC, AI, Offset, ArrayOffset, Info);<br>-    } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {<br>-      uint64_t GEPArrayOffset = ArrayOffset;<br>-      uint64_t GEPOffset = Offset;<br>-      isSafeGEP(GEPI, AI, GEPOffset, GEPArrayOffset, Info);<br>-      if (!Info.isUnsafe)<br>-        isSafeForScalarRepl(GEPI, AI, GEPOffset, GEPArrayOffset, Info);<br>-    } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(UI)) {<br>-      ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());<br>-      if (Length)<br>-        isSafeMemAccess(AI, Offset, ArrayOffset, Length->getZExtValue(), 0,<br>-                        UI.getOperandNo() == 1, Info);<br>-      else<br>-        MarkUnsafe(Info);<br>-    } else if (LoadInst *LI = dyn_cast<LoadInst>(User)) {<br>-      if (!LI->isVolatile()) {<br>-        const Type *LIType = LI->getType();<br>-        isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(LIType),<br>-                        LIType, false, Info);<br>-      } else<br>-        MarkUnsafe(Info);<br>-    } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {<br>-      // Store is ok if storing INTO the pointer, not storing the pointer<br>-      if (!SI->isVolatile() && SI->getOperand(0) != I) {<br>-        const Type *SIType = SI->getOperand(0)->getType();<br>-        isSafeMemAccess(AI, Offset, ArrayOffset, TD->getTypeAllocSize(SIType),<br>-                        SIType, true, Info);<br>-      } else<br>-        MarkUnsafe(Info);<br>-    } else if (isa<DbgInfoIntrinsic>(UI)) {<br>-      // If one user is DbgInfoIntrinsic then check if all users are<br>-      // DbgInfoIntrinsics.<br>-      if (OnlyUsedByDbgInfoIntrinsics(I)) {<br>-        Info.needsCleanup = true;<br>-        return;<br>-      }<br>-      MarkUnsafe(Info);<br>-    } else {<br>-      DEBUG(errs() << "  Transformation preventing inst: " << *User << '\n');<br>-      MarkUnsafe(Info);<br>-    }<br>-    if (Info.isUnsafe) return;<br>-  }<br>-}<br>+/// isSafeUseOfAllocation - Check if this user is an allowed use for an<br>+/// aggregate allocation.<br>+void SROA::isSafeUseOfAllocation(Instruction *User, AllocaInst *AI,<br>+                                 AllocaInfo &Info) {<br>+  if (BitCastInst *C = dyn_cast<BitCastInst>(User))<br>+    return isSafeUseOfBitCastedAllocation(C, AI, Info);<br>+<br>+  if (LoadInst *LI = dyn_cast<LoadInst>(User))<br>+    if (!LI->isVolatile())<br>+      return;// Loads (returning a first class aggregrate) are always rewritable<br>+<br>+  if (StoreInst *SI = dyn_cast<StoreInst>(User))<br>+    if (!SI->isVolatile() && SI->getOperand(0) != AI)<br>+      return;// Store is ok if storing INTO the pointer, not storing the pointer<br>+ <br>+  GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User);<br>+  if (GEPI == 0)<br>+    return MarkUnsafe(Info);<br><br>-/// isSafeGEP - Check if a GEP instruction can be handled for scalar<br>-/// replacement.  It is safe when all the indices are constant, in-bounds<br>-/// references, and when the resulting offset corresponds to an element within<br>-/// the alloca type.  The results are flagged in the Info parameter.  Upon<br>-/// return, Offset is adjusted as specified by the GEP indices.  For the<br>-/// special case of a variable index to a 2-element array, ArrayOffset is set<br>-/// to the array element size.<br>-void SROA::isSafeGEP(GetElementPtrInst *GEPI, AllocaInst *AI,<br>-                     uint64_t &Offset, uint64_t &ArrayOffset,<br>-                     AllocaInfo &Info) {<br>-  gep_type_iterator GEPIt = gep_type_begin(GEPI), E = gep_type_end(GEPI);<br>-  if (GEPIt == E)<br>-    return;<br>+  gep_type_iterator I = gep_type_begin(GEPI), E = gep_type_end(GEPI);<br><br>-  // The first GEP index must be zero.<br>-  if (!isa<ConstantInt>(GEPIt.getOperand()) ||<br>-      !cast<ConstantInt>(GEPIt.getOperand())->isZero())<br>+  // The GEP is not safe to transform if not of the form "GEP <ptr>, 0, <cst>".<br>+  if (I == E ||<br>+      I.getOperand() != Constant::getNullValue(I.getOperand()->getType())) {<br>     return MarkUnsafe(Info);<br>-  if (++GEPIt == E)<br>-    return;<br>+  }<br>+<br>+  ++I;<br>+  if (I == E) return MarkUnsafe(Info);  // ran out of GEP indices??<br><br>+  bool IsAllZeroIndices = true;<br>+  <br>   // If the first index is a non-constant index into an array, see if we can<br>   // handle it as a special case.<br>-  const Type *ArrayEltTy = 0;<br>-  if (ArrayOffset == 0 && Offset == 0) {<br>-    if (const ArrayType *AT = dyn_cast<ArrayType>(*GEPIt)) {<br>-      if (!isa<ConstantInt>(GEPIt.getOperand())) {<br>-        uint64_t NumElements = AT->getNumElements();<br>-<br>-        // If this is an array index and the index is not constant, we cannot<br>-        // promote... that is unless the array has exactly one or two elements<br>-        // in it, in which case we CAN promote it, but we have to canonicalize<br>-        // this out if this is the only problem.<br>-        if ((NumElements != 1 && NumElements != 2) || !AllUsersAreLoads(GEPI))<br>-          return MarkUnsafe(Info);<br>+  if (const ArrayType *AT = dyn_cast<ArrayType>(*I)) {<br>+    if (!isa<ConstantInt>(I.getOperand())) {<br>+      IsAllZeroIndices = 0;<br>+      uint64_t NumElements = AT->getNumElements();<br>+      <br>+      // If this is an array index and the index is not constant, we cannot<br>+      // promote... that is unless the array has exactly one or two elements in<br>+      // it, in which case we CAN promote it, but we have to canonicalize this<br>+      // out if this is the only problem.<br>+      if ((NumElements == 1 || NumElements == 2) &&<br>+          AllUsersAreLoads(GEPI)) {<br>         Info.needsCleanup = true;<br>-        ArrayOffset = TD->getTypeAllocSizeInBits(AT->getElementType());<br>-        ArrayEltTy = AT->getElementType();<br>-        ++GEPIt;<br>+        return;  // Canonicalization required!<br>       }<br>+      return MarkUnsafe(Info);<br>     }<br>   }<br>-<br>+ <br>   // Walk through the GEP type indices, checking the types that this indexes<br>   // into.<br>-  for (; GEPIt != E; ++GEPIt) {<br>+  for (; I != E; ++I) {<br>     // Ignore struct elements, no extra checking needed for these.<br>-    if (isa<StructType>(*GEPIt))<br>+    if (isa<StructType>(*I))<br>       continue;<br>+    <br>+    ConstantInt *IdxVal = dyn_cast<ConstantInt>(I.getOperand());<br>+    if (!IdxVal) return MarkUnsafe(Info);<br><br>-    ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPIt.getOperand());<br>-    if (!IdxVal)<br>-      return MarkUnsafe(Info);<br>-<br>-    if (const ArrayType *AT = dyn_cast<ArrayType>(*GEPIt)) {<br>+    // Are all indices still zero?<br>+    IsAllZeroIndices &= IdxVal->isZero();<br>+    <br>+    if (const ArrayType *AT = dyn_cast<ArrayType>(*I)) {<br>       // This GEP indexes an array.  Verify that this is an in-range constant<br>       // integer. Specifically, consider A[0][i]. We cannot know that the user<br>       // isn't doing invalid things like allowing i to index an out-of-range<br>@@ -494,254 +612,144 @@<br>       // of any accesses into structs where any of the components are variables.<br>       if (IdxVal->getZExtValue() >= AT->getNumElements())<br>         return MarkUnsafe(Info);<br>-    } else {<br>-      const VectorType *VT = dyn_cast<VectorType>(*GEPIt);<br>-      assert(VT && "unexpected type in GEP type iterator");<br>+    } else if (const VectorType *VT = dyn_cast<VectorType>(*I)) {<br>       if (IdxVal->getZExtValue() >= VT->getNumElements())<br>         return MarkUnsafe(Info);<br>     }<br>   }<br>-<br>-  // All the indices are safe.  Now compute the offset due to this GEP and<br>-  // check if the alloca has a component element at that offset.<br>-  if (ArrayOffset == 0) {<br>-    SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end());<br>-    Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(),<br>-                                   &Indices[0], Indices.size());<br>-  } else {<br>-    // Both array elements have the same type, so it suffices to check one of<br>-    // them.  Copy the GEP indices starting from the array index, but replace<br>-    // that variable index with a constant zero.<br>-    SmallVector<Value*, 8> Indices(GEPI->op_begin() + 2, GEPI->op_end());<br>-    Indices[0] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext()));<br>-    const Type *ArrayEltPtr = PointerType::getUnqual(ArrayEltTy);<br>-    Offset += TD->getIndexedOffset(ArrayEltPtr, &Indices[0], Indices.size());<br>-  }<br>-  if (!TypeHasComponent(AI->getAllocatedType(), Offset, 0))<br>-    MarkUnsafe(Info);<br>-}<br>-<br>-/// isSafeMemAccess - Check if a load/store/memcpy operates on the entire AI<br>-/// alloca or has an offset and size that corresponds to a component element<br>-/// within it.  The offset checked here may have been formed from a GEP with a<br>-/// pointer bitcasted to a different type.<br>-void SROA::isSafeMemAccess(AllocaInst *AI, uint64_t Offset,<br>-                           uint64_t ArrayOffset, uint64_t MemSize,<br>-                           const Type *MemOpType, bool isStore,<br>-                           AllocaInfo &Info) {<br>-  // Check if this is a load/store of the entire alloca.<br>-  if (Offset == 0 && ArrayOffset == 0 &&<br>-      MemSize == TD->getTypeAllocSize(AI->getAllocatedType())) {<br>-    bool UsesAggregateType = (MemOpType == AI->getAllocatedType());<br>-    // This is safe for MemIntrinsics (where MemOpType is 0), integer types<br>-    // (which are essentially the same as the MemIntrinsics, especially with<br>-    // regard to copying padding between elements), or references using the<br>-    // aggregate type of the alloca.<br>-    if (!MemOpType || isa<IntegerType>(MemOpType) || UsesAggregateType) {<br>-      if (!UsesAggregateType) {<br>-        if (isStore)<br>-          Info.isMemCpyDst = true;<br>-        else<br>-          Info.isMemCpySrc = true;<br>-      }<br>-      return;<br>-    }<br>-  }<br>-  // Check if the offset/size correspond to a component within the alloca type.<br>-  const Type *T = AI->getAllocatedType();<br>-  if (TypeHasComponent(T, Offset, MemSize) &&<br>-      (ArrayOffset == 0 || TypeHasComponent(T, Offset + ArrayOffset, MemSize)))<br>-    return;<br>-<br>-  return MarkUnsafe(Info);<br>+  <br>+  // If there are any non-simple uses of this getelementptr, make sure to reject<br>+  // them.<br>+  return isSafeElementUse(GEPI, IsAllZeroIndices, AI, Info);<br> }<br><br>-/// TypeHasComponent - Return true if T has a component type with the<br>-/// specified offset and size.  If Size is zero, do not check the size.<br>-bool SROA::TypeHasComponent(const Type *T, uint64_t Offset, uint64_t Size) {<br>-  const Type *EltTy;<br>-  uint64_t EltSize;<br>-  if (const StructType *ST = dyn_cast<StructType>(T)) {<br>-    const StructLayout *Layout = TD->getStructLayout(ST);<br>-    unsigned EltIdx = Layout->getElementContainingOffset(Offset);<br>-    EltTy = ST->getContainedType(EltIdx);<br>-    EltSize = TD->getTypeAllocSize(EltTy);<br>-    Offset -= Layout->getElementOffset(EltIdx);<br>-  } else if (const ArrayType *AT = dyn_cast<ArrayType>(T)) {<br>-    EltTy = AT->getElementType();<br>-    EltSize = TD->getTypeAllocSize(EltTy);<br>-    Offset %= EltSize;<br>-  } else {<br>-    return false;<br>+/// isSafeMemIntrinsicOnAllocation - Check if the specified memory<br>+/// intrinsic can be promoted by SROA.  At this point, we know that the operand<br>+/// of the memintrinsic is a pointer to the beginning of the allocation.<br>+void SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocaInst *AI,<br>+                                          unsigned OpNo, AllocaInfo &Info) {<br>+  // If not constant length, give up.<br>+  ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());<br>+  if (!Length) return MarkUnsafe(Info);<br>+  <br>+  // If not the whole aggregate, give up.<br>+  if (Length->getZExtValue() !=<br>+      TD->getTypeAllocSize(AI->getType()->getElementType()))<br>+    return MarkUnsafe(Info);<br>+  <br>+  // We only know about memcpy/memset/memmove.<br>+  if (!isa<MemIntrinsic>(MI))<br>+    return MarkUnsafe(Info);<br>+  <br>+  // Otherwise, we can transform it.  Determine whether this is a memcpy/set<br>+  // into or out of the aggregate.<br>+  if (OpNo == 1)<br>+    Info.isMemCpyDst = true;<br>+  else {<br>+    assert(OpNo == 2);<br>+    Info.isMemCpySrc = true;<br>   }<br>-  if (Offset == 0 && (Size == 0 || EltSize == Size))<br>-    return true;<br>-  // Check if the component spans multiple elements.<br>-  if (Offset + Size > EltSize)<br>-    return false;<br>-  return TypeHasComponent(EltTy, Offset, Size);<br> }<br><br>-/// RewriteForScalarRepl - Alloca AI is being split into NewElts, so rewrite<br>-/// the instruction I, which references it, to use the separate elements.<br>-/// Offset indicates the position within AI that is referenced by this<br>-/// instruction.<br>-void SROA::RewriteForScalarRepl(Instruction *I, AllocaInst *AI, uint64_t Offset,<br>-                                SmallVector<AllocaInst*, 32> &NewElts) {<br>-  for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; ) {<br>-    Instruction *User = cast<Instruction>(*UI++);<br>+/// isSafeUseOfBitCastedAllocation - Check if all users of this bitcast<br>+/// from an alloca are safe for SROA of that alloca.<br>+void SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocaInst *AI,<br>+                                          AllocaInfo &Info) {<br>+  for (Value::use_iterator UI = BC->use_begin(), E = BC->use_end();<br>+       UI != E; ++UI) {<br>+    if (BitCastInst *BCU = dyn_cast<BitCastInst>(UI)) {<br>+      isSafeUseOfBitCastedAllocation(BCU, AI, Info);<br>+    } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(UI)) {<br>+      isSafeMemIntrinsicOnAllocation(MI, AI, UI.getOperandNo(), Info);<br>+    } else if (StoreInst *SI = dyn_cast<StoreInst>(UI)) {<br>+      if (SI->isVolatile())<br>+        return MarkUnsafe(Info);<br>+      <br>+      // If storing the entire alloca in one chunk through a bitcasted pointer<br>+      // to integer, we can transform it.  This happens (for example) when you<br>+      // cast a {i32,i32}* to i64* and store through it.  This is similar to the<br>+      // memcpy case and occurs in various "byval" cases and emulated memcpys.<br>+      if (isa<IntegerType>(SI->getOperand(0)->getType()) &&<br>+          TD->getTypeAllocSize(SI->getOperand(0)->getType()) ==<br>+          TD->getTypeAllocSize(AI->getType()->getElementType())) {<br>+        Info.isMemCpyDst = true;<br>+        continue;<br>+      }<br>+      return MarkUnsafe(Info);<br>+    } else if (LoadInst *LI = dyn_cast<LoadInst>(UI)) {<br>+      if (LI->isVolatile())<br>+        return MarkUnsafe(Info);<br><br>-    if (BitCastInst *BC = dyn_cast<BitCastInst>(User)) {<br>-      if (BC->getOperand(0) == AI)<br>-        BC->setOperand(0, NewElts[0]);<br>-      // If the bitcast type now matches the operand type, it will be removed<br>-      // after processing its uses.<br>-      RewriteForScalarRepl(BC, AI, Offset, NewElts);<br>-    } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(User)) {<br>-      RewriteGEP(GEPI, AI, Offset, NewElts);<br>-    } else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(User)) {<br>-      ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());<br>-      uint64_t MemSize = Length->getZExtValue();<br>-      if (Offset == 0 &&<br>-          MemSize == TD->getTypeAllocSize(AI->getAllocatedType()))<br>-        RewriteMemIntrinUserOfAlloca(MI, I, AI, NewElts);<br>-    } else if (LoadInst *LI = dyn_cast<LoadInst>(User)) {<br>-      const Type *LIType = LI->getType();<br>-      if (LIType == AI->getAllocatedType()) {<br>-        // Replace:<br>-        //   %res = load { i32, i32 }* %alloc<br>-        // with:<br>-        //   %load.0 = load i32* %alloc.0<br>-        //   %insert.0 insertvalue { i32, i32 } zeroinitializer, i32 %load.0, 0<br>-        //   %load.1 = load i32* %alloc.1<br>-        //   %insert = insertvalue { i32, i32 } %insert.0, i32 %load.1, 1<br>-        // (Also works for arrays instead of structs)<br>-        Value *Insert = UndefValue::get(LIType);<br>-        for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {<br>-          Value *Load = new LoadInst(NewElts[i], "load", LI);<br>-          Insert = InsertValueInst::Create(Insert, Load, i, "insert", LI);<br>-        }<br>-        LI->replaceAllUsesWith(Insert);<br>-        LI->eraseFromParent();<br>-      } else if (isa<IntegerType>(LIType) &&<br>-                 TD->getTypeAllocSize(LIType) ==<br>-                 TD->getTypeAllocSize(AI->getAllocatedType())) {<br>-        // If this is a load of the entire alloca to an integer, rewrite it.<br>-        RewriteLoadUserOfWholeAlloca(LI, AI, NewElts);<br>+      // If loading the entire alloca in one chunk through a bitcasted pointer<br>+      // to integer, we can transform it.  This happens (for example) when you<br>+      // cast a {i32,i32}* to i64* and load through it.  This is similar to the<br>+      // memcpy case and occurs in various "byval" cases and emulated memcpys.<br>+      if (isa<IntegerType>(LI->getType()) &&<br>+          TD->getTypeAllocSize(LI->getType()) ==<br>+          TD->getTypeAllocSize(AI->getType()->getElementType())) {<br>+        Info.isMemCpySrc = true;<br>+        continue;<br>       }<br>-    } else if (StoreInst *SI = dyn_cast<StoreInst>(User)) {<br>-      Value *Val = SI->getOperand(0);<br>-      const Type *SIType = Val->getType();<br>-      if (SIType == AI->getAllocatedType()) {<br>-        // Replace:<br>-        //   store { i32, i32 } %val, { i32, i32 }* %alloc<br>-        // with:<br>-        //   %val.0 = extractvalue { i32, i32 } %val, 0<br>-        //   store i32 %val.0, i32* %alloc.0<br>-        //   %val.1 = extractvalue { i32, i32 } %val, 1<br>-        //   store i32 %val.1, i32* %alloc.1<br>-        // (Also works for arrays instead of structs)<br>-        for (unsigned i = 0, e = NewElts.size(); i != e; ++i) {<br>-          Value *Extract = ExtractValueInst::Create(Val, i, Val->getName(), SI);<br>-          new StoreInst(Extract, NewElts[i], SI);<br>-        }<br>-        SI->eraseFromParent();<br>-      } else if (isa<IntegerType>(SIType) &&<br>-                 TD->getTypeAllocSize(SIType) ==<br>-                 TD->getTypeAllocSize(AI->getAllocatedType())) {<br>-        // If this is a store of the entire alloca from an integer, rewrite it.<br>-        RewriteStoreUserOfWholeAlloca(SI, AI, NewElts);<br>+      return MarkUnsafe(Info);<br>+    } else if (isa<DbgInfoIntrinsic>(UI)) {<br>+      // If one user is DbgInfoIntrinsic then check if all users are<br>+      // DbgInfoIntrinsics.<br>+      if (OnlyUsedByDbgInfoIntrinsics(BC)) {<br>+        Info.needsCleanup = true;<br>+        return;<br>       }<br>+      else<br>+        MarkUnsafe(Info);<br>     }<br>-  }<br>-  // Delete unused instructions and identity bitcasts.<br>-  if (I->use_empty())<br>-    I->eraseFromParent();<br>-  else if (BitCastInst *BC = dyn_cast<BitCastInst>(I)) {<br>-    if (BC->getDestTy() == BC->getSrcTy()) {<br>-      BC->replaceAllUsesWith(BC->getOperand(0));<br>-      BC->eraseFromParent();<br>+    else {<br>+      return MarkUnsafe(Info);<br>     }<br>+    if (Info.isUnsafe) return;<br>   }<br> }<br><br>-/// FindElementAndOffset - Return the index of the element containing Offset<br>-/// within the specified type, which must be either a struct or an array.<br>-/// Sets T to the type of the element and Offset to the offset within that<br>-/// element.<br>-unsigned SROA::FindElementAndOffset(const Type *&T, uint64_t &Offset) {<br>-  unsigned Idx = 0;<br>-  if (const StructType *ST = dyn_cast<StructType>(T)) {<br>-    const StructLayout *Layout = TD->getStructLayout(ST);<br>-    Idx = Layout->getElementContainingOffset(Offset);<br>-    T = ST->getContainedType(Idx);<br>-    Offset -= Layout->getElementOffset(Idx);<br>-  } else {<br>-    const ArrayType *AT = dyn_cast<ArrayType>(T);<br>-    assert(AT && "unexpected type for scalar replacement");<br>-    T = AT->getElementType();<br>-    uint64_t EltSize = TD->getTypeAllocSize(T);<br>-    Idx = (unsigned)(Offset / EltSize);<br>-    Offset -= Idx * EltSize;<br>-  }<br>-  return Idx;<br>-}<br>-<br>-/// RewriteGEP - Check if this GEP instruction moves the pointer across<br>-/// elements of the alloca that are being split apart, and if so, rewrite<br>-/// the GEP to be relative to the new element.<br>-void SROA::RewriteGEP(GetElementPtrInst *GEPI, AllocaInst *AI, uint64_t Offset,<br>-                      SmallVector<AllocaInst*, 32> &NewElts) {<br>-  Instruction *Val = GEPI;<br>-<br>-  uint64_t OldOffset = Offset;<br>-  SmallVector<Value*, 8> Indices(GEPI->op_begin() + 1, GEPI->op_end());<br>-  Offset += TD->getIndexedOffset(GEPI->getPointerOperandType(),<br>-                                 &Indices[0], Indices.size());<br>-<br>-  const Type *T = AI->getAllocatedType();<br>-  unsigned OldIdx = FindElementAndOffset(T, OldOffset);<br>-  if (GEPI->getOperand(0) == AI)<br>-    OldIdx = ~0U; // Force the GEP to be rewritten.<br>-<br>-  T = AI->getAllocatedType();<br>-  uint64_t EltOffset = Offset;<br>-  unsigned Idx = FindElementAndOffset(T, EltOffset);<br>-<br>-  // If this GEP moves the pointer across elements of the alloca that are<br>-  // being split, then it needs to be rewritten.<br>-  if (Idx != OldIdx) {<br>-    const Type *i32Ty = Type::getInt32Ty(AI->getContext());<br>-    SmallVector<Value*, 8> NewArgs;<br>-    NewArgs.push_back(Constant::getNullValue(i32Ty));<br>-    while (EltOffset != 0) {<br>-      unsigned EltIdx = FindElementAndOffset(T, EltOffset);<br>-      NewArgs.push_back(ConstantInt::get(i32Ty, EltIdx));<br>-    }<br>-    if (NewArgs.size() > 1) {<br>-      Val = GetElementPtrInst::CreateInBounds(NewElts[Idx], NewArgs.begin(),<br>-                                              NewArgs.end(), "", GEPI);<br>-      Val->takeName(GEPI);<br>-      if (Val->getType() != GEPI->getType())<br>-        Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI);<br>-    } else {<br>-      Val = NewElts[Idx];<br>-      // Insert a new bitcast.  If the types match, it will be removed after<br>-      // handling all of its uses.<br>-      Val = new BitCastInst(Val, GEPI->getType(), Val->getNameStr(), GEPI);<br>-      Val->takeName(GEPI);<br>+/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes<br>+/// to its first element.  Transform users of the cast to use the new values<br>+/// instead.<br>+void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocaInst *AI,<br>+                                      SmallVector<AllocaInst*, 32> &NewElts) {<br>+  Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end();<br>+  while (UI != UE) {<br>+    Instruction *User = cast<Instruction>(*UI++);<br>+    if (BitCastInst *BCU = dyn_cast<BitCastInst>(User)) {<br>+      RewriteBitCastUserOfAlloca(BCU, AI, NewElts);<br>+      if (BCU->use_empty()) BCU->eraseFromParent();<br>+      continue;<br>     }<br><br>-    GEPI->replaceAllUsesWith(Val);<br>-    GEPI->eraseFromParent();<br>-  }<br>+    if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(User)) {<br>+      // This must be memcpy/memmove/memset of the entire aggregate.<br>+      // Split into one per element.<br>+      RewriteMemIntrinUserOfAlloca(MI, BCInst, AI, NewElts);<br>+      continue;<br>+    }<br>+      <br>+    if (StoreInst *SI = dyn_cast<StoreInst>(User)) {<br>+      // If this is a store of the entire alloca from an integer, rewrite it.<br>+      RewriteStoreUserOfWholeAlloca(SI, AI, NewElts);<br>+      continue;<br>+    }<br><br>-  RewriteForScalarRepl(Val, AI, Offset, NewElts);<br>+    if (LoadInst *LI = dyn_cast<LoadInst>(User)) {<br>+      // If this is a load of the entire alloca to an integer, rewrite it.<br>+      RewriteLoadUserOfWholeAlloca(LI, AI, NewElts);<br>+      continue;<br>+    }<br>+    <br>+    // Otherwise it must be some other user of a gep of the first pointer.  Just<br>+    // leave these alone.<br>+    continue;<br>+  }<br> }<br><br> /// RewriteMemIntrinUserOfAlloca - MI is a memcpy/memset/memmove from or to AI.<br> /// Rewrite it to copy or set the elements of the scalarized memory.<br>-void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *Inst,<br>+void SROA::RewriteMemIntrinUserOfAlloca(MemIntrinsic *MI, Instruction *BCInst,<br>                                         AllocaInst *AI,<br>                                         SmallVector<AllocaInst*, 32> &NewElts) {<br><br>@@ -753,10 +761,10 @@<br>   LLVMContext &Context = MI->getContext();<br>   unsigned MemAlignment = MI->getAlignment();<br>   if (MemTransferInst *MTI = dyn_cast<MemTransferInst>(MI)) { // memmove/memcopy<br>-    if (Inst == MTI->getRawDest())<br>+    if (BCInst == MTI->getRawDest())<br>       OtherPtr = MTI->getRawSource();<br>     else {<br>-      assert(Inst == MTI->getRawSource());<br>+      assert(BCInst == MTI->getRawSource());<br>       OtherPtr = MTI->getRawDest();<br>     }<br>   }<br>@@ -790,7 +798,7 @@<br>   // Process each element of the aggregate.<br>   Value *TheFn = MI->getOperand(0);<br>   const Type *BytePtrTy = MI->getRawDest()->getType();<br>-  bool SROADest = MI->getRawDest() == Inst;<br>+  bool SROADest = MI->getRawDest() == BCInst;<br><br>   Constant *Zero = Constant::getNullValue(Type::getInt32Ty(MI->getContext()));<br><br>@@ -802,9 +810,9 @@<br>     if (OtherPtr) {<br>       Value *Idx[2] = { Zero,<br>                       ConstantInt::get(Type::getInt32Ty(MI->getContext()), i) };<br>-      OtherElt = GetElementPtrInst::CreateInBounds(OtherPtr, Idx, Idx + 2,<br>+      OtherElt = GetElementPtrInst::Create(OtherPtr, Idx, Idx + 2,<br>                                            OtherPtr->getNameStr()+"."+Twine(i),<br>-                                                   MI);<br>+                                           MI);<br>       uint64_t EltOffset;<br>       const PointerType *OtherPtrTy = cast<PointerType>(OtherPtr->getType());<br>       if (const StructType *ST =<br>@@ -929,9 +937,15 @@<br>   // Extract each element out of the integer according to its structure offset<br>   // and store the element value to the individual alloca.<br>   Value *SrcVal = SI->getOperand(0);<br>-  const Type *AllocaEltTy = AI->getAllocatedType();<br>+  const Type *AllocaEltTy = AI->getType()->getElementType();<br>   uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy);<br><br>+  // If this isn't a store of an integer to the whole alloca, it may be a store<br>+  // to the first element.  Just ignore the store in this case and normal SROA<br>+  // will handle it.<br>+  if (!isa<IntegerType>(SrcVal->getType()) ||<br>+      TD->getTypeAllocSizeInBits(SrcVal->getType()) != AllocaSizeBits)<br>+    return;<br>   // Handle tail padding by extending the operand<br>   if (TD->getTypeSizeInBits(SrcVal->getType()) != AllocaSizeBits)<br>     SrcVal = new ZExtInst(SrcVal,<br>@@ -1045,9 +1059,16 @@<br>                                         SmallVector<AllocaInst*, 32> &NewElts) {<br>   // Extract each element out of the NewElts according to its structure offset<br>   // and form the result value.<br>-  const Type *AllocaEltTy = AI->getAllocatedType();<br>+  const Type *AllocaEltTy = AI->getType()->getElementType();<br>   uint64_t AllocaSizeBits = TD->getTypeAllocSizeInBits(AllocaEltTy);<br><br>+  // If this isn't a load of the whole alloca to an integer, it may be a load<br>+  // of the first element.  Just ignore the load in this case and normal SROA<br>+  // will handle it.<br>+  if (!isa<IntegerType>(LI->getType()) ||<br>+      TD->getTypeAllocSizeInBits(LI->getType()) != AllocaSizeBits)<br>+    return;<br>+  <br>   DEBUG(errs() << "PROMOTING LOAD OF WHOLE ALLOCA: " << *AI << '\n' << *LI<br>                << '\n');<br><br>@@ -1121,6 +1142,7 @@<br>   LI->eraseFromParent();<br> }<br><br>+<br> /// HasPadding - Return true if the specified type has any structure or<br> /// alignment padding, false otherwise.<br> static bool HasPadding(const Type *Ty, const TargetData &TD) {<br>@@ -1170,10 +1192,14 @@<br>   // the users are safe to transform.<br>   AllocaInfo Info;<br><br>-  isSafeForScalarRepl(AI, AI, 0, 0, Info);<br>-  if (Info.isUnsafe) {<br>-    DEBUG(errs() << "Cannot transform: " << *AI << '\n');<br>-    return 0;<br>+  for (Value::use_iterator I = AI->use_begin(), E = AI->use_end();<br>+       I != E; ++I) {<br>+    isSafeUseOfAllocation(cast<Instruction>(*I), AI, Info);<br>+    if (Info.isUnsafe) {<br>+      DEBUG(errs() << "Cannot transform: " << *AI << "\n  due to user: "<br>+                   << **I << '\n');<br>+      return 0;<br>+    }<br>   }<br><br>   // Okay, we know all the users are promotable.  If the aggregate is a memcpy<br>@@ -1182,7 +1208,7 @@<br>   // types, but may actually be used.  In these cases, we refuse to promote the<br>   // struct.<br>   if (Info.isMemCpySrc && Info.isMemCpyDst &&<br>-      HasPadding(AI->getAllocatedType(), *TD))<br>+      HasPadding(AI->getType()->getElementType(), *TD))<br>     return 0;<br><br>   // If we require cleanup, return 1, otherwise return 3.<br>@@ -1219,15 +1245,15 @@<br>   // Insert the new GEP instructions, which are properly indexed.<br>   SmallVector<Value*, 8> Indices(GEPI->op_begin()+1, GEPI->op_end());<br>   Indices[1] = Constant::getNullValue(Type::getInt32Ty(GEPI->getContext()));<br>-  Value *ZeroIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0),<br>-                                                     Indices.begin(),<br>-                                                     Indices.end(),<br>-                                                     GEPI->getName()+".0",GEPI);<br>+  Value *ZeroIdx = GetElementPtrInst::Create(GEPI->getOperand(0),<br>+                                             Indices.begin(),<br>+                                             Indices.end(),<br>+                                             GEPI->getName()+".0", GEPI);<br>   Indices[1] = ConstantInt::get(Type::getInt32Ty(GEPI->getContext()), 1);<br>-  Value *OneIdx = GetElementPtrInst::CreateInBounds(GEPI->getOperand(0),<br>-                                                    Indices.begin(),<br>-                                                    Indices.end(),<br>-                                                    GEPI->getName()+".1", GEPI);<br>+  Value *OneIdx = GetElementPtrInst::Create(GEPI->getOperand(0),<br>+                                            Indices.begin(),<br>+                                            Indices.end(),<br>+                                            GEPI->getName()+".1", GEPI);<br>   // Replace all loads of the variable index GEP with loads from both<br>   // indexes and a select.<br>   while (!GEPI->use_empty()) {<br>@@ -1238,24 +1264,22 @@<br>     LI->replaceAllUsesWith(R);<br>     LI->eraseFromParent();<br>   }<br>+  GEPI->eraseFromParent();<br> }<br><br>+<br> /// CleanupAllocaUsers - If SROA reported that it can promote the specified<br> /// allocation, but only if cleaned up, perform the cleanups required.<br>-void SROA::CleanupAllocaUsers(Value *V) {<br>+void SROA::CleanupAllocaUsers(AllocaInst *AI) {<br>   // At this point, we know that the end result will be SROA'd and promoted, so<br>   // we can insert ugly code if required so long as sroa+mem2reg will clean it<br>   // up.<br>-  for (Value::use_iterator UI = V->use_begin(), E = V->use_end();<br>+  for (Value::use_iterator UI = AI->use_begin(), E = AI->use_end();<br>        UI != E; ) {<br>     User *U = *UI++;<br>-    if (isa<BitCastInst>(U)) {<br>-      CleanupAllocaUsers(U);<br>-    } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {<br>+    if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U))<br>       CleanupGEP(GEPI);<br>-      CleanupAllocaUsers(GEPI);<br>-      if (GEPI->use_empty()) GEPI->eraseFromParent();<br>-    } else {<br>+    else {<br>       Instruction *I = cast<Instruction>(U);<br>       SmallVector<DbgInfoIntrinsic *, 2> DbgInUses;<br>       if (!isa<StoreInst>(I) && OnlyUsedByDbgInfoIntrinsics(I, &DbgInUses)) {<br>@@ -1371,7 +1395,7 @@<br><br>       // Compute the offset that this GEP adds to the pointer.<br>       SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end());<br>-      uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(),<br>+      uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(),<br>                                                 &Indices[0], Indices.size());<br>       // See if all uses can be converted.<br>       if (!CanConvertToScalar(GEP, IsNotTrivial, VecTy, SawVec,Offset+GEPOffset,<br>@@ -1433,7 +1457,7 @@<br>     if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(User)) {<br>       // Compute the offset that this GEP adds to the pointer.<br>       SmallVector<Value*, 8> Indices(GEP->op_begin()+1, GEP->op_end());<br>-      uint64_t GEPOffset = TD->getIndexedOffset(GEP->getPointerOperandType(),<br>+      uint64_t GEPOffset = TD->getIndexedOffset(GEP->getOperand(0)->getType(),<br>                                                 &Indices[0], Indices.size());<br>       ConvertUsesToScalar(GEP, NewAI, Offset+GEPOffset*8);<br>       GEP->eraseFromParent();<br><br>Modified: llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll<br>URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91268&r1=91267&r2=91268&view=diff">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll?rev=91268&r1=91267&r2=91268&view=diff</a><br><br>==============================================================================<br>--- llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll (original)<br>+++ llvm/trunk/test/Transforms/ScalarRepl/2009-12-11-NeonTypes.ll Sun Dec 13 23:11:02 2009<br>@@ -1,68 +0,0 @@<br>-; RUN: opt < %s -scalarrepl -S | FileCheck %s<br>-; Radar 7441282<br>-<br>-target datalayout = "e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:64:64-v128:128:128-a0:0:32-n32"<br>-target triple = "thumbv7-apple-darwin10"<br>-<br>-%struct.__neon_int16x8x2_t = type { <8 x i16>, <8 x i16> }<br>-%struct.int16x8_t = type { <8 x i16> }<br>-%struct.int16x8x2_t = type { [2 x %struct.int16x8_t] }<br>-%union..0anon = type { %struct.int16x8x2_t }<br>-<br>-define arm_apcscc void @test(<8 x i16> %tmp.0, %struct.int16x8x2_t* %dst) nounwind {<br>-; CHECK: @test<br>-; CHECK-NOT: alloca<br>-; CHECK: "alloca point"<br>-entry:<br>-  %tmp_addr = alloca %struct.int16x8_t            ; <%struct.int16x8_t*> [#uses=3]<br>-  %dst_addr = alloca %struct.int16x8x2_t*         ; <%struct.int16x8x2_t**> [#uses=2]<br>-  %__rv = alloca %union..0anon                    ; <%union..0anon*> [#uses=2]<br>-  %__bx = alloca %struct.int16x8_t                ; <%struct.int16x8_t*> [#uses=2]<br>-  %__ax = alloca %struct.int16x8_t                ; <%struct.int16x8_t*> [#uses=2]<br>-  %tmp2 = alloca %struct.int16x8x2_t              ; <%struct.int16x8x2_t*> [#uses=2]<br>-  %0 = alloca %struct.int16x8x2_t                 ; <%struct.int16x8x2_t*> [#uses=2]<br>-  %"alloca point" = bitcast i32 0 to i32          ; <i32> [#uses=0]<br>-  %1 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  store <8 x i16> %tmp.0, <8 x i16>* %1<br>-  store %struct.int16x8x2_t* %dst, %struct.int16x8x2_t** %dst_addr<br>-  %2 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %3 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %4 = load <8 x i16>* %3, align 16               ; <<8 x i16>> [#uses=1]<br>-  store <8 x i16> %4, <8 x i16>* %2, align 16<br>-  %5 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %6 = getelementptr inbounds %struct.int16x8_t* %tmp_addr, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %7 = load <8 x i16>* %6, align 16               ; <<8 x i16>> [#uses=1]<br>-  store <8 x i16> %7, <8 x i16>* %5, align 16<br>-  %8 = getelementptr inbounds %struct.int16x8_t* %__ax, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %9 = load <8 x i16>* %8, align 16               ; <<8 x i16>> [#uses=2]<br>-  %10 = getelementptr inbounds %struct.int16x8_t* %__bx, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  %11 = load <8 x i16>* %10, align 16             ; <<8 x i16>> [#uses=2]<br>-  %12 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1]<br>-  %13 = bitcast %struct.int16x8x2_t* %12 to %struct.__neon_int16x8x2_t* ; <%struct.__neon_int16x8x2_t*> [#uses=2]<br>-  %14 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> <i32 0, i32 8, i32 2, i32 10, i32 4, i32 12, i32 6, i32 14> ; <<8 x i16>> [#uses=1]<br>-  %15 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 0 ; <<8 x i16>*> [#uses=1]<br>-  store <8 x i16> %14, <8 x i16>* %15<br>-  %16 = shufflevector <8 x i16> %9, <8 x i16> %11, <8 x i32> <i32 1, i32 9, i32 3, i32 11, i32 5, i32 13, i32 7, i32 15> ; <<8 x i16>> [#uses=1]<br>-  %17 = getelementptr inbounds %struct.__neon_int16x8x2_t* %13, i32 0, i32 1 ; <<8 x i16>*> [#uses=1]<br>-  store <8 x i16> %16, <8 x i16>* %17<br>-  %18 = getelementptr inbounds %union..0anon* %__rv, i32 0, i32 0 ; <%struct.int16x8x2_t*> [#uses=1]<br>-  %19 = bitcast %struct.int16x8x2_t* %0 to i8*    ; <i8*> [#uses=1]<br>-  %20 = bitcast %struct.int16x8x2_t* %18 to i8*   ; <i8*> [#uses=1]<br>-  call void @llvm.memcpy.i32(i8* %19, i8* %20, i32 32, i32 16)<br>-  %tmp21 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; <i8*> [#uses=1]<br>-  %21 = bitcast %struct.int16x8x2_t* %0 to i8*    ; <i8*> [#uses=1]<br>-  call void @llvm.memcpy.i32(i8* %tmp21, i8* %21, i32 32, i32 16)<br>-  %22 = load %struct.int16x8x2_t** %dst_addr, align 4 ; <%struct.int16x8x2_t*> [#uses=1]<br>-  %23 = bitcast %struct.int16x8x2_t* %22 to i8*   ; <i8*> [#uses=1]<br>-  %tmp22 = bitcast %struct.int16x8x2_t* %tmp2 to i8* ; <i8*> [#uses=1]<br>-  call void @llvm.memcpy.i32(i8* %23, i8* %tmp22, i32 32, i32 16)<br>-  br label %return<br>-<br>-; CHECK: store <8 x i16><br>-; CHECK: store <8 x i16><br>-<br>-return:                                           ; preds = %entry<br>-  ret void<br>-}<br>-<br>-declare void @llvm.memcpy.i32(i8* nocapture, i8* nocapture, i32, i32) nounwind<br><br><br>_______________________________________________<br>llvm-commits mailing list<br><a href="mailto:llvm-commits@cs.uiuc.edu">llvm-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits<br></div></blockquote></div><br></div></body></html>