Fix an assertion in MemCpyOpt pass.

The MemCpyOpt pass is capable of optimizing:
      callee(&S); copy N bytes from S to D.
    into:
      callee(&D);
subject to some legality constraints. 

  Assertion is triggered when the compiler tries to evalute "sizeof(typeof(D))",
while D is an opaque-typed, 'sret' formal argument of function being compiled.
i.e. the signature of the func being compiled is something like this:
  T caller(...,%opaque* noalias nocapture sret %D, ...)

  The fix is that when come across such situation, instead of calling some
utility functions to get the size of D's type (which will crash), we simply
assume D has at least N bytes as implified by the copy-instruction.

rdar://14073661 

llvm-svn: 183584
This commit is contained in:
Shuxin Yang 2013-06-07 22:45:21 +00:00
parent f60b8ceb7e
commit bd254f2601
2 changed files with 43 additions and 2 deletions

View File

@ -626,8 +626,10 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy,
return false;
Type *StructTy = cast<PointerType>(A->getType())->getElementType();
uint64_t destSize = TD->getTypeAllocSize(StructTy);
// If StructTy is an opaque type, it should have at least <cpyLen> bytes,
// as implified by the copy-instruction.
uint64_t destSize = StructTy->isSized() ?
TD->getTypeAllocSize(StructTy) : cpyLen;
if (destSize < srcSize)
return false;
} else {

View File

@ -168,6 +168,45 @@ entry:
ret void
}
; rdar://14073661.
; Test10 triggered assertion when the compiler try to get the size of the
; opaque type of *x, where the x is the formal argument with attribute 'sret'.
%opaque = type opaque
declare void @foo(i32* noalias nocapture)
define void @test10(%opaque* noalias nocapture sret %x, i32 %y) {
%a = alloca i32, align 4
store i32 %y, i32* %a
call void @foo(i32* noalias nocapture %a)
%c = load i32* %a
%d = bitcast %opaque* %x to i32*
store i32 %c, i32* %d
ret void
}
; Test11 is similar to test10 except that the instruction "store i32 %y, i32* %a"
; before the call-site is deleted. MemCopyOpt is able to optimize this snippet into
;
; %x1 = bitcast %opaque* %x to i32*
; call void @foo(i32* noalias nocapture %x1)
; ret void
;
define void @test11(%opaque* noalias nocapture sret %x, i32 %y) {
; CHECK: test11
; CHECK: %x1 = bitcast %opaque* %x to i32*
; CHECK: call void @foo(i32* noalias nocapture %x1)
; CHECK: ret void
%a = alloca i32, align 4
call void @foo(i32* noalias nocapture %a)
%c = load i32* %a
%d = bitcast %opaque* %x to i32*
store i32 %c, i32* %d
ret void
}
declare void @f1(%struct.big* sret)
declare void @f2(%struct.big*)