[llvm] 9a0b085 - Modify verifier checks to support musttail + preallocated

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Tue May 26 16:26:01 PDT 2020


Author: Arthur Eubanks
Date: 2020-05-26T15:20:20-07:00
New Revision: 9a0b0855a96ad91e082c6fb066e0ebabe72eb6b3

URL: https://github.com/llvm/llvm-project/commit/9a0b0855a96ad91e082c6fb066e0ebabe72eb6b3
DIFF: https://github.com/llvm/llvm-project/commit/9a0b0855a96ad91e082c6fb066e0ebabe72eb6b3.diff

LOG: 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

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst
index 0891392b1e61..61a0085c6f88 100644
--- a/llvm/docs/LangRef.rst
+++ b/llvm/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(<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,

diff  --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 4d64af3e8de4..5ca6762d1c7f 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/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 
diff er 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/llvm/test/Verifier/preallocated-invalid.ll b/llvm/test/Verifier/preallocated-invalid.ll
index faa4c7a9fbfe..7fdab33167e5 100644
--- a/llvm/test/Verifier/preallocated-invalid.ll
+++ b/llvm/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/llvm/test/Verifier/preallocated-valid.ll b/llvm/test/Verifier/preallocated-valid.ll
index 07f748ca8678..483493c0c747 100644
--- a/llvm/test/Verifier/preallocated-valid.ll
+++ b/llvm/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
+}


        


More information about the llvm-commits mailing list