Modify verifier checks to support musttail + preallocated
authorArthur Eubanks <aeubanks@google.com>
Tue, 26 May 2020 19:36:03 +0000 (12:36 -0700)
committerArthur Eubanks <aeubanks@google.com>
Tue, 26 May 2020 22:20:20 +0000 (15:20 -0700)
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

llvm/docs/LangRef.rst
llvm/lib/IR/Verifier.cpp
llvm/test/Verifier/preallocated-invalid.ll
llvm/test/Verifier/preallocated-valid.ll

index 0891392..61a0085 100644 (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,
index 4d64af3..5ca6762 100644 (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 "
index faa4c7a..7fdab33 100644 (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
 }
index 07f748c..483493c 100644 (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
+}