mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 05:29:24 +00:00
Allow scalarrepl to treat an all-zero GEP just as bitcast.
This includes not marking a GEP involving a vector as unsafe, but only when it has all zero indices. This allows scalarrepl to work in a few more cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@57177 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
96f945267c
commit
5fac55fafb
@ -531,6 +531,7 @@ void SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI,
|
||||
}
|
||||
}
|
||||
|
||||
bool hasVector = false;
|
||||
|
||||
// Walk through the GEP type indices, checking the types that this indexes
|
||||
// into.
|
||||
@ -539,22 +540,30 @@ void SROA::isSafeUseOfAllocation(Instruction *User, AllocationInst *AI,
|
||||
if (isa<StructType>(*I))
|
||||
continue;
|
||||
|
||||
// Don't SROA pointers into vectors.
|
||||
if (isa<VectorType>(*I))
|
||||
return MarkUnsafe(Info);
|
||||
|
||||
// Otherwise, we must have an index into an array type. Verify that this is
|
||||
// an in-range constant integer. Specifically, consider A[0][i]. We
|
||||
// cannot know that the user isn't doing invalid things like allowing i to
|
||||
// index an out-of-range subscript that accesses A[1]. Because of this, we
|
||||
// have to reject SROA of any accesses into structs where any of the
|
||||
// components are variables.
|
||||
ConstantInt *IdxVal = dyn_cast<ConstantInt>(I.getOperand());
|
||||
if (!IdxVal) return MarkUnsafe(Info);
|
||||
if (IdxVal->getZExtValue() >= cast<ArrayType>(*I)->getNumElements())
|
||||
return MarkUnsafe(Info);
|
||||
|
||||
// Are all indices still zero?
|
||||
IsAllZeroIndices &= IdxVal->isZero();
|
||||
|
||||
if (const ArrayType *AT = dyn_cast<ArrayType>(*I)) {
|
||||
// This GEP indexes an array. Verify that this is an in-range constant
|
||||
// integer. Specifically, consider A[0][i]. We cannot know that the user
|
||||
// isn't doing invalid things like allowing i to index an out-of-range
|
||||
// subscript that accesses A[1]. Because of this, we have to reject SROA
|
||||
// of any accesses into structs where any of the components are variables.
|
||||
if (IdxVal->getZExtValue() >= AT->getNumElements())
|
||||
return MarkUnsafe(Info);
|
||||
}
|
||||
|
||||
// Note if we've seen a vector type yet
|
||||
hasVector |= isa<VectorType>(*I);
|
||||
|
||||
// Don't SROA pointers into vectors, unless all indices are zero. When all
|
||||
// indices are zero, we only consider this GEP as a bitcast, but will still
|
||||
// not consider breaking up the vector.
|
||||
if (hasVector && !IsAllZeroIndices)
|
||||
return MarkUnsafe(Info);
|
||||
}
|
||||
|
||||
// If there are any non-simple uses of this getelementptr, make sure to reject
|
||||
@ -661,6 +670,11 @@ void SROA::RewriteBitCastUserOfAlloca(Instruction *BCInst, AllocationInst *AI,
|
||||
// It is likely that OtherPtr is a bitcast, if so, remove it.
|
||||
if (BitCastInst *BC = dyn_cast<BitCastInst>(OtherPtr))
|
||||
OtherPtr = BC->getOperand(0);
|
||||
// All zero GEPs are effectively casts
|
||||
if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(OtherPtr))
|
||||
if (GEP->hasAllZeroIndices())
|
||||
OtherPtr = GEP->getOperand(0);
|
||||
|
||||
if (ConstantExpr *BCE = dyn_cast<ConstantExpr>(OtherPtr))
|
||||
if (BCE->getOpcode() == Instruction::BitCast)
|
||||
OtherPtr = BCE->getOperand(0);
|
||||
|
24
test/Transforms/ScalarRepl/2008-09-22-vector-gep.ll
Normal file
24
test/Transforms/ScalarRepl/2008-09-22-vector-gep.ll
Normal file
@ -0,0 +1,24 @@
|
||||
; This test checks to see if scalarrepl also works when a gep with all zeroes is
|
||||
; used instead of a bitcast to prepare a memmove pointer argument. Previously,
|
||||
; this would not work when there was a vector involved in the struct, preventing
|
||||
; scalarrepl from removing the alloca below.
|
||||
|
||||
; RUN: llvm-as < %s | opt -scalarrepl | llvm-dis > %t
|
||||
; RUN: cat %t | not grep alloca
|
||||
|
||||
%struct.two = type <{ < 2 x i8 >, i16 }>
|
||||
|
||||
define void @main(%struct.two* %D, i16 %V) {
|
||||
entry:
|
||||
%S = alloca %struct.two
|
||||
%S.2 = getelementptr %struct.two* %S, i32 0, i32 1
|
||||
store i16 %V, i16* %S.2
|
||||
; This gep is effectively a bitcast to i8*, but is sometimes generated
|
||||
; because the type of the first element in %struct.two is i8.
|
||||
%tmpS = getelementptr %struct.two* %S, i32 0, i32 0, i32 0
|
||||
%tmpD = bitcast %struct.two* %D to i8*
|
||||
call void @llvm.memmove.i32(i8* %tmpD, i8* %tmpS, i32 4, i32 1)
|
||||
ret void
|
||||
}
|
||||
|
||||
declare void @llvm.memmove.i32(i8*, i8*, i32, i32) nounwind
|
Loading…
Reference in New Issue
Block a user