Index: llvm/lib/Analysis/MemoryBuiltins.cpp =================================================================== --- llvm/lib/Analysis/MemoryBuiltins.cpp +++ llvm/lib/Analysis/MemoryBuiltins.cpp @@ -807,7 +807,7 @@ SizeOffsetType ObjectSizeOffsetVisitor::visitArgument(Argument &A) { Type *MemoryTy = A.getPointeeInMemoryValueType(); // No interprocedural analysis is done at the moment. - if (!MemoryTy|| !MemoryTy->isSized()) { + if (!MemoryTy) { ++ObjectVisitorArgument; return unknown(); } Index: llvm/lib/IR/Value.cpp =================================================================== --- llvm/lib/IR/Value.cpp +++ llvm/lib/IR/Value.cpp @@ -853,10 +853,8 @@ if (DerefBytes == 0) { // Handle byval/byref/inalloca/preallocated arguments if (Type *ArgMemTy = A->getPointeeInMemoryValueType()) { - if (ArgMemTy->isSized()) { - // FIXME: Why isn't this the type alloc size? - DerefBytes = DL.getTypeStoreSize(ArgMemTy).getKnownMinSize(); - } + // FIXME: Why isn't this the type alloc size? + DerefBytes = DL.getTypeStoreSize(ArgMemTy).getKnownMinSize(); } } @@ -949,8 +947,7 @@ if (!Alignment && A->hasStructRetAttr()) { // An sret parameter has at least the ABI alignment of the return type. Type *EltTy = A->getParamStructRetType(); - if (EltTy->isSized()) - return DL.getABITypeAlign(EltTy); + return DL.getABITypeAlign(EltTy); } return Alignment.valueOrOne(); } else if (const AllocaInst *AI = dyn_cast(this)) { Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -1869,6 +1869,13 @@ Check(Attrs.getByValType()->isSized(&Visited), "Attribute 'byval' does not support unsized types!", V); } + + if (Attrs.hasAttribute(Attribute::StructRet)) { + SmallPtrSet Visited; + Check(Attrs.getStructRetType()->isSized(&Visited), + "Attribute 'sret' does not support unsized types!", V); + } + if (Attrs.hasAttribute(Attribute::ByRef)) { SmallPtrSet Visited; Check(Attrs.getByRefType()->isSized(&Visited), Index: llvm/test/Transforms/InstCombine/object-size-opaque.ll =================================================================== --- llvm/test/Transforms/InstCombine/object-size-opaque.ll +++ /dev/null @@ -1,11 +0,0 @@ -; RUN: opt -passes=instcombine -S %s | FileCheck %s -%opaque = type opaque - -; CHECK: call i64 @llvm.objectsize.i64 -define void @foo(ptr sret(%opaque) %in, ptr %sizeptr) { - %size = call i64 @llvm.objectsize.i64(ptr %in, i1 0, i1 0, i1 0) - store i64 %size, ptr %sizeptr - ret void -} - -declare i64 @llvm.objectsize.i64(ptr, i1, i1, i1) Index: llvm/test/Transforms/MemCpyOpt/memcpy.ll =================================================================== --- llvm/test/Transforms/MemCpyOpt/memcpy.ll +++ llvm/test/Transforms/MemCpyOpt/memcpy.ll @@ -343,10 +343,10 @@ ; 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 +%empty = type {} declare void @foo(ptr noalias nocapture) -define void @test10(ptr noalias nocapture sret(%opaque) %x, i32 %y) { +define void @test10(ptr noalias nocapture sret(%empty) %x, i32 %y) { ; CHECK-LABEL: @test10( ; CHECK-NEXT: [[A:%.*]] = alloca i32, align 4 ; CHECK-NEXT: store i32 [[Y:%.*]], ptr [[A]], align 4 Index: llvm/test/Transforms/MergeFunc/apply_function_attributes.ll =================================================================== --- llvm/test/Transforms/MergeFunc/apply_function_attributes.ll +++ llvm/test/Transforms/MergeFunc/apply_function_attributes.ll @@ -1,12 +1,12 @@ ; RUN: opt -S -mergefunc < %s | FileCheck %s -%Opaque_type = type opaque +%Empty_type = type {} %S2i = type <{ i64, i64 }> %D2i = type <{ i64, i64 }> %Di = type <{ i32 }> %Si = type <{ i32 }> -define void @B(%Opaque_type* sret(%Opaque_type) %a, %S2i* %b, i32* %xp, i32* %yp) { +define void @B(%Empty_type* sret(%Empty_type) %a, %S2i* %b, i32* %xp, i32* %yp) { %x = load i32, i32* %xp %y = load i32, i32* %yp %sum = add i32 %x, %y @@ -15,7 +15,7 @@ ret void } -define void @C(%Opaque_type* sret(%Opaque_type) %a, %S2i* %b, i32* %xp, i32* %yp) { +define void @C(%Empty_type* sret(%Empty_type) %a, %S2i* %b, i32* %xp, i32* %yp) { %x = load i32, i32* %xp %y = load i32, i32* %yp %sum = add i32 %x, %y @@ -24,7 +24,7 @@ ret void } -define void @A(%Opaque_type* sret(%Opaque_type) %a, %D2i* %b, i32* %xp, i32* %yp) { +define void @A(%Empty_type* sret(%Empty_type) %a, %D2i* %b, i32* %xp, i32* %yp) { %x = load i32, i32* %xp %y = load i32, i32* %yp %sum = add i32 %x, %y @@ -34,14 +34,14 @@ } ; Make sure we transfer the parameter attributes to the call site. -; CHECK-LABEL: define void @C(%Opaque_type* sret -; CHECK: tail call void bitcast (void (%Opaque_type*, %D2i*, i32*, i32*)* @A to void (%Opaque_type*, %S2i*, i32*, i32*)*)(%Opaque_type* sret(%Opaque_type) %0, %S2i* %1, i32* %2, i32* %3) +; CHECK-LABEL: define void @C(%Empty_type* sret +; CHECK: tail call void bitcast (void (%Empty_type*, %D2i*, i32*, i32*)* @A to void (%Empty_type*, %S2i*, i32*, i32*)*)(%Empty_type* sret(%Empty_type) %0, %S2i* %1, i32* %2, i32* %3) ; CHECK: ret void ; Make sure we transfer the parameter attributes to the call site. -; CHECK-LABEL: define void @B(%Opaque_type* sret +; CHECK-LABEL: define void @B(%Empty_type* sret ; CHECK: %5 = bitcast -; CHECK: tail call void @A(%Opaque_type* sret(%Opaque_type) %0, %D2i* %5, i32* %2, i32* %3) +; CHECK: tail call void @A(%Empty_type* sret(%Empty_type) %0, %D2i* %5, i32* %2, i32* %3) ; CHECK: ret void Index: llvm/test/Verifier/sret.ll =================================================================== --- llvm/test/Verifier/sret.ll +++ llvm/test/Verifier/sret.ll @@ -9,3 +9,8 @@ ; CHECK: Attribute 'sret(i32)' applied to incompatible type! ; CHECK-NEXT: void (i32)* @not_ptr declare void @not_ptr(i32 sret(i32) %x) + +%opaque.ty = type opaque + +declare void @c(%opaque.ty* sret(%opaque.ty) %a) +; CHECK: Attribute 'sret' does not support unsized types!