From 1c2b03aae9e56e69d215e9b39928a1340e3ca0c3 Mon Sep 17 00:00:00 2001 From: Shuxin Yang Date: Fri, 7 Jun 2013 22:45:21 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@183584 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/MemCpyOptimizer.cpp | 6 ++-- test/Transforms/MemCpyOpt/memcpy.ll | 39 +++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/lib/Transforms/Scalar/MemCpyOptimizer.cpp index be0f0e8a25f..8600c9ebf79 100644 --- a/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -626,8 +626,10 @@ bool MemCpyOpt::performCallSlotOptzn(Instruction *cpy, return false; Type *StructTy = cast(A->getType())->getElementType(); - uint64_t destSize = TD->getTypeAllocSize(StructTy); - + // If StructTy is an opaque type, it should have at least bytes, + // as implified by the copy-instruction. + uint64_t destSize = StructTy->isSized() ? + TD->getTypeAllocSize(StructTy) : cpyLen; if (destSize < srcSize) return false; } else { diff --git a/test/Transforms/MemCpyOpt/memcpy.ll b/test/Transforms/MemCpyOpt/memcpy.ll index 582a57b5d39..fa768712ec9 100644 --- a/test/Transforms/MemCpyOpt/memcpy.ll +++ b/test/Transforms/MemCpyOpt/memcpy.ll @@ -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*) -- 2.34.1