[llvm-commits] [llvm] r61980 - in /llvm/trunk: lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/bitcast-gep.ll
Chris Lattner
sabre at nondot.org
Thu Jan 8 21:44:56 PST 2009
Author: lattner
Date: Thu Jan 8 23:44:56 2009
New Revision: 61980
URL: http://llvm.org/viewvc/llvm-project?rev=61980&view=rev
Log:
Fix part 3/2 of PR3290, making instcombine zap (gep(bitcast)) when possible.
Modified:
llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
llvm/trunk/test/Transforms/InstCombine/bitcast-gep.ll
Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=61980&r1=61979&r2=61980&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Thu Jan 8 23:44:56 2009
@@ -7695,6 +7695,66 @@
return 0;
}
+/// 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;
+
+ // 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
+ // is something like [0 x {int, int}]
+ const Type *IntPtrTy = TD->getIntPtrType();
+ int64_t FirstIdx = 0;
+ if (int64_t TySize = TD->getABITypeSize(Ty)) {
+ FirstIdx = Offset/TySize;
+ Offset %= TySize;
+
+ // Handle silly modulus not returning values values [0..TySize).
+ if (Offset < 0) {
+ --FirstIdx;
+ Offset += TySize;
+ assert(Offset >= 0);
+ }
+ assert((uint64_t)Offset < (uint64_t)TySize && "Out of range offset");
+ }
+
+ NewIndices.push_back(ConstantInt::get(IntPtrTy, FirstIdx));
+
+ // Index into the types. If we fail, set OrigBase to null.
+ while (Offset) {
+ if (const StructType *STy = dyn_cast<StructType>(Ty)) {
+ const StructLayout *SL = TD->getStructLayout(STy);
+ if (Offset >= (int64_t)SL->getSizeInBytes()) {
+ // We can't index into this, bail out.
+ return false;
+ }
+ unsigned Elt = SL->getElementContainingOffset(Offset);
+ NewIndices.push_back(ConstantInt::get(Type::Int32Ty, Elt));
+
+ Offset -= SL->getElementOffset(Elt);
+ Ty = STy->getElementType(Elt);
+ } else if (isa<ArrayType>(Ty) || isa<VectorType>(Ty)) {
+ const SequentialType *STy = cast<SequentialType>(Ty);
+ if (uint64_t EltSize = TD->getABITypeSize(STy->getElementType())) {
+ NewIndices.push_back(ConstantInt::get(IntPtrTy,Offset/EltSize));
+ Offset %= EltSize;
+ } else {
+ NewIndices.push_back(ConstantInt::get(IntPtrTy, 0));
+ }
+ Ty = STy->getElementType();
+ } else {
+ // Otherwise, we can't index into this, bail out.
+ return false;
+ }
+ }
+
+ return true;
+}
+
/// @brief Implement the transforms for cast of pointer (bitcast/ptrtoint)
Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) {
Value *Src = CI.getOperand(0);
@@ -7725,74 +7785,21 @@
Value *OrigBase = cast<BitCastInst>(GEP->getOperand(0))->getOperand(0);
const Type *GEPIdxTy =
cast<PointerType>(OrigBase->getType())->getElementType();
- if (GEPIdxTy->isSized()) {
- SmallVector<Value*, 8> NewIndices;
-
- // 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
- // is something like [0 x {int, int}]
- const Type *IntPtrTy = TD->getIntPtrType();
- int64_t FirstIdx = 0;
- if (int64_t TySize = TD->getABITypeSize(GEPIdxTy)) {
- FirstIdx = Offset/TySize;
- Offset %= TySize;
-
- // Handle silly modulus not returning values values [0..TySize).
- if (Offset < 0) {
- --FirstIdx;
- Offset += TySize;
- assert(Offset >= 0);
- }
- assert((uint64_t)Offset < (uint64_t)TySize &&"Out of range offset");
- }
+ SmallVector<Value*, 8> NewIndices;
+ if (FindElementAtOffset(GEPIdxTy, Offset, NewIndices, TD)) {
+ // If we were able to index down into an element, create the GEP
+ // and bitcast the result. This eliminates one bitcast, potentially
+ // two.
+ Instruction *NGEP = GetElementPtrInst::Create(OrigBase,
+ NewIndices.begin(),
+ NewIndices.end(), "");
+ InsertNewInstBefore(NGEP, CI);
+ NGEP->takeName(GEP);
- NewIndices.push_back(ConstantInt::get(IntPtrTy, FirstIdx));
-
- // Index into the types. If we fail, set OrigBase to null.
- while (Offset) {
- if (const StructType *STy = dyn_cast<StructType>(GEPIdxTy)) {
- const StructLayout *SL = TD->getStructLayout(STy);
- if (Offset < (int64_t)SL->getSizeInBytes()) {
- unsigned Elt = SL->getElementContainingOffset(Offset);
- NewIndices.push_back(ConstantInt::get(Type::Int32Ty, Elt));
-
- Offset -= SL->getElementOffset(Elt);
- GEPIdxTy = STy->getElementType(Elt);
- } else {
- // Otherwise, we can't index into this, bail out.
- Offset = 0;
- OrigBase = 0;
- }
- } else if (isa<ArrayType>(GEPIdxTy) || isa<VectorType>(GEPIdxTy)) {
- const SequentialType *STy = cast<SequentialType>(GEPIdxTy);
- if (uint64_t EltSize = TD->getABITypeSize(STy->getElementType())){
- NewIndices.push_back(ConstantInt::get(IntPtrTy,Offset/EltSize));
- Offset %= EltSize;
- } else {
- NewIndices.push_back(ConstantInt::get(IntPtrTy, 0));
- }
- GEPIdxTy = STy->getElementType();
- } else {
- // Otherwise, we can't index into this, bail out.
- Offset = 0;
- OrigBase = 0;
- }
- }
- if (OrigBase) {
- // If we were able to index down into an element, create the GEP
- // and bitcast the result. This eliminates one bitcast, potentially
- // two.
- Instruction *NGEP = GetElementPtrInst::Create(OrigBase,
- NewIndices.begin(),
- NewIndices.end(), "");
- InsertNewInstBefore(NGEP, CI);
- NGEP->takeName(GEP);
-
- if (isa<BitCastInst>(CI))
- return new BitCastInst(NGEP, CI.getType());
- assert(isa<PtrToIntInst>(CI));
- return new PtrToIntInst(NGEP, CI.getType());
- }
+ if (isa<BitCastInst>(CI))
+ return new BitCastInst(NGEP, CI.getType());
+ assert(isa<PtrToIntInst>(CI));
+ return new PtrToIntInst(NGEP, CI.getType());
}
}
}
@@ -10675,24 +10682,52 @@
}
}
+ /// See if we can simplify:
+ /// X = bitcast A to B*
+ /// Y = gep X, <...constant indices...>
+ /// into a gep of the original struct. This is important for SROA and alias
+ /// analysis of unions. If "A" is also a bitcast, wait for A/X to be merged.
if (BitCastInst *BCI = dyn_cast<BitCastInst>(PtrOp)) {
- // If this GEP instruction doesn't move the pointer, just replace the GEP
- // with a bitcast of the real input to the dest type.
- if (GEP.hasAllZeroIndices()) {
- // If the bitcast is of an allocation, and the allocation will be
- // converted to match the type of the cast, don't touch this.
- if (isa<AllocationInst>(BCI->getOperand(0))) {
- // See if the bitcast simplifies, if so, don't nuke this GEP yet.
- if (Instruction *I = visitBitCast(*BCI)) {
- if (I != BCI) {
- I->takeName(BCI);
- BCI->getParent()->getInstList().insert(BCI, I);
- ReplaceInstUsesWith(*BCI, I);
+ if (!isa<BitCastInst>(BCI->getOperand(0)) && GEP.hasAllConstantIndices()) {
+ // Determine how much the GEP moves the pointer. We are guaranteed to get
+ // a constant back from EmitGEPOffset.
+ ConstantInt *OffsetV = cast<ConstantInt>(EmitGEPOffset(&GEP, GEP, *this));
+ int64_t Offset = OffsetV->getSExtValue();
+
+ // If this GEP instruction doesn't move the pointer, just replace the GEP
+ // with a bitcast of the real input to the dest type.
+ if (Offset == 0) {
+ // If the bitcast is of an allocation, and the allocation will be
+ // converted to match the type of the cast, don't touch this.
+ if (isa<AllocationInst>(BCI->getOperand(0))) {
+ // See if the bitcast simplifies, if so, don't nuke this GEP yet.
+ if (Instruction *I = visitBitCast(*BCI)) {
+ if (I != BCI) {
+ I->takeName(BCI);
+ BCI->getParent()->getInstList().insert(BCI, I);
+ ReplaceInstUsesWith(*BCI, I);
+ }
+ return &GEP;
}
- return &GEP;
}
+ return new BitCastInst(BCI->getOperand(0), GEP.getType());
+ }
+
+ // Otherwise, if the offset is non-zero, we need to find out if there is a
+ // field at Offset in 'A's type. If so, we can pull the cast through the
+ // GEP.
+ SmallVector<Value*, 8> NewIndices;
+ const Type *InTy =
+ cast<PointerType>(BCI->getOperand(0)->getType())->getElementType();
+ if (FindElementAtOffset(InTy, Offset, NewIndices, TD)) {
+ Instruction *NGEP =
+ GetElementPtrInst::Create(BCI->getOperand(0), NewIndices.begin(),
+ NewIndices.end());
+ if (NGEP->getType() == GEP.getType()) return NGEP;
+ InsertNewInstBefore(NGEP, GEP);
+ NGEP->takeName(&GEP);
+ return new BitCastInst(NGEP, GEP.getType());
}
- return new BitCastInst(BCI->getOperand(0), GEP.getType());
}
}
Modified: llvm/trunk/test/Transforms/InstCombine/bitcast-gep.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/bitcast-gep.ll?rev=61980&r1=61979&r2=61980&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/bitcast-gep.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/bitcast-gep.ll Thu Jan 8 23:44:56 2009
@@ -17,3 +17,14 @@
%G = load i8** %F ; <i8*> [#uses=1]
ret i8* %G
}
+
+; PR3290
+%struct.Key = type { { i32, i32 } }
+%struct.anon = type <{ i8, [3 x i8], i32 }>
+
+define i32 *@test2(%struct.Key *%A) {
+ %B = bitcast %struct.Key* %A to %struct.anon*
+ %C = getelementptr %struct.anon* %B, i32 0, i32 2
+ ret i32 *%C
+}
+
More information about the llvm-commits
mailing list