Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -1488,6 +1488,25 @@ of the called function. Inter-procedural optimizations work as usual as long as they take into account the first two properties. +More specific types of operand bundles are described below. + +Deoptimization Operand Bundles +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Deoptimization operand bundles are characterized by the ``"deopt`` +operand bundle tag. These operand bundles represent an alternate +"safe" continuation for the call site they're attached to, and can be +used by a suitable runtime to deoptimize the compiled frame at the +specified call site. Exact details of deoptimization is out of scope +for the language reference, but it usually involves rewriting a +compiled frame into a set of interpreted frames. + +From the compiler's perspective, deoptimization operand bundles make +the call sites they're attached to at least ``readonly``. They read +through all of their pointer typed operands (even if they're not +otherwise escaped) and the entire visible heap. Deoptimization +operand bundles do not capture their operands. + .. _moduleasm: Module-Level Inline Assembly Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -67,6 +67,14 @@ MD_align = 17 // "align" }; + // Known operand bundle tag IDs, which always have the same value. All + // operand bundle tags that LLVM has special knowledge of are listed here. + // Additionally, this scheme allows LLVM to efficiently check for specific + // operand bundle tags without comparing strings. + enum { + OB_deopt = 0, // "deopt" + }; + /// getMDKindID - Return a unique non-zero ID for the specified metadata kind. /// This ID is uniqued across modules in the current LLVMContext. unsigned getMDKindID(StringRef Name) const; Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -46,6 +46,9 @@ YieldCallback = nullptr; YieldOpaqueHandle = nullptr; NamedStructTypesUniqueID = 0; + + auto *DeoptTag = getOrInsertBundleTag("deopt"); + assert(DeoptTag->second == LLVMContext::OB_deopt && "Out of order"); } namespace { Index: lib/IR/Verifier.cpp =================================================================== --- lib/IR/Verifier.cpp +++ lib/IR/Verifier.cpp @@ -2324,6 +2324,15 @@ if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) visitIntrinsicCallSite(ID, CS); + // Verify that a callsite has at most one "deopt" operand bundle. + bool FoundDeoptBundle = false; + for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) { + if (CS.getOperandBundleAt(i).getTagID() == LLVMContext::OB_deopt) { + Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I); + FoundDeoptBundle = true; + } + } + visitInstruction(*I); } Index: test/Verifier/operand-bundles.ll =================================================================== --- test/Verifier/operand-bundles.ll +++ test/Verifier/operand-bundles.ll @@ -34,3 +34,14 @@ %x = add i32 42, 1 ret void } + +define void @f_deopt(i32* %ptr) { +; CHECK: Multiple deopt operand bundles +; CHECK-NEXT: call void @g() [ "deopt"(i32 42, i64 100, i32 %x), "deopt"(float 0.000000e+00, i64 100, i32 %l) ] + + entry: + %l = load i32, i32* %ptr + call void @g() [ "deopt"(i32 42, i64 100, i32 %x), "deopt"(float 0.0, i64 100, i32 %l) ] + %x = add i32 42, 1 + ret void +}