forked from OSchip/llvm-project
Add a "gc-transition" operand bundle
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 llvm-svn: 258338
This commit is contained in:
parent
af69f1c690
commit
a34ce95b60
|
@ -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
|
||||
|
|
|
@ -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
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -71,8 +71,9 @@ public:
|
|||
/// 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.
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue