1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 04:32:44 +01:00

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
This commit is contained in:
Arthur Eubanks 2020-05-26 12:36:03 -07:00
parent 7c8e51c47a
commit 79048330b0
4 changed files with 49 additions and 16 deletions

View File

@ -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(<ty>)``
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<int_call_preallocated_arg>`, although is
ignored during codegen.
:ref:`llvm.call.preallocated.arg<int_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 <attr_inalloca>` attribute are
forwarded in place.
#. Arguments with the :ref:`inalloca <attr_inalloca>` or
:ref:`preallocated <attr_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,

View File

@ -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 "

View File

@ -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
}

View File

@ -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
}