1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-18 18:42:46 +02:00

[PlaceSafepoints] New attributes for patchable statepoints.

Summary:
This patch teaches the PlaceSafepoints pass about two `CallSite`
function attributes:

 * "statepoint-id": if the string value of this attribute can be parsed
   as an integer, then it is propagated to the ID parameter of the
   statepoint created.

 * "statepoint-num-patch-bytes": if the string value of this attribute
   can be parsed as an integer, then it is propagated to the `num patch
   bytes` parameter of the statepoint created.

This change intentionally does not assert on a malformed value for these
attributes, given that they're not "official" attributes.

Reviewers: reames, pgavlin

Subscribers: llvm-commits

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

llvm-svn: 237286
This commit is contained in:
Sanjoy Das 2015-05-13 20:11:31 +00:00
parent 58d34e616d
commit 961d383020
3 changed files with 99 additions and 12 deletions

View File

@ -677,6 +677,21 @@ of this function is inserted at each poll site desired. While calls or invokes
inside this method are transformed to a ``gc.statepoints``, recursive poll
insertion is not performed.
By default PlaceSafepoints passes in ``0xABCDEF00`` as the statepoint
ID and ``0`` as the number of patchable bytes to the newly constructed
``gc.statepoint``. These values can be configured on a per-callsite
basis using the attributes ``"statepoint-id"`` and
``"statepoint-num-patch-bytes"``. If a call site is marked with a
``"statepoint-id"`` function attribute and its value is a positive
integer (represented as a string), then that value is used as the ID
of the newly constructed ``gc.statepoint``. If a call site is marked
with a ``"statepoint-num-patch-bytes"`` function attribute and its
value is a positive integer, then that value is used as the 'num patch
bytes' parameter of the newly constructed ``gc.statepoint``. The
``"statepoint-id"`` and ``"statepoint-num-patch-bytes"`` attributes
are not propagated to the ``gc.statepoint`` call or invoke if they
could be successfully parsed.
If you are scheduling the RewriteStatepointsForGC pass late in the pass order,
you should probably schedule this pass immediately before it. The exception
would be if you need to preserve abstract frame information (e.g. for

View File

@ -881,20 +881,52 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */
// Create the statepoint given all the arguments
Instruction *Token = nullptr;
AttributeSet OriginalAttrs;
uint64_t ID;
uint32_t NumPatchBytes;
AttributeSet OriginalAttrs = CS.getAttributes();
Attribute AttrID =
OriginalAttrs.getAttribute(AttributeSet::FunctionIndex, "statepoint-id");
Attribute AttrNumPatchBytes = OriginalAttrs.getAttribute(
AttributeSet::FunctionIndex, "statepoint-num-patch-bytes");
AttrBuilder AttrsToRemove;
bool HasID = AttrID.isStringAttribute() &&
!AttrID.getValueAsString().getAsInteger(10, ID);
if (HasID)
AttrsToRemove.addAttribute("statepoint-id");
else
ID = 0xABCDEF00;
bool HasNumPatchBytes =
AttrNumPatchBytes.isStringAttribute() &&
!AttrNumPatchBytes.getValueAsString().getAsInteger(10, NumPatchBytes);
if (HasNumPatchBytes)
AttrsToRemove.addAttribute("statepoint-num-patch-bytes");
else
NumPatchBytes = 0;
OriginalAttrs = OriginalAttrs.removeAttributes(
CS.getInstruction()->getContext(), AttributeSet::FunctionIndex,
AttrsToRemove);
Value *StatepointTarget = NumPatchBytes == 0
? CS.getCalledValue()
: ConstantPointerNull::get(cast<PointerType>(
CS.getCalledValue()->getType()));
if (CS.isCall()) {
CallInst *ToReplace = cast<CallInst>(CS.getInstruction());
CallInst *Call = Builder.CreateGCStatepointCall(
0xABCDEF00, 0, CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()),
None, None, "safepoint_token");
ID, NumPatchBytes, StatepointTarget,
makeArrayRef(CS.arg_begin(), CS.arg_end()), None, None,
"safepoint_token");
Call->setTailCall(ToReplace->isTailCall());
Call->setCallingConv(ToReplace->getCallingConv());
// Before we have to worry about GC semantics, all attributes are legal
// TODO: handle param attributes
OriginalAttrs = ToReplace->getAttributes();
// In case if we can handle this set of attributes - set up function
// attributes directly on statepoint and return attributes later for
// gc_result intrinsic.
@ -915,14 +947,10 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */
// original block.
Builder.SetInsertPoint(ToReplace->getParent());
InvokeInst *Invoke = Builder.CreateGCStatepointInvoke(
0xABCDEF00, 0, CS.getCalledValue(), ToReplace->getNormalDest(),
ID, NumPatchBytes, StatepointTarget, ToReplace->getNormalDest(),
ToReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()),
Builder.getInt32(0), None, "safepoint_token");
// Currently we will fail on parameter attributes and on certain
// function attributes.
OriginalAttrs = ToReplace->getAttributes();
// In case if we can handle this set of attributes - set up function
// attributes directly on statepoint and return attributes later for
// gc_result intrinsic.

View File

@ -0,0 +1,44 @@
; RUN: opt -place-safepoints -S < %s | FileCheck %s
declare void @f()
declare i32 @personality_function()
define void @test_id() gc "statepoint-example" {
; CHECK-LABEL: @test_id(
entry:
; CHECK-LABEL: entry:
; CHECK: invoke i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 100, i32 0, void ()* @f
invoke void @f() "statepoint-id"="100" to label %normal_return unwind label %exceptional_return
normal_return:
ret void
exceptional_return:
%landing_pad4 = landingpad {i8*, i32} personality i32 ()* @personality_function cleanup
ret void
}
define void @test_num_patch_bytes() gc "statepoint-example" {
; CHECK-LABEL: @test_num_patch_bytes(
entry:
; CHECK-LABEL: entry:
; CHECK: invoke i32 (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 99, void ()* null,
invoke void @f() "statepoint-num-patch-bytes"="99" to label %normal_return unwind label %exceptional_return
normal_return:
ret void
exceptional_return:
%landing_pad4 = landingpad {i8*, i32} personality i32 ()* @personality_function cleanup
ret void
}
declare void @do_safepoint()
define void @gc.safepoint_poll() {
entry:
call void @do_safepoint()
ret void
}
; CHECK-NOT: statepoint-id
; CHECK-NOT: statepoint-num-patch_bytes