Skip to content

Commit

Permalink
Add a "gc-transition" operand bundle
Browse files Browse the repository at this point in the history
Summary:
This adds a new kind of operand bundle to LLVM denoted by the
`"gc-transition"` tag.  Inputs to `"gc-transition"` operand bundle are
lowered into the "transition args" section of `gc.statepoint` by
`RewriteStatepointsForGC`.

This removes the last bit of functionality that was unsupported in the
deopt bundle based code path in `RewriteStatepointsForGC`.

Reviewers: pgavlin, JosephTremoulet, reames

Subscribers: sanjoy, mcrosier, llvm-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@258338 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
sanjoy committed Jan 20, 2016
1 parent 8ae8a5e commit e6a9ed7
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 10 deletions.
12 changes: 12 additions & 0 deletions docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1602,6 +1602,18 @@ it is undefined behavior to execute a ``call`` or ``invoke`` which:
Similarly, if no funclet EH pads have been entered-but-not-yet-exited,
executing a ``call`` or ``invoke`` with a ``"funclet"`` bundle is undefined behavior.

GC Transition Operand Bundles
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

GC transition operand bundles are characterized by the
``"gc-transition"`` operand bundle tag. These operand bundles mark a
call as a transition between a function with one GC strategy to a
function with a different GC strategy. If coordinating the transition
between GC strategies requires additional code generation at the call
site, these bundles may contain any values that are needed by the
generated code. For more details, see :ref:`GC Transitions
<gc_transition_args>`.

.. _moduleasm:

Module-Level Inline Assembly
Expand Down
4 changes: 3 additions & 1 deletion docs/Statepoints.rst
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,9 @@ we get:
Note that in this example %p and %obj.relocate are the same address and we
could replace one with the other, potentially removing the derived pointer
from the live set at the safepoint entirely.
from the live set at the safepoint entirely.

.. _gc_transition_args:

GC Transitions
^^^^^^^^^^^^^^^^^^
Expand Down
5 changes: 3 additions & 2 deletions include/llvm/IR/LLVMContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ class LLVMContext {
/// Additionally, this scheme allows LLVM to efficiently check for specific
/// operand bundle tags without comparing strings.
enum {
OB_deopt = 0, // "deopt"
OB_funclet = 1, // "funclet"
OB_deopt = 0, // "deopt"
OB_funclet = 1, // "funclet"
OB_gc_transition = 2, // "gc-transition"
};

/// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
Expand Down
5 changes: 5 additions & 0 deletions lib/IR/LLVMContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
assert(FuncletEntry->second == LLVMContext::OB_funclet &&
"funclet operand bundle id drifted!");
(void)FuncletEntry;

auto *GCTransitionEntry = pImpl->getOrInsertBundleTag("gc-transition");
assert(GCTransitionEntry->second == LLVMContext::OB_gc_transition &&
"gc-transition operand bundle id drifted!");
(void)GCTransitionEntry;
}
LLVMContext::~LLVMContext() { delete pImpl; }

Expand Down
14 changes: 9 additions & 5 deletions lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2513,17 +2513,21 @@ void Verifier::VerifyCallSite(CallSite CS) {
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
visitIntrinsicCallSite(ID, CS);

// Verify that a callsite has at most one "deopt" and one "funclet" operand
// bundle.
bool FoundDeoptBundle = false, FoundFuncletBundle = false;
// Verify that a callsite has at most one "deopt", at most one "funclet" and
// at most one "gc-transition" operand bundle.
bool FoundDeoptBundle = false, FoundFuncletBundle = false,
FoundGCTransitionBundle = false;
for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) {
OperandBundleUse BU = CS.getOperandBundleAt(i);
uint32_t Tag = BU.getTagID();
if (Tag == LLVMContext::OB_deopt) {
Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I);
FoundDeoptBundle = true;
}
if (Tag == LLVMContext::OB_funclet) {
} else if (Tag == LLVMContext::OB_gc_transition) {
Assert(!FoundGCTransitionBundle, "Multiple gc-transition operand bundles",
I);
FoundGCTransitionBundle = true;
} else if (Tag == LLVMContext::OB_funclet) {
Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", I);
FoundFuncletBundle = true;
Assert(BU.Inputs.size() == 1,
Expand Down
7 changes: 5 additions & 2 deletions lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1404,8 +1404,11 @@ makeStatepointExplicitImpl(const CallSite CS, /* to replace */
if (UseDeoptBundles) {
CallArgs = {CS.arg_begin(), CS.arg_end()};
DeoptArgs = GetDeoptBundleOperands(CS);
// TODO: we don't fill in TransitionArgs or Flags in this branch, but we
// could have an operand bundle for that too.
if (auto TransitionBundle =
CS.getOperandBundle(LLVMContext::OB_gc_transition)) {
Flags |= uint32_t(StatepointFlags::GCTransition);
TransitionArgs = TransitionBundle->Inputs;
}
AttributeSet OriginalAttrs = CS.getAttributes();

Attribute AttrID = OriginalAttrs.getAttribute(AttributeSet::FunctionIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,11 @@ define i32 addrspace(1)* @f3(i32 addrspace(1)* %arg) gc "statepoint-example" pe
%lpad = landingpad token cleanup
resume token undef
}

define i32 addrspace(1)* @f4(i32 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: @f4(
entry:
; CHECK: @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @g, i32 0, i32 1, i32 2, i32 400, i8 90,
call void @g() [ "gc-transition"(i32 400, i8 90) ]
ret i32 addrspace(1)* %arg
}
13 changes: 13 additions & 0 deletions test/Verifier/operand-bundles.ll
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,16 @@ define void @f_deopt(i32* %ptr) {
%x = add i32 42, 1
ret void
}

define void @f_gc_transition(i32* %ptr) {
; CHECK: Multiple gc-transition operand bundles
; CHECK-NEXT: call void @g() [ "gc-transition"(i32 42, i64 100, i32 %x), "gc-transition"(float 0.000000e+00, i64 100, i32 %l) ]
; CHECK-NOT: call void @g() [ "gc-transition"(i32 42, i64 120, i32 %x) ]

entry:
%l = load i32, i32* %ptr
call void @g() [ "gc-transition"(i32 42, i64 100, i32 %x), "gc-transition"(float 0.0, i64 100, i32 %l) ]
call void @g() [ "gc-transition"(i32 42, i64 120) ] ;; The verifier should not complain about this one
%x = add i32 42, 1
ret void
}

0 comments on commit e6a9ed7

Please sign in to comment.