[llvm-commits] CVS: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
Chris Lattner
sabre at nondot.org
Sun Mar 18 17:17:00 PDT 2007
Changes in directory llvm/lib/Transforms/Scalar:
ScalarReplAggregates.cpp updated: 1.78 -> 1.79
---
Log message:
implement the next chunk of SROA with memset/memcpy's of aggregates. This
implements Transforms/ScalarRepl/memset-aggregate-byte-leader.ll
---
Diffs of the changes: (+107 -36)
ScalarReplAggregates.cpp | 143 +++++++++++++++++++++++++++++++++++------------
1 files changed, 107 insertions(+), 36 deletions(-)
Index: llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp
diff -u llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.78 llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.79
--- llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp:1.78 Thu Mar 8 01:03:55 2007
+++ llvm/lib/Transforms/Scalar/ScalarReplAggregates.cpp Sun Mar 18 19:16:43 2007
@@ -60,14 +60,15 @@
}
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<AllocaInst*, 32> &NewElts);
const Type *CanConvertToScalar(Value *V, bool &IsNotTrivial);
@@ -214,6 +215,7 @@
Instruction *User = cast<Instruction>(AI->use_back());
if (BitCastInst *BCInst = dyn_cast<BitCastInst>(User)) {
RewriteBitCastUserOfAlloca(BCInst, AI, ElementAllocas);
+ BCInst->eraseFromParent();
continue;
}
@@ -242,6 +244,25 @@
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<ConstantInt>(GEPI->getOperand(i))) {
+ IsStartOfAggregateGEP = false;
+ break;
+ }
+ if (!cast<ConstantInt>(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 @@
/// 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<Instruction>(*I);
@@ -273,14 +295,38 @@
break;
case Instruction::GetElementPtr: {
GetElementPtrInst *GEP = cast<GetElementPtrInst>(User);
+ bool AreAllZeroIndices = isFirstElt;
if (GEP->getNumOperands() > 1) {
- if (!isa<Constant>(GEP->getOperand(1)) ||
- !cast<Constant>(GEP->getOperand(1))->isNullValue())
- return 0; // Using pointer arithmetic to navigate the array...
+ if (!isa<ConstantInt>(GEP->getOperand(1)) ||
+ !cast<ConstantInt>(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<ConstantInt>(GEP->getOperand(i)) ||
+ !cast<ConstantInt>(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<BitCastInst>(User), AI))
+ break;
+ DOUT << " Transformation preventing inst: " << *User;
+ return 0;
+ case Instruction::Call:
+ if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(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 @@
++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<ArrayType>(*I)) {
uint64_t NumElements = AT->getNumElements();
- if (isa<ConstantInt>(I.getOperand())) {
+ if (ConstantInt *Idx = dyn_cast<ConstantInt>(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<ConstantInt>(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 @@
else
NumElements = cast<VectorType>(*I)->getNumElements();
- if (!isa<ConstantInt>(I.getOperand())) return 0;
- if (cast<ConstantInt>(I.getOperand())->getZExtValue() >= NumElements)
+ ConstantInt *IdxVal = dyn_cast<ConstantInt>(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 @@
// 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<ConstantInt>(MI->getLength());
+ if (!Length) return false;
+
+ // If not the whole aggregate, give up.
+ const TargetData &TD = getAnalysis<TargetData>();
+ if (Length->getZExtValue() != TD.getTypeSize(AI->getType()->getElementType()))
+ return false;
+
+ // We only know about memcpy/memset/memmove.
+ if (!isa<MemCpyInst>(MI) && !isa<MemSetInst>(MI) && !isa<MemMoveInst>(MI))
+ return false;
+ // Otherwise, we can transform it.
+ return true;
}
/// isSafeUseOfBitCastedAllocation - Return true if all users of this bitcast
@@ -373,21 +447,8 @@
if (!isSafeUseOfBitCastedAllocation(BCU, AI))
return false;
} else if (MemIntrinsic *MI = dyn_cast<MemIntrinsic>(UI)) {
- // If not constant length, give up.
- ConstantInt *Length = dyn_cast<ConstantInt>(MI->getLength());
- if (!Length) return false;
-
- // If not the whole aggregate, give up.
- const TargetData &TD = getAnalysis<TargetData>();
- if (Length->getZExtValue() !=
- TD.getTypeSize(AI->getType()->getElementType()))
- return false;
-
- // We only know about memcpy/memset/memmove.
- if (!isa<MemCpyInst>(MI) && !isa<MemSetInst>(MI) &&
- !isa<MemMoveInst>(MI))
+ if (!isSafeMemIntrinsicOnAllocation(MI, AI))
return false;
- // Otherwise, we can transform it.
} else {
return false;
}
@@ -395,21 +456,33 @@
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<AllocaInst*, 32> &NewElts) {
Constant *Zero = Constant::getNullValue(Type::Int32Ty);
const TargetData &TD = getAnalysis<TargetData>();
- while (!BCInst->use_empty()) {
- if (BitCastInst *BCU = dyn_cast<BitCastInst>(BCInst->use_back())) {
+
+ Value::use_iterator UI = BCInst->use_begin(), UE = BCInst->use_end();
+ while (UI != UE) {
+ if (BitCastInst *BCU = dyn_cast<BitCastInst>(*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<MemIntrinsic>(BCInst->use_back());
+ MemIntrinsic *MI = dyn_cast<MemIntrinsic>(*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 @@
// 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();
}
More information about the llvm-commits
mailing list