Add 'notail' marker for call instructions.
authorAkira Hatanaka <ahatanaka@apple.com>
Fri, 6 Nov 2015 23:55:38 +0000 (23:55 +0000)
committerAkira Hatanaka <ahatanaka@apple.com>
Fri, 6 Nov 2015 23:55:38 +0000 (23:55 +0000)
This marker prevents optimization passes from adding 'tail' or
'musttail' markers to a call. Is is used to prevent tail call
optimization from being performed on the call.

rdar://problem/22667622

Differential Revision: http://reviews.llvm.org/D12923

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252368 91177308-0d34-0410-b5e6-96231b3b80d8

docs/LangRef.rst
include/llvm/IR/Instructions.h
lib/AsmParser/LLLexer.cpp
lib/AsmParser/LLParser.cpp
lib/AsmParser/LLToken.h
lib/Bitcode/Reader/BitcodeReader.cpp
lib/Bitcode/Writer/BitcodeWriter.cpp
lib/IR/AsmWriter.cpp
lib/Transforms/Scalar/TailRecursionElimination.cpp
test/Bitcode/compatibility.ll
test/Transforms/TailCallElim/notail.ll [new file with mode: 0644]

index d2bba5c8a74310e22567cf78417c7b70e305463d..d58b7b2e4df720c691de1c898d6986bc9dffdd2b 100644 (file)
@@ -8386,7 +8386,7 @@ Syntax:
 
 ::
 
-      <result> = [tail | musttail] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
+      <result> = [tail | musttail | notail ] call [cconv] [ret attrs] <ty> [<fnty>*] <fnptrval>(<function args>) [fn attrs]
                    [ operand bundles ]
 
 Overview:
@@ -8439,6 +8439,10 @@ This instruction requires several arguments:
    -  `Platform-specific constraints are
       met. <CodeGenerator.html#tailcallopt>`_
 
+#. The optional ``notail`` marker indicates that the optimizers should not add
+   ``tail`` or ``musttail`` markers to the call. It is used to prevent tail
+   call optimization from being performed on the call.
+
 #. The optional "cconv" marker indicates which :ref:`calling
    convention <callingconv>` the call should use. If none is
    specified, the call defaults to using C calling conventions. The
index c2ade1994f5dc08ee9d7b6e3d2c754804a62ed36..263d0918d8415c7f0a4b4b76f36c6cb6b0903d29 100644 (file)
@@ -1489,16 +1489,21 @@ public:
   }
 
   // Note that 'musttail' implies 'tail'.
-  enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 };
+  enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2,
+                      TCK_NoTail = 3 };
   TailCallKind getTailCallKind() const {
     return TailCallKind(getSubclassDataFromInstruction() & 3);
   }
   bool isTailCall() const {
-    return (getSubclassDataFromInstruction() & 3) != TCK_None;
+    unsigned Kind = getSubclassDataFromInstruction() & 3;
+    return Kind == TCK_Tail || Kind == TCK_MustTail;
   }
   bool isMustTailCall() const {
     return (getSubclassDataFromInstruction() & 3) == TCK_MustTail;
   }
+  bool isNoTailCall() const {
+    return (getSubclassDataFromInstruction() & 3) == TCK_NoTail;
+  }
   void setTailCall(bool isTC = true) {
     setInstructionSubclassData((getSubclassDataFromInstruction() & ~3) |
                                unsigned(isTC ? TCK_Tail : TCK_None));
index 82d6eb7788cc3844f413328c9f9703cfd54aa5a6..91ce1fd7669dfebba2dc27b9c0048f70b1002c8f 100644 (file)
@@ -527,6 +527,7 @@ lltok::Kind LLLexer::LexIdentifier() {
   KEYWORD(caller);
   KEYWORD(tail);
   KEYWORD(musttail);
+  KEYWORD(notail);
   KEYWORD(target);
   KEYWORD(triple);
   KEYWORD(unwind);
index 7feb99d555c5e5a99c5bf1b5fd55c89a091fdfe3..aabd9716118fd32124f6e78d7152b7e3cbd62020 100644 (file)
@@ -4830,6 +4830,7 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB,
   case lltok::kw_call:     return ParseCall(Inst, PFS, CallInst::TCK_None);
   case lltok::kw_tail:     return ParseCall(Inst, PFS, CallInst::TCK_Tail);
   case lltok::kw_musttail: return ParseCall(Inst, PFS, CallInst::TCK_MustTail);
+  case lltok::kw_notail:   return ParseCall(Inst, PFS, CallInst::TCK_NoTail);
   // Memory.
   case lltok::kw_alloca:         return ParseAlloc(Inst, PFS);
   case lltok::kw_load:           return ParseLoad(Inst, PFS);
index ecd6481e6faafdbe5fedf712e7afcecf2bc17c5a..6980790c098dcf47b932de2c5e2cab8061083b14 100644 (file)
@@ -54,6 +54,7 @@ namespace lltok {
     kw_caller,
     kw_tail,
     kw_musttail,
+    kw_notail,
     kw_target,
     kw_triple,
     kw_unwind,
index bc846192fcfd02674000237aacfaf7020cc977d9..a0029b26ff95cec2463a0b1d45b418dac185d122 100644 (file)
@@ -5002,6 +5002,8 @@ std::error_code BitcodeReader::parseFunctionBody(Function *F) {
         TCK = CallInst::TCK_Tail;
       if (CCInfo & (1 << 14))
         TCK = CallInst::TCK_MustTail;
+      if (CCInfo & (1 << 16))
+        TCK = CallInst::TCK_NoTail;
       cast<CallInst>(I)->setTailCallKind(TCK);
       cast<CallInst>(I)->setAttributes(PAL);
       break;
index 941e54765f5bb3803b0eb408cae81e1575a443a5..b88e55c92cbb32691428db25e889945fdea6349f 100644 (file)
@@ -2131,7 +2131,8 @@ static void WriteInstruction(const Instruction &I, unsigned InstID,
 
     Vals.push_back(VE.getAttributeID(CI.getAttributes()));
     Vals.push_back((CI.getCallingConv() << 1) | unsigned(CI.isTailCall()) |
-                   unsigned(CI.isMustTailCall()) << 14 | 1 << 15);
+                   unsigned(CI.isMustTailCall()) << 14 | 1 << 15 |
+                   unsigned(CI.isNoTailCall()) << 16);
     Vals.push_back(VE.getTypeID(FTy));
     PushValueAndType(CI.getCalledValue(), InstID, Vals, VE);  // Callee
 
index db757508594a2bcfdda37ef5c273b89caa0af220..2f8a3406a373c7863a699028697b0ddb4a6d6aaa 100644 (file)
@@ -2768,6 +2768,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
       Out << "musttail ";
     else if (CI->isTailCall())
       Out << "tail ";
+    else if (CI->isNoTailCall())
+      Out << "notail ";
   }
 
   // Print out the opcode...
index 1eddef7ef94141608a4a292fd61d87c8cd863bdf..7e1ba2c3c90366ea2f5b87caf14eb8535ec044d2 100644 (file)
@@ -304,7 +304,9 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) {
       if (!CI || CI->isTailCall())
         continue;
 
-      if (CI->doesNotAccessMemory()) {
+      bool IsNoTail = CI->isNoTailCall();
+
+      if (!IsNoTail && CI->doesNotAccessMemory()) {
         // A call to a readnone function whose arguments are all things computed
         // outside this function can be marked tail. Even if you stored the
         // alloca address into a global, a readnone function can't load the
@@ -332,7 +334,7 @@ bool TailCallElim::markTails(Function &F, bool &AllCallsAreTailCalls) {
         }
       }
 
-      if (Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) {
+      if (!IsNoTail && Escaped == UNESCAPED && !Tracker.AllocaUsers.count(CI)) {
         DeferredTails.push_back(CI);
       } else {
         AllCallsAreTailCalls = false;
index 73c24f0370a6528c45acab2537fae5f058a010e5..49689a992372b41e34a5e33376151db2e2f794d2 100644 (file)
@@ -1144,6 +1144,13 @@ define void @instructions.call_musttail(i8* inalloca %val) {
   ret void
 }
 
+define void @instructions.call_notail() {
+  notail call void @f1()
+  ; CHECK: notail call void @f1()
+
+  ret void
+}
+
 define void @instructions.landingpad() personality i32 -2 {
   invoke void @llvm.donothing() to label %proceed unwind label %catch1
   invoke void @llvm.donothing() to label %proceed unwind label %catch2
diff --git a/test/Transforms/TailCallElim/notail.ll b/test/Transforms/TailCallElim/notail.ll
new file mode 100644 (file)
index 0000000..e6fdbd1
--- /dev/null
@@ -0,0 +1,24 @@
+; RUN: opt < %s -tailcallelim -S | FileCheck %s
+
+; CHECK: tail call void @callee0()
+; CHECK: notail call void @callee1()
+
+define void @foo1(i32 %a) {
+entry:
+  %tobool = icmp eq i32 %a, 0
+  br i1 %tobool, label %if.else, label %if.then
+
+if.then:
+  call void @callee0()
+  br label %if.end
+
+if.else:
+  notail call void @callee1()
+  br label %if.end
+
+if.end:
+  ret void
+}
+
+declare void @callee0()
+declare void @callee1()