<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>