[llvm-commits] [llvm] r62905 - /llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp
Bill Wendling
isanbard at gmail.com
Fri Jan 23 17:16:14 PST 2009
Author: void
Date: Fri Jan 23 19:16:14 2009
New Revision: 62905
URL: http://llvm.org/viewvc/llvm-project?rev=62905&view=rev
Log:
Pull r62904 into Dib:
Make InstCombineStoreToCast handle aggregates more aggressively,
handling the case in Transforms/InstCombine/cast-store-gep.ll, which
is a heavily reduced testcase from Clang on x86-64.
Modified:
llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp
Modified: llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp?rev=62905&r1=62904&r2=62905&view=diff
==============================================================================
--- llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/branches/Apple/Dib/lib/Transforms/Scalar/InstructionCombining.cpp Fri Jan 23 19:16:14 2009
@@ -7700,12 +7700,12 @@
/// FindElementAtOffset - Given a type and a constant offset, determine whether
/// or not there is a sequence of GEP indices into the type that will land us at
-/// the specified offset. If so, fill them into NewIndices and return true,
-/// otherwise return false.
-static bool FindElementAtOffset(const Type *Ty, int64_t Offset,
- SmallVectorImpl<Value*> &NewIndices,
- const TargetData *TD) {
- if (!Ty->isSized()) return false;
+/// the specified offset. If so, fill them into NewIndices and return the
+/// resultant element type, otherwise return null.
+static const Type *FindElementAtOffset(const Type *Ty, int64_t Offset,
+ SmallVectorImpl<Value*> &NewIndices,
+ const TargetData *TD) {
+ if (!Ty->isSized()) return 0;
// Start with the index over the outer type. Note that the type size
// might be zero (even if the offset isn't zero) if the indexed type
@@ -7731,7 +7731,7 @@
while (Offset) {
// Indexing into tail padding between struct/array elements.
if (uint64_t(Offset*8) >= TD->getTypeSizeInBits(Ty))
- return false;
+ return 0;
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
const StructLayout *SL = TD->getStructLayout(STy);
@@ -7751,11 +7751,11 @@
Ty = AT->getElementType();
} else {
// Otherwise, we can't index into the middle of this atomic type, bail.
- return false;
+ return 0;
}
}
- return true;
+ return Ty;
}
/// @brief Implement the transforms for cast of pointer (bitcast/ptrtoint)
@@ -11139,7 +11139,8 @@
}
/// InstCombineStoreToCast - Fold store V, (cast P) -> store (cast V), P
-/// when possible.
+/// when possible. This makes it generally easy to do alias analysis and/or
+/// SROA/mem2reg of the memory object.
static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) {
User *CI = cast<User>(SI.getOperand(1));
Value *CastOp = CI->getOperand(0);
@@ -11153,18 +11154,34 @@
if (!DestPTy->isInteger() && !isa<PointerType>(DestPTy))
return 0;
+ /// NewGEPIndices - If SrcPTy is an aggregate type, we can emit a "noop gep"
+ /// to its first element. This allows us to handle things like:
+ /// store i32 xxx, (bitcast {foo*, float}* %P to i32*)
+ /// on 32-bit hosts.
+ SmallVector<Value*, 4> NewGEPIndices;
+
// If the source is an array, the code below will not succeed. Check to
// see if a trivial 'gep P, 0, 0' will help matters. Only do this for
// constants.
- if (const ArrayType *ASrcTy = dyn_cast<ArrayType>(SrcPTy))
- if (Constant *CSrc = dyn_cast<Constant>(CastOp))
- if (ASrcTy->getNumElements() != 0) {
- Value* Idxs[2];
- Idxs[0] = Idxs[1] = Constant::getNullValue(Type::Int32Ty);
- CastOp = ConstantExpr::getGetElementPtr(CSrc, Idxs, 2);
- SrcTy = cast<PointerType>(CastOp->getType());
- SrcPTy = SrcTy->getElementType();
+ if (isa<ArrayType>(SrcPTy) || isa<StructType>(SrcPTy)) {
+ // Index through pointer.
+ Constant *Zero = Constant::getNullValue(Type::Int32Ty);
+ NewGEPIndices.push_back(Zero);
+
+ while (1) {
+ if (const StructType *STy = dyn_cast<StructType>(SrcPTy)) {
+ NewGEPIndices.push_back(Zero);
+ SrcPTy = STy->getElementType(0);
+ } else if (const ArrayType *ATy = dyn_cast<ArrayType>(SrcPTy)) {
+ NewGEPIndices.push_back(Zero);
+ SrcPTy = ATy->getElementType();
+ } else {
+ break;
}
+ }
+
+ SrcTy = PointerType::get(SrcPTy, SrcTy->getAddressSpace());
+ }
if (!SrcPTy->isInteger() && !isa<PointerType>(SrcPTy))
return 0;
@@ -11192,6 +11209,19 @@
if (isa<PointerType>(SIOp0->getType()))
opcode = Instruction::PtrToInt;
}
+
+ // SIOp0 is a pointer to aggregate and this is a store to the first field,
+ // emit a GEP to index into its first field.
+ if (!NewGEPIndices.empty()) {
+ if (Constant *C = dyn_cast<Constant>(CastOp))
+ CastOp = ConstantExpr::getGetElementPtr(C, &NewGEPIndices[0],
+ NewGEPIndices.size());
+ else
+ CastOp = IC.InsertNewInstBefore(
+ GetElementPtrInst::Create(CastOp, NewGEPIndices.begin(),
+ NewGEPIndices.end()), SI);
+ }
+
if (Constant *C = dyn_cast<Constant>(SIOp0))
NewCast = ConstantExpr::getCast(opcode, C, CastDstTy);
else
More information about the llvm-commits
mailing list