diff --git a/lib/Transforms/Scalar/ScalarReplAggregates.cpp b/lib/Transforms/Scalar/ScalarReplAggregates.cpp index de5b05f4c1c..880e8df72c5 100644 --- a/lib/Transforms/Scalar/ScalarReplAggregates.cpp +++ b/lib/Transforms/Scalar/ScalarReplAggregates.cpp @@ -60,14 +60,15 @@ namespace { } private: - int isSafeElementUse(Value *Ptr); + int isSafeElementUse(Value *Ptr, bool isFirstElt, AllocationInst *AI); int isSafeUseOfAllocation(Instruction *User, AllocationInst *AI); + bool isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocationInst *AI); bool isSafeUseOfBitCastedAllocation(BitCastInst *User, AllocationInst *AI); int isSafeAllocaToScalarRepl(AllocationInst *AI); void CanonicalizeAllocaUsers(AllocationInst *AI); AllocaInst *AddNewAlloca(Function &F, const Type *Ty, AllocationInst *Base); - void RewriteBitCastUserOfAlloca(BitCastInst *BCInst, AllocationInst *AI, + void RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocationInst *AI, SmallVector &NewElts); const Type *CanConvertToScalar(Value *V, bool &IsNotTrivial); @@ -214,6 +215,7 @@ bool SROA::performScalarRepl(Function &F) { Instruction *User = cast(AI->use_back()); if (BitCastInst *BCInst = dyn_cast(User)) { RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas); + BCInst->eraseFromParent(); continue; } @@ -242,6 +244,25 @@ bool SROA::performScalarRepl(Function &F) { NewArgs.size(), "", GEPI); RepValue->takeName(GEPI); } + + // If this GEP is to the start of the aggregate, check for memcpys. + if (Idx == 0) { + bool IsStartOfAggregateGEP = true; + for (unsigned i = 3, e = GEPI->getNumOperands(); i != e; ++i) { + if (!isa(GEPI->getOperand(i))) { + IsStartOfAggregateGEP = false; + break; + } + if (!cast(GEPI->getOperand(i))->isZero()) { + IsStartOfAggregateGEP = false; + break; + } + } + + if (IsStartOfAggregateGEP) + RewriteBitCastUserOfAlloca(GEPI, AI, ElementAllocas); + } + // Move all of the users over to the new GEP. GEPI->replaceAllUsesWith(RepValue); @@ -259,9 +280,10 @@ bool SROA::performScalarRepl(Function &F) { /// isSafeElementUse - Check to see if this use is an allowed use for a -/// getelementptr instruction of an array aggregate allocation. +/// getelementptr instruction of an array aggregate allocation. isFirstElt +/// indicates whether Ptr is known to the start of the aggregate. /// -int SROA::isSafeElementUse(Value *Ptr) { +int SROA::isSafeElementUse(Value *Ptr, bool isFirstElt, AllocationInst *AI) { for (Value::use_iterator I = Ptr->use_begin(), E = Ptr->use_end(); I != E; ++I) { Instruction *User = cast(*I); @@ -273,14 +295,38 @@ int SROA::isSafeElementUse(Value *Ptr) { break; case Instruction::GetElementPtr: { GetElementPtrInst *GEP = cast(User); + bool AreAllZeroIndices = isFirstElt; if (GEP->getNumOperands() > 1) { - if (!isa(GEP->getOperand(1)) || - !cast(GEP->getOperand(1))->isNullValue()) - return 0; // Using pointer arithmetic to navigate the array... + if (!isa(GEP->getOperand(1)) || + !cast(GEP->getOperand(1))->isZero()) + return 0; // Using pointer arithmetic to navigate the array. + + if (AreAllZeroIndices) { + for (unsigned i = 2, e = GEP->getNumOperands(); i != e; ++i) { + if (!isa(GEP->getOperand(i)) || + !cast(GEP->getOperand(i))->isZero()) { + AreAllZeroIndices = false; + break; + } + } + } } - if (!isSafeElementUse(GEP)) return 0; + if (!isSafeElementUse(GEP, AreAllZeroIndices, AI)) return 0; break; } + case Instruction::BitCast: + if (isFirstElt && + isSafeUseOfBitCastedAllocation(cast(User), AI)) + break; + DOUT << " Transformation preventing inst: " << *User; + return 0; + case Instruction::Call: + if (MemIntrinsic *MI = dyn_cast(User)) { + if (isFirstElt && isSafeMemIntrinsicOnAllocation(MI, AI)) + break; + } + DOUT << " Transformation preventing inst: " << *User; + return 0; default: DOUT << " Transformation preventing inst: " << *User; return 0; @@ -317,15 +363,19 @@ int SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI) { ++I; if (I == E) return 0; // ran out of GEP indices?? + bool IsAllZeroIndices = true; + // If this is a use of an array allocation, do a bit more checking for sanity. if (const ArrayType *AT = dyn_cast(*I)) { uint64_t NumElements = AT->getNumElements(); - if (isa(I.getOperand())) { + if (ConstantInt *Idx = dyn_cast(I.getOperand())) { + IsAllZeroIndices &= Idx->isZero(); + // Check to make sure that index falls within the array. If not, // something funny is going on, so we won't do the optimization. // - if (cast(GEPI->getOperand(2))->getZExtValue() >= NumElements) + if (Idx->getZExtValue() >= NumElements) return 0; // We cannot scalar repl this level of the array unless any array @@ -342,12 +392,16 @@ int SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI) { else NumElements = cast(*I)->getNumElements(); - if (!isa(I.getOperand())) return 0; - if (cast(I.getOperand())->getZExtValue() >= NumElements) + ConstantInt *IdxVal = dyn_cast(I.getOperand()); + if (!IdxVal) return 0; + if (IdxVal->getZExtValue() >= NumElements) return 0; + IsAllZeroIndices &= IdxVal->isZero(); } } else { + IsAllZeroIndices = 0; + // If this is an array index and the index is not constant, we cannot // promote... that is unless the array has exactly one or two elements in // it, in which case we CAN promote it, but we have to canonicalize this @@ -361,7 +415,27 @@ int SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI) { // If there are any non-simple uses of this getelementptr, make sure to reject // them. - return isSafeElementUse(GEPI); + return isSafeElementUse(GEPI, IsAllZeroIndices, AI); +} + +/// isSafeMemIntrinsicOnAllocation - Return true if the specified memory +/// intrinsic can be promoted by SROA. At this point, we know that the operand +/// of the memintrinsic is a pointer to the beginning of the allocation. +bool SROA::isSafeMemIntrinsicOnAllocation(MemIntrinsic *MI, AllocationInst *AI){ + // If not constant length, give up. + ConstantInt *Length = dyn_cast(MI->getLength()); + if (!Length) return false; + + // If not the whole aggregate, give up. + const TargetData &TD = getAnalysis(); + if (Length->getZExtValue() != TD.getTypeSize(AI->getType()->getElementType())) + return false; + + // We only know about memcpy/memset/memmove. + if (!isa(MI) && !isa(MI) && !isa(MI)) + return false; + // Otherwise, we can transform it. + return true; } /// isSafeUseOfBitCastedAllocation - Return true if all users of this bitcast @@ -373,21 +447,8 @@ bool SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocationInst *AI) { if (!isSafeUseOfBitCastedAllocation(BCU, AI)) return false; } else if (MemIntrinsic *MI = dyn_cast(UI)) { - // If not constant length, give up. - ConstantInt *Length = dyn_cast(MI->getLength()); - if (!Length) return false; - - // If not the whole aggregate, give up. - const TargetData &TD = getAnalysis(); - if (Length->getZExtValue() != - TD.getTypeSize(AI->getType()->getElementType())) + if (!isSafeMemIntrinsicOnAllocation(MI, AI)) return false; - - // We only know about memcpy/memset/memmove. - if (!isa(MI) && !isa(MI) && - !isa(MI)) - return false; - // Otherwise, we can transform it. } else { return false; } @@ -395,21 +456,33 @@ bool SROA::isSafeUseOfBitCastedAllocation(BitCastInst *BC, AllocationInst *AI) { return true; } -/// RewriteBitCastUserOfAlloca - BCInst (transitively) casts AI. Transform -/// users of the cast to use the new values instead. -void SROA::RewriteBitCastUserOfAlloca(BitCastInst *BCInst, AllocationInst *AI, +/// RewriteBitCastUserOfAlloca - BCInst (transitively) bitcasts AI, or indexes +/// to its first element. Transform users of the cast to use the new values +/// instead. +void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocationInst *AI, SmallVector &NewElts) { Constant *Zero = Constant::getNullValue(Type::Int32Ty); const TargetData &TD = getAnalysis(); - while (!BCInst->use_empty()) { - if (BitCastInst *BCU = dyn_cast(BCInst->use_back())) { + + Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end(); + while (UI != UE) { + if (BitCastInst *BCU = dyn_cast(*UI)) { RewriteBitCastUserOfAlloca(BCU, AI, NewElts); + ++UI; + BCU->eraseFromParent(); continue; } // Otherwise, must be memcpy/memmove/memset of the entire aggregate. Split // into one per element. - MemIntrinsic *MI = cast(BCInst->use_back()); + MemIntrinsic *MI = dyn_cast(*UI); + + // If it's not a mem intrinsic, it must be some other user of a gep of the + // first pointer. Just leave these alone. + if (!MI) { + ++UI; + continue; + } // If this is a memcpy/memmove, construct the other pointer as the // appropriate type. @@ -553,11 +626,9 @@ void SROA::RewriteBitCastUserOfAlloca(BitCastInst *BCInst, AllocationInst *AI, // Finally, MI is now dead, as we've modified its actions to occur on all of // the elements of the aggregate. + ++UI; MI->eraseFromParent(); } - - // The cast is dead, remove it. - BCInst->eraseFromParent(); }