From 79048330b0e8161b132379da874ae4639728c9cf Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Tue, 26 May 2020 12:36:03 -0700 Subject: [PATCH] Modify verifier checks to support musttail + preallocated Summary: preallocated and musttail can work together, but we don't want to call @llvm.call.preallocated.setup() to modify the stack in musttail calls. So we shouldn't have the "preallocated" operand bundle when a preallocated call is musttail. Also disallow use of preallocated on calls without preallocated. Codegen not yet implemented. Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D80581 --- docs/LangRef.rst | 17 +++++++++++------ lib/IR/Verifier.cpp | 16 ++++++++++------ test/Verifier/preallocated-invalid.ll | 21 +++++++++++++++++---- test/Verifier/preallocated-valid.ll | 11 +++++++++++ 4 files changed, 49 insertions(+), 16 deletions(-) diff --git a/docs/LangRef.rst b/docs/LangRef.rst index 0891392b1e6..61a0085c6f8 100644 --- a/docs/LangRef.rst +++ b/docs/LangRef.rst @@ -1065,17 +1065,22 @@ Currently, only the following parameter attributes are defined: 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 @@ This instruction requires several arguments: #. 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/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 4d64af3e8de..5ca6762d1c7 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -2988,9 +2988,13 @@ void Verifier::visitCallBase(CallBase &Call) { 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 @@ static AttrBuilder getParameterABIAttributes(int I, AttributeList Attrs) { 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 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) { ++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/test/Verifier/preallocated-invalid.ll b/test/Verifier/preallocated-invalid.ll index faa4c7a9fbf..7fdab33167e 100644 --- a/test/Verifier/preallocated-invalid.ll +++ b/test/Verifier/preallocated-invalid.ll @@ -89,7 +89,7 @@ define void @preallocated_attribute_type_mismatch() { 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 @@ define void @preallocated_arg_token() { 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/test/Verifier/preallocated-valid.ll b/test/Verifier/preallocated-valid.ll index 07f748ca867..483493c0c74 100644 --- a/test/Verifier/preallocated-valid.ll +++ b/test/Verifier/preallocated-valid.ll @@ -4,6 +4,7 @@ declare token @llvm.call.preallocated.setup(i32) 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 @@ define void @preallocated_num_args() { 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 +}