diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -1065,17 +1065,22 @@ form and the known alignment of the pointer specified to the call site. If the alignment is not specified, then the code generator makes a target-specific assumption. + +.. _attr_preallocated: + ``preallocated()`` This indicates that the pointer parameter should really be passed by value to the function, and that the pointer parameter's pointee has already been initialized before the call instruction. This attribute is only valid on LLVM pointer arguments. The argument must be the value returned by the appropriate - :ref:`llvm.call.preallocated.arg`, although is - ignored during codegen. + :ref:`llvm.call.preallocated.arg` on non + ``musttail`` calls, or the corresponding caller parameter in ``musttail`` + calls, although it is ignored during codegen. - Any function call with a ``preallocated`` attribute in any parameter - must have a ``"preallocated"`` operand bundle. + A non ``musttail`` function call with a ``preallocated`` attribute in + any parameter must have a ``"preallocated"`` operand bundle. A ``musttail`` + function call cannot have a ``"preallocated"`` operand bundle. The preallocated attribute requires a type argument, which must be the same as the pointee type of the argument. @@ -10634,8 +10639,8 @@ #. The call will not cause unbounded stack growth if it is part of a recursive cycle in the call graph. - #. Arguments with the :ref:`inalloca ` attribute are - forwarded in place. + #. Arguments with the :ref:`inalloca ` or + :ref:`preallocated ` attribute are forwarded in place. #. If the musttail call appears in a function with the ``"thunk"`` attribute and the caller and callee both have varargs, than any unprototyped arguments in register or memory are forwarded to the callee. Similarly, diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2988,9 +2988,13 @@ if (Call.paramHasAttr(i, Attribute::Preallocated)) { Value *ArgVal = Call.getArgOperand(i); - Assert(Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0, - "preallocated operand requires a preallocated bundle", ArgVal, - Call); + bool hasOB = + Call.countOperandBundlesOfType(LLVMContext::OB_preallocated) != 0; + bool isMustTail = Call.isMustTailCall(); + Assert(hasOB != isMustTail, + "preallocated operand either requires a preallocated bundle or " + "the call to be musttail (but not both)", + ArgVal, Call); } } @@ -3150,9 +3154,6 @@ void Verifier::verifyMustTailCall(CallInst &CI) { Assert(!CI.isInlineAsm(), "cannot use musttail call with inline asm", &CI); - // FIXME: support musttail + preallocated - Assert(!CI.countOperandBundlesOfType(LLVMContext::OB_preallocated), - "musttail and preallocated not yet supported", &CI); // - The caller and callee prototypes must match. Pointer types of // parameters or return types may differ in pointee type, but not @@ -4533,6 +4534,9 @@ ++NumPreallocatedArgs; } } + Assert(NumPreallocatedArgs != 0, + "cannot use preallocated intrinsics on a call without " + "preallocated arguments"); Assert(NumArgs->equalsInt(NumPreallocatedArgs), "llvm.call.preallocated.setup arg size must be equal to number " "of preallocated arguments " diff --git a/llvm/test/Verifier/preallocated-invalid.ll b/llvm/test/Verifier/preallocated-invalid.ll --- a/llvm/test/Verifier/preallocated-invalid.ll +++ b/llvm/test/Verifier/preallocated-invalid.ll @@ -89,7 +89,7 @@ ret void } -; CHECK: preallocated operand requires a preallocated bundle +; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail define void @preallocated_require_bundle() { %cs = call token @llvm.call.preallocated.setup(i32 1) %x = call i8* @llvm.call.preallocated.arg(token %cs, i32 0) preallocated(i32) @@ -117,9 +117,22 @@ ret void } -; CHECK: musttail and preallocated not yet supported -define void @musttail() { +; CHECK: cannot use preallocated intrinsics on a call without preallocated arguments +define void @preallocated_no_preallocated_args() { %cs = call token @llvm.call.preallocated.setup(i32 0) - musttail call void @foo0() ["preallocated"(token %cs)] + call void @foo0() ["preallocated"(token %cs)] + ret void +} + +; CHECK: preallocated operand either requires a preallocated bundle or the call to be musttail +define void @musttail_and_bundle(i32* preallocated(i32) %a) { + %cs = call token @llvm.call.preallocated.setup(i32 0) + musttail call void @musttail_and_bundle(i32* preallocated(i32) %a) ["preallocated"(token %cs)] + ret void +} + +; CHECK: cannot guarantee tail call due to mismatched ABI impacting function attributes +define void @musttail_attr_no_match(i32* preallocated(i32) %a) { + musttail call void @musttail_and_bundle(i32* %a) ret void } diff --git a/llvm/test/Verifier/preallocated-valid.ll b/llvm/test/Verifier/preallocated-valid.ll --- a/llvm/test/Verifier/preallocated-valid.ll +++ b/llvm/test/Verifier/preallocated-valid.ll @@ -4,6 +4,7 @@ declare i8* @llvm.call.preallocated.arg(token, i32) declare void @foo1(i32* preallocated(i32)) +declare i64 @foo1_i64(i32* preallocated(i32)) declare void @foo2(i32* preallocated(i32), i32*, i32* preallocated(i32)) define void @preallocated() { @@ -38,3 +39,13 @@ call void @foo2(i32* preallocated(i32) %x1, i32* %a, i32* preallocated(i32) %y1) ["preallocated"(token %cs)] ret void } + +define void @preallocate_musttail(i32* preallocated(i32) %a) { + musttail call void @foo1(i32* preallocated(i32) %a) + ret void +} + +define i64 @preallocate_musttail_i64(i32* preallocated(i32) %a) { + %r = musttail call i64 @foo1_i64(i32* preallocated(i32) %a) + ret i64 %r +}