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

Extend the statepoint intrinsic to allow statepoints to be marked as transitions from GC-aware code to code that is not GC-aware.

This changes the shape of the statepoint intrinsic from:

  @llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 unused, ...call args, i32 # deopt args, ...deopt args, ...gc args)

to:

  @llvm.experimental.gc.statepoint(anyptr target, i32 # call args, i32 flags, ...call args, i32 # transition args, ...transition args, i32 # deopt args, ...deopt args, ...gc args)

This extension offers the backend the opportunity to insert (somewhat) arbitrary code to manage the transition from GC-aware code to code that is not GC-aware and back.

In order to support the injection of transition code, this extension wraps the STATEPOINT ISD node generated by the usual lowering lowering with two additional nodes: GC_TRANSITION_START and GC_TRANSITION_END. The transition arguments that were passed passed to the intrinsic (if any) are lowered and provided as operands to these nodes and may be used by the backend during code generation.

Eventually, the lowering of the GC_TRANSITION_{START,END} nodes should be informed by the GC strategy in use for the function containing the intrinsic call; for now, these nodes are instead replaced with no-ops.

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

llvm-svn: 236888
This commit is contained in:
Pat Gavlin 2015-05-08 18:07:42 +00:00
parent 815c3c4a12
commit c022b8d288
43 changed files with 616 additions and 180 deletions

View File

@ -142,8 +142,8 @@ resulting relocation sequence is:
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
gc "statepoint-example" {
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4)
ret i8 addrspace(1)* %obj.relocated
}
@ -207,7 +207,82 @@ This example was taken from the tests for the :ref:`RewriteStatepointsForGC` uti
opt -rewrite-statepoints-for-gc test/Transforms/RewriteStatepointsForGC/basics.ll -S | llc -debug-only=stackmaps
GC Transitions
^^^^^^^^^^^^^^^^^^
As a practical consideration, many garbage-collected systems allow code that is
collector-aware ("managed code") to call code that is not collector-aware
("unmanaged code"). It is common that such calls must also be safepoints, since
it is desirable to allow the collector to run during the execution of
unmanaged code. Futhermore, it is common that coordinating the transition from
managed to unmanaged code requires extra code generation at the call site to
inform the collector of the transition. In order to support these needs, a
statepoint may be marked as a GC transition, and data that is necessary to
perform the transition (if any) may be provided as additional arguments to the
statepoint.
Note that although in many cases statepoints may be inferred to be GC
transitions based on the function symbols involved (e.g. a call from a
function with GC strategy "foo" to a function with GC strategy "bar"),
indirect calls that are also GC transitions must also be supported. This
requirement is the driving force behing the decision to require that GC
transitions are explicitly marked.
Let's revisit the sample given above, this time treating the call to ``@foo``
as a GC transition. Depending on our target, the transition code may need to
access some extra state in order to inform the collector of the transition.
Let's assume a hypothetical GC--somewhat unimaginatively named "hypothetical-gc"
--that requires that a TLS variable must be written to before and after a call
to unmanaged code. The resulting relocation sequence is:
.. code-block:: llvm
@flag = thread_local global i32 0, align 4
define i8 addrspace(1)* @test1(i8 addrspace(1) *%obj)
gc "hypothetical-gc" {
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 1, i32* @Flag, i32 0, i8 addrspace(1)* %obj)
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4)
ret i8 addrspace(1)* %obj.relocated
}
During lowering, this will result in a instruction selection DAG that looks
something like:
.. code-block::
CALLSEQ_START
...
GC_TRANSITION_START (lowered i32 *@Flag), SRCVALUE i32* Flag
STATEPOINT
GC_TRANSITION_END (lowered i32 *@Flag), SRCVALUE i32 *Flag
...
CALLSEQ_END
In order to generate the necessary transition code, the backend for each target
supported by "hypothetical-gc" must be modified to lower ``GC_TRANSITION_START``
and ``GC_TRANSITION_END`` nodes appropriately when the "hypothetical-gc"
strategy is in use for a particular function. Assuming that such lowering has
been added for X86, the generated assembly would be:
.. code-block:: gas
.globl test1
.align 16, 0x90
pushq %rax
movl $1, %fs:Flag@TPOFF
callq foo
movl $0, %fs:Flag@TPOFF
.Ltmp1:
movq (%rsp), %rax # This load is redundant (oops!)
popq %rdx
retq
Note that the design as presented above is not fully implemented: in particular,
strategy-specific lowering is not present, and all GC transitions are emitted as
as single no-op before and after the call instruction. These no-ops are often
removed by the backend during dead machine instruction elimination.
Intrinsics
@ -223,8 +298,9 @@ Syntax:
declare i32
@llvm.experimental.gc.statepoint(func_type <target>,
i64 <#call args>. i64 <unused>,
i64 <#call args>. i64 <flags>,
... (call parameters),
i64 <# transition args>, ... (transition parameters),
i64 <# deopt args>, ... (deopt parameters),
... (gc parameters))
@ -247,8 +323,19 @@ The '#call args' operand is the number of arguments to the actual
call. It must exactly match the number of arguments passed in the
'call parameters' variable length section.
The 'unused' operand is unused and likely to be removed. Please do
not use.
The 'flags' operand is used to specify extra information about the
statepoint. This is currently only used to mark certain statepoints
as GC transitions. This operand is a 64-bit integer with the following
layout, where bit 0 is the least significant bit:
+-------+---------------------------------------------------+
| Bit # | Usage |
+=======+===================================================+
| 0 | Set if the statepoint is a GC transition, cleared |
| | otherwise. |
+-------+---------------------------------------------------+
| 1-63 | Reserved for future use; must be cleared. |
+-------+---------------------------------------------------+
The 'call parameters' arguments are simply the arguments which need to
be passed to the call target. They will be lowered according to the
@ -257,6 +344,14 @@ instruction. The number of arguments must exactly match what is
specified in '# call args'. The types must match the signature of
'target'.
The 'transition parameters' arguments contain an arbitrary list of
Values which need to be passed to GC transition code. They will be
lowered and passed as operands to the appropriate GC_TRANSITION nodes
in the selection DAG. It is assumed that these arguments must be
available before and after (but not necessarily during) the execution
of the callee. The '# transition args' field indicates how many operands
are to be interpreted as 'transition parameters'.
The 'deopt parameters' arguments contain an arbitrary list of Values
which is meaningful to the runtime. The runtime may read any of these
values, but is assumed not to modify them. If the garbage collector
@ -471,7 +566,7 @@ As an example, given this code:
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
gc "statepoint-example" {
call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i8 addrspace(1)* %obj
}
@ -481,7 +576,7 @@ The pass would produce this IR:
define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
gc "statepoint-example" {
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
%0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
ret i8 addrspace(1)* %obj.relocated
}
@ -535,8 +630,8 @@ This pass would produce the following IR:
.. code-block:: llvm
define void @test() gc "statepoint-example" {
%safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
ret void
}

View File

@ -701,6 +701,15 @@ namespace ISD {
/// is the chain and the second operand is the alloca pointer.
LIFETIME_START, LIFETIME_END,
/// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the
/// beginning and end of GC transition sequence, and carry arbitrary
/// information that target might need for lowering. The first operand is
/// a chain, the rest are specified by the target and not touched by the DAG
/// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be
/// nested.
GC_TRANSITION_START,
GC_TRANSITION_END,
/// BUILTIN_OP_END - This must be the last enum value in this list.
/// The target-specific pre-isel opcode values start here.
BUILTIN_OP_END

View File

@ -24,6 +24,15 @@
#include "llvm/Support/Compiler.h"
namespace llvm {
/// The statepoint intrinsic accepts a set of flags as its third argument.
/// Valid values come out of this set.
enum class StatepointFlags {
None = 0,
GCTransition = 1, ///< Indicates that this statepoint is a transition from
///< GC-aware code to code that is not GC-aware.
MaskAll = GCTransition ///< A bitmask that includes all valid flags.
};
class GCRelocateOperands;
class ImmutableStatepoint;
@ -72,6 +81,10 @@ public:
/// Return the underlying CallSite.
CallSiteTy getCallSite() { return StatepointCS; }
uint64_t getFlags() const {
return cast<ConstantInt>(StatepointCS.getArgument(2))->getZExtValue();
}
/// Return the value actually being called or invoked.
ValueTy *getActualCallee() {
return StatepointCS.getArgument(ActualCalleePos);
@ -106,16 +119,42 @@ public:
return iterator_range<arg_iterator>(call_args_begin(), call_args_end());
}
/// Number of GC transition args.
int getNumTotalGCTransitionArgs() {
const Value *NumGCTransitionArgs = *gc_transition_args_begin();
return cast<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
}
typename CallSiteTy::arg_iterator gc_transition_args_begin() {
int Offset = call_args_end() - StatepointCS.arg_begin();
assert(Offset <= (int)StatepointCS.arg_size());
return StatepointCS.arg_begin() + Offset;
}
typename CallSiteTy::arg_iterator gc_transition_args_end() {
int Offset = (gc_transition_args_begin() + 1 +
getNumTotalGCTransitionArgs()) - StatepointCS.arg_begin();
assert(Offset <= (int)StatepointCS.arg_size());
return StatepointCS.arg_begin() + Offset;
}
/// range adapter for GC transition arguments
iterator_range<arg_iterator> gc_transition_args() {
return iterator_range<arg_iterator>(gc_transition_args_begin(),
gc_transition_args_end());
}
/// Number of additional arguments excluding those intended
/// for garbage collection.
int getNumTotalVMSArgs() {
Value *NumVMSArgs = *call_args_end();
Value *NumVMSArgs = *vm_state_begin();
return cast<ConstantInt>(NumVMSArgs)->getZExtValue();
}
typename CallSiteTy::arg_iterator vm_state_begin() { return call_args_end(); }
typename CallSiteTy::arg_iterator vm_state_begin() {
return gc_transition_args_end();
}
typename CallSiteTy::arg_iterator vm_state_end() {
int Offset = CallArgsBeginPos + getNumCallArgs() + 1 + getNumTotalVMSArgs();
int Offset = (gc_transition_args_end() + 1 + getNumTotalVMSArgs()) -
StatepointCS.arg_begin();
assert(Offset <= (int)StatepointCS.arg_size());
return StatepointCS.arg_begin() + Offset;
}
@ -152,6 +191,8 @@ public:
// The internal asserts in the iterator accessors do the rest.
(void)call_args_begin();
(void)call_args_end();
(void)gc_transition_args_begin();
(void)gc_transition_args_end();
(void)vm_state_begin();
(void)vm_state_end();
(void)gc_args_begin();

View File

@ -288,6 +288,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
case ISD::DEBUGTRAP: return "debugtrap";
case ISD::LIFETIME_START: return "lifetime.start";
case ISD::LIFETIME_END: return "lifetime.end";
case ISD::GC_TRANSITION_START: return "gc_transition.start";
case ISD::GC_TRANSITION_END: return "gc_transition.end";
// Bit manipulation
case ISD::BSWAP: return "bswap";

View File

@ -585,24 +585,66 @@ void SelectionDAGBuilder::LowerStatepoint(
SDNode *CallNode =
lowerCallFromStatepoint(ISP, LandingPad, *this, PendingExports);
// Construct the actual STATEPOINT node with all the appropriate arguments
// and return values.
// Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END
// nodes with all the appropriate arguments and return values.
// TODO: Currently, all of these operands are being marked as read/write in
// PrologEpilougeInserter.cpp, we should special case the VMState arguments
// and flags to be read-only.
SmallVector<SDValue, 40> Ops;
// Calculate and push starting position of vmstate arguments
// Call Node: Chain, Target, {Args}, RegMask, [Glue]
SDValue Chain = CallNode->getOperand(0);
SDValue Glue;
if (CallNode->getGluedNode()) {
bool CallHasIncomingGlue = CallNode->getGluedNode();
if (CallHasIncomingGlue) {
// Glue is always last operand
Glue = CallNode->getOperand(CallNode->getNumOperands() - 1);
}
// Build the GC_TRANSITION_START node if necessary.
//
// The operands to the GC_TRANSITION_{START,END} nodes are laid out in the
// order in which they appear in the call to the statepoint intrinsic. If
// any of the operands is a pointer-typed, that operand is immediately
// followed by a SRCVALUE for the pointer that may be used during lowering
// (e.g. to form MachinePointerInfo values for loads/stores).
const bool IsGCTransition =
(ISP.getFlags() & (uint64_t)StatepointFlags::GCTransition) ==
(uint64_t)StatepointFlags::GCTransition;
if (IsGCTransition) {
SmallVector<SDValue, 8> TSOps;
// Add chain
TSOps.push_back(Chain);
// Add GC transition arguments
for (auto I = ISP.gc_transition_args_begin() + 1,
E = ISP.gc_transition_args_end();
I != E; ++I) {
TSOps.push_back(getValue(*I));
if ((*I)->getType()->isPointerTy())
TSOps.push_back(DAG.getSrcValue(*I));
}
// Add glue if necessary
if (CallHasIncomingGlue)
TSOps.push_back(Glue);
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
SDValue GCTransitionStart =
DAG.getNode(ISD::GC_TRANSITION_START, getCurSDLoc(), NodeTys, TSOps);
Chain = GCTransitionStart.getValue(0);
Glue = GCTransitionStart.getValue(1);
}
// Calculate and push starting position of vmstate arguments
// Get number of arguments incoming directly into call node
unsigned NumCallRegArgs =
CallNode->getNumOperands() - (Glue.getNode() ? 4 : 3);
CallNode->getNumOperands() - (CallHasIncomingGlue ? 4 : 3);
Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, getCurSDLoc(), MVT::i32));
// Add call target
@ -612,7 +654,7 @@ void SelectionDAGBuilder::LowerStatepoint(
// Add call arguments
// Get position of register mask in the call
SDNode::op_iterator RegMaskIt;
if (Glue.getNode())
if (CallHasIncomingGlue)
RegMaskIt = CallNode->op_end() - 2;
else
RegMaskIt = CallNode->op_end() - 1;
@ -621,11 +663,17 @@ void SelectionDAGBuilder::LowerStatepoint(
// Add a leading constant argument with the Flags and the calling convention
// masked together
CallingConv::ID CallConv = CS.getCallingConv();
int Flags = cast<ConstantInt>(CS.getArgument(2))->getZExtValue();
assert(Flags == 0 && "not expected to be used");
uint64_t Flags = cast<ConstantInt>(CS.getArgument(2))->getZExtValue();
assert(
((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)
&& "unknown flag used");
const int Shift = 1;
static_assert(
((~(uint64_t)0 << Shift) & (uint64_t)StatepointFlags::MaskAll) == 0,
"shift width too small");
Ops.push_back(DAG.getTargetConstant(StackMaps::ConstantOp, getCurSDLoc(),
MVT::i64));
Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << 1),
Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << Shift),
getCurSDLoc(), MVT::i64));
// Insert all vmstate and gcstate arguments
@ -635,7 +683,7 @@ void SelectionDAGBuilder::LowerStatepoint(
Ops.push_back(*RegMaskIt);
// Add chain
Ops.push_back(CallNode->getOperand(0));
Ops.push_back(Chain);
// Same for the glue, but we add it only if original call had it
if (Glue.getNode())
@ -648,8 +696,40 @@ void SelectionDAGBuilder::LowerStatepoint(
SDNode *StatepointMCNode =
DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops);
SDNode *SinkNode = StatepointMCNode;
// Build the GC_TRANSITION_END node if necessary.
//
// See the comment above regarding GC_TRANSITION_START for the layout of
// the operands to the GC_TRANSITION_END node.
if (IsGCTransition) {
SmallVector<SDValue, 8> TEOps;
// Add chain
TEOps.push_back(SDValue(StatepointMCNode, 0));
// Add GC transition arguments
for (auto I = ISP.gc_transition_args_begin() + 1,
E = ISP.gc_transition_args_end();
I != E; ++I) {
TEOps.push_back(getValue(*I));
if ((*I)->getType()->isPointerTy())
TEOps.push_back(DAG.getSrcValue(*I));
}
// Add glue
TEOps.push_back(SDValue(StatepointMCNode, 1));
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
SDValue GCTransitionStart =
DAG.getNode(ISD::GC_TRANSITION_END, getCurSDLoc(), NodeTys, TEOps);
SinkNode = GCTransitionStart.getNode();
}
// Replace original call
DAG.ReplaceAllUsesWith(CallNode, StatepointMCNode); // This may update Root
DAG.ReplaceAllUsesWith(CallNode, SinkNode); // This may update Root
// Remove originall call node
DAG.DeleteNode(CallNode);

View File

@ -17,6 +17,7 @@
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Statepoint.h"
using namespace llvm;
/// CreateGlobalString - Make a new global variable with an initializer that
@ -252,8 +253,9 @@ static std::vector<Value *> getStatepointArgs(IRBuilderBase &B,
std::vector<Value *> Args;
Args.push_back(ActualCallee);
Args.push_back(B.getInt32(CallArgs.size()));
Args.push_back(B.getInt32(0)); // unused
Args.push_back(B.getInt32((unsigned)StatepointFlags::None));
Args.insert(Args.end(), CallArgs.begin(), CallArgs.end());
Args.push_back(B.getInt32(0 /* no transition args */));
Args.push_back(B.getInt32(DeoptArgs.size()));
Args.insert(Args.end(), DeoptArgs.begin(), DeoptArgs.end());
Args.insert(Args.end(), GCArgs.begin(), GCArgs.end());

View File

@ -1529,9 +1529,12 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) {
Assert(NumCallArgs == NumParams,
"gc.statepoint mismatch in number of call args", &CI);
const Value *Unused = CS.getArgument(2);
Assert(isa<ConstantInt>(Unused) && cast<ConstantInt>(Unused)->isNullValue(),
"gc.statepoint parameter #3 must be zero", &CI);
const Value *FlagsV = CS.getArgument(2);
Assert(isa<ConstantInt>(FlagsV),
"gc.statepoint flags must be constant integer", &CI);
const uint64_t Flags = cast<ConstantInt>(FlagsV)->getZExtValue();
Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,
"unknown flag used in gc.statepoint flags argument", &CI);
// Verify that the types of the call parameter arguments match
// the type of the wrapped callee.
@ -1544,7 +1547,19 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) {
&CI);
}
const int EndCallArgsInx = 2+NumCallArgs;
const Value *NumDeoptArgsV = CS.getArgument(EndCallArgsInx+1);
const Value *NumTransitionArgsV = CS.getArgument(EndCallArgsInx+1);
Assert(isa<ConstantInt>(NumTransitionArgsV),
"gc.statepoint number of transition arguments "
"must be constant integer",
&CI);
const int NumTransitionArgs =
cast<ConstantInt>(NumTransitionArgsV)->getZExtValue();
Assert(NumTransitionArgs >= 0,
"gc.statepoint number of transition arguments must be positive", &CI);
const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs;
const Value *NumDeoptArgsV = CS.getArgument(EndTransitionArgsInx+1);
Assert(isa<ConstantInt>(NumDeoptArgsV),
"gc.statepoint number of deoptimization arguments "
"must be constant integer",
@ -1554,7 +1569,9 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) {
"must be positive",
&CI);
Assert(4 + NumCallArgs + NumDeoptArgs <= (int)CS.arg_size(),
const int ExpectedNumArgs =
5 + NumCallArgs + NumTransitionArgs + NumDeoptArgs;
Assert(ExpectedNumArgs <= (int)CS.arg_size(),
"gc.statepoint too few arguments according to length fields", &CI);
// Check that the only uses of this gc.statepoint are gc.result or
@ -3346,11 +3363,17 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
Assert(StatepointCS.arg_size() > NumCallArgs+3,
"gc.statepoint: mismatch in number of call arguments");
Assert(isa<ConstantInt>(StatepointCS.getArgument(NumCallArgs+3)),
"gc.statepoint: number of transition arguments must be "
"a constant integer");
const int NumTransitionArgs =
cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
const int DeoptArgsStart = 2 + NumCallArgs + 1 + NumTransitionArgs + 1;
Assert(isa<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart)),
"gc.statepoint: number of deoptimization arguments must be "
"a constant integer");
const int NumDeoptArgs =
cast<ConstantInt>(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4;
cast<ConstantInt>(StatepointCS.getArgument(DeoptArgsStart))->getZExtValue();
const int GCParamArgsStart = DeoptArgsStart + 1 + NumDeoptArgs;
const int GCParamArgsEnd = StatepointCS.arg_size();
Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd,
"gc.relocate: statepoint base index doesn't fall within the "

View File

@ -513,6 +513,10 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM,
setOperationAction(ISD::DYNAMIC_STACKALLOC, getPointerTy(), Custom);
// GC_TRANSITION_START and GC_TRANSITION_END need custom lowering.
setOperationAction(ISD::GC_TRANSITION_START, MVT::Other, Custom);
setOperationAction(ISD::GC_TRANSITION_END, MVT::Other, Custom);
if (!TM.Options.UseSoftFloat && X86ScalarSSEf64) {
// f32 and f64 use SSE.
// Set up the FP register classes.
@ -17425,6 +17429,48 @@ static SDValue LowerMGATHER(SDValue Op, const X86Subtarget *Subtarget,
return Op;
}
SDValue X86TargetLowering::LowerGC_TRANSITION_START(SDValue Op,
SelectionDAG &DAG) const {
// TODO: Eventually, the lowering of these nodes should be informed by or
// deferred to the GC strategy for the function in which they appear. For
// now, however, they must be lowered to something. Since they are logically
// no-ops in the case of a null GC strategy (or a GC strategy which does not
// require special handling for these nodes), lower them as literal NOOPs for
// the time being.
SmallVector<SDValue, 2> Ops;
Ops.push_back(Op.getOperand(0));
if (Op->getGluedNode())
Ops.push_back(Op->getOperand(Op->getNumOperands() - 1));
SDLoc OpDL(Op);
SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue);
SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0);
return NOOP;
}
SDValue X86TargetLowering::LowerGC_TRANSITION_END(SDValue Op,
SelectionDAG &DAG) const {
// TODO: Eventually, the lowering of these nodes should be informed by or
// deferred to the GC strategy for the function in which they appear. For
// now, however, they must be lowered to something. Since they are logically
// no-ops in the case of a null GC strategy (or a GC strategy which does not
// require special handling for these nodes), lower them as literal NOOPs for
// the time being.
SmallVector<SDValue, 2> Ops;
Ops.push_back(Op.getOperand(0));
if (Op->getGluedNode())
Ops.push_back(Op->getOperand(Op->getNumOperands() - 1));
SDLoc OpDL(Op);
SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue);
SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0);
return NOOP;
}
/// LowerOperation - Provide custom lowering hooks for some operations.
///
SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
@ -17514,6 +17560,9 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::FSINCOS: return LowerFSINCOS(Op, Subtarget, DAG);
case ISD::MGATHER: return LowerMGATHER(Op, Subtarget, DAG);
case ISD::MSCATTER: return LowerMSCATTER(Op, Subtarget, DAG);
case ISD::GC_TRANSITION_START:
return LowerGC_TRANSITION_START(Op, DAG);
case ISD::GC_TRANSITION_END: return LowerGC_TRANSITION_END(Op, DAG);
}
}

View File

@ -969,6 +969,8 @@ namespace llvm {
SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerWin64_i128OP(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGC_TRANSITION_START(SDValue Op, SelectionDAG &DAG) const;
SDValue LowerGC_TRANSITION_END(SDValue Op, SelectionDAG &DAG) const;
SDValue
LowerFormalArguments(SDValue Chain,

View File

@ -22,8 +22,8 @@ entry:
%alloca = alloca i1
%load2 = load i1, i1* %alloca
%load3 = load i32, i32 addrspace(1)* %dparam
%tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
%relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4)
%tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
%relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5)
%load4 = load i32, i32 addrspace(1)* %relocate
%nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5
%load5 = load i32, i32 addrspace(1)* %nparam

View File

@ -13,29 +13,29 @@
; function and integer
define i32* @test_iAny(i32* %v) gc "statepoint-example" {
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %v)
%v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %v)
%v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
ret i32* %v-new
}
; float
define float* @test_fAny(float* %v) gc "statepoint-example" {
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, float* %v)
%v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, float* %v)
%v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 5, i32 5)
ret float* %v-new
}
; array of integers
define [3 x i32]* @test_aAny([3 x i32]* %v) gc "statepoint-example" {
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %v)
%v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %v)
%v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
ret [3 x i32]* %v-new
}
; vector of integers
define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" {
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, <3 x i32>* %v)
%v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, <3 x i32>* %v)
%v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 5, i32 5)
ret <3 x i32>* %v-new
}
@ -43,8 +43,8 @@ define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" {
; struct
define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" {
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, %struct.test* %v)
%v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %struct.test* %v)
%v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 5, i32 5)
ret %struct.test* %v-new
}

View File

@ -21,7 +21,7 @@ define i32 addrspace(1)* @test(i32 addrspace(1)* %ptr) gc "statepoint-example" {
entry:
%alloca = alloca i32 addrspace(1)*, align 8
store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca)
call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca)
%rel = load i32 addrspace(1)*, i32 addrspace(1)** %alloca
ret i32 addrspace(1)* %rel
}
@ -38,7 +38,7 @@ define i32 addrspace(1)* @test2(i32 addrspace(1)* %ptr) gc "statepoint-example"
entry:
%alloca = alloca i32 addrspace(1)*, align 8
store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca)
call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca)
ret i32 addrspace(1)* null
}

View File

@ -20,7 +20,7 @@ define i1 @test_i1_return() gc "statepoint-example" {
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0)
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0)
%call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
ret i1 %call1
}
@ -32,7 +32,7 @@ define i32 @test_i32_return() gc "statepoint-example" {
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0)
%safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0, i32 0)
%call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
ret i32 %call1
}
@ -44,7 +44,7 @@ define i32* @test_i32ptr_return() gc "statepoint-example" {
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0)
%safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0, i32 0)
%call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
ret i32* %call1
}
@ -56,7 +56,7 @@ define float @test_float_return() gc "statepoint-example" {
; CHECK: popq %rax
; CHECK: retq
entry:
%safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0)
%safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0, i32 0)
%call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
ret float %call1
}
@ -70,8 +70,8 @@ define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
; CHECK-NEXT: popq %rdx
; CHECK-NEXT: retq
entry:
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
%call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %a)
%call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
ret i1 %call2
}
@ -81,7 +81,7 @@ define void @test_void_vararg() gc "statepoint-example" {
; Check a statepoint wrapping a *void* returning vararg function works
; CHECK: callq varargf
entry:
%safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0)
%safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0)
;; if we try to use the result from a statepoint wrapping a
;; non-void-returning varargf, we will experience a crash.
ret void

View File

@ -25,8 +25,8 @@ entry:
%before = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p
%cmp1 = call i1 @f(i32 addrspace(1)* %before)
call void @llvm.assume(i1 %cmp1)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p)
%pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p)
%pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5)
%after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew
%cmp2 = call i1 @f(i32 addrspace(1)* %after)
ret i1 %cmp2
@ -44,8 +44,8 @@ entry:
%cmp1 = call i1 @f(i32 addrspace(1)* %v)
call void @llvm.assume(i1 %cmp1)
store i32 addrspace(1)* %v, i32 addrspace(1)* addrspace(1)* %p
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p)
%pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p)
%pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5)
%after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew
%cmp2 = call i1 @f(i32 addrspace(1)* %after)
ret i1 %cmp2
@ -72,7 +72,7 @@ entry:
%before = load i32 addrspace(1)*, i32 addrspace(1)** %p
%cmp1 = call i1 @f(i32 addrspace(1)* %before)
call void @llvm.assume(i1 %cmp1)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0)
%after = load i32 addrspace(1)*, i32 addrspace(1)** %p
%cmp2 = call i1 @f(i32 addrspace(1)* %after)
ret i1 %cmp2
@ -90,7 +90,7 @@ entry:
%cmp1 = call i1 @f(i32 addrspace(1)* %v)
call void @llvm.assume(i1 %cmp1)
store i32 addrspace(1)* %v, i32 addrspace(1)** %p
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0)
%after = load i32 addrspace(1)*, i32 addrspace(1)** %p
%cmp2 = call i1 @f(i32 addrspace(1)* %after)
ret i1 %cmp2

View File

@ -0,0 +1,133 @@
; RUN: llc < %s | FileCheck %s
; This file contains a collection of basic tests to ensure we didn't
; screw up normal call lowering when a statepoint is a GC transition.
target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-linux-gnu"
declare zeroext i1 @return_i1()
declare zeroext i32 @return_i32()
declare zeroext i32 @return_i32_with_args(i32, i8*)
declare i32* @return_i32ptr()
declare float @return_float()
declare void @varargf(i32, ...)
define i1 @test_i1_return() gc "statepoint-example" {
; CHECK-LABEL: test_i1_return
; This is just checking that a i1 gets lowered normally when there's no extra
; state arguments to the statepoint
; CHECK: pushq %rax
; CHECK: callq return_i1
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0)
%call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
ret i1 %call1
}
define i32 @test_i32_return() gc "statepoint-example" {
; CHECK-LABEL: test_i32_return
; CHECK: pushq %rax
; CHECK: callq return_i32
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 1, i32 0, i32 0)
%call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
ret i32 %call1
}
define i32* @test_i32ptr_return() gc "statepoint-example" {
; CHECK-LABEL: test_i32ptr_return
; CHECK: pushq %rax
; CHECK: callq return_i32ptr
; CHECK: popq %rdx
; CHECK: retq
entry:
%safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 1, i32 0, i32 0)
%call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
ret i32* %call1
}
define float @test_float_return() gc "statepoint-example" {
; CHECK-LABEL: test_float_return
; CHECK: pushq %rax
; CHECK: callq return_float
; CHECK: popq %rax
; CHECK: retq
entry:
%safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 1, i32 0, i32 0)
%call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
ret float %call1
}
define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
; CHECK-LABEL: test_relocate
; Check that an ununsed relocate has no code-generation impact
; CHECK: pushq %rax
; CHECK: callq return_i1
; CHECK-NEXT: .Ltmp9:
; CHECK-NEXT: popq %rdx
; CHECK-NEXT: retq
entry:
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0, i32 addrspace(1)* %a)
%call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
ret i1 %call2
}
define void @test_void_vararg() gc "statepoint-example" {
; CHECK-LABEL: test_void_vararg
; Check a statepoint wrapping a *void* returning vararg function works
; CHECK: callq varargf
entry:
%safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 1, i32 42, i32 43, i32 0, i32 0)
;; if we try to use the result from a statepoint wrapping a
;; non-void-returning varargf, we will experience a crash.
ret void
}
define i32 @test_transition_args() gc "statepoint-example" {
; CHECK-LABEL: test_transition_args
; CHECK: pushq %rax
; CHECK: callq return_i32
; CHECK: popq %rdx
; CHECK: retq
entry:
%val = alloca i32
%safepoint_token = call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 1, i32 2, i32* %val, i64 42, i32 0)
%call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
ret i32 %call1
}
define i32 @test_transition_args_2() gc "statepoint-example" {
; CHECK-LABEL: test_transition_args_2
; CHECK: pushq %rax
; CHECK: callq return_i32
; CHECK: popq %rdx
; CHECK: retq
entry:
%val = alloca i32
%arg = alloca i8
%safepoint_token = call i32 (i32 (i32, i8*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i32 (i32, i8*)* @return_i32_with_args, i32 2, i32 1, i32 0, i8* %arg, i32 2, i32* %val, i64 42, i32 0)
%call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
ret i32 %call1
}
declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
declare i1 @llvm.experimental.gc.result.i1(i32)
declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()*, i32, i32, ...)
declare i32 @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i32 (i32, i8*)*, i32, i32, ...)
declare i32 @llvm.experimental.gc.result.i32(i32)
declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...)
declare i32* @llvm.experimental.gc.result.p0i32(i32)
declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...)
declare float @llvm.experimental.gc.result.f32(i32)
declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...)
declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)

View File

@ -13,7 +13,7 @@ entry:
; CHECK: .Ltmp{{[0-9]+}}:
; CHECK: callq some_other_call
; CHECK: .Ltmp{{[0-9]+}}:
%0 = invoke i32 (i64 addrspace(1)* (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64p1i64f(i64 addrspace(1)* (i64 addrspace(1)*)* @some_other_call, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1)
%0 = invoke i32 (i64 addrspace(1)* (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64p1i64f(i64 addrspace(1)* (i64 addrspace(1)*)* @some_other_call, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1)
to label %normal_return unwind label %exceptional_return
normal_return:

View File

@ -14,17 +14,17 @@ define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 a
; CHECK: movq %rdx, 16(%rsp)
; CHECK: movq %rdi, 8(%rsp)
; CHECK: movq %rsi, (%rsp)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9)
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10)
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10)
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11)
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12)
; CHECK: callq
; This is the key check. There should NOT be any memory moves here
; CHECK-NOT: movq
%safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11)
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10)
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9)
%safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12)
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11)
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10)
; CHECK: callq
ret i32 1
}
@ -37,17 +37,17 @@ define i32 @reserve_first(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrsp
; CHECK: movq %rdx, 16(%rsp)
; CHECK: movq %rdi, 8(%rsp)
; CHECK: movq %rsi, (%rsp)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9)
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10)
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c)
%a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10)
%b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11)
%c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12)
; CHECK: callq
; This is the key check. There should NOT be any memory moves here
; CHECK-NOT: movq
%safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 addrspace(1)* %a1, i32 0, i32 addrspace(1)* %c1, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11)
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10)
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9)
%safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 addrspace(1)* %a1, i32 0, i32 addrspace(1)* %c1, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1)
%a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12)
%b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11)
%c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10)
; CHECK: callq
ret i32 1
}

View File

@ -21,10 +21,10 @@ define i1 @test(i32 addrspace(1)* %ptr) gc "statepoint-example" {
entry:
%metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
%safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null)
%call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
%a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6)
%b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
%a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
%b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 8, i32 8)
;
ret i1 %call1
}

View File

@ -10,9 +10,9 @@ define i32 @test_sor_basic(i32* %base) gc "statepoint-example" {
; CHECK: getelementptr i32, i32* %base-new, i32 15
entry:
%ptr = getelementptr i32, i32* %base, i32 15
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}
@ -20,15 +20,15 @@ entry:
define i32 @test_sor_two_derived(i32* %base) gc "statepoint-example" {
; CHECK: getelementptr i32, i32* %base, i32 15
; CHECK: getelementptr i32, i32* %base, i32 12
; CHECK: getelementptr i32, i32* %base-new, i32 15
; CHECK: getelementptr i32, i32* %base-new, i32 12
; CHECK: getelementptr i32, i32* %base-new, i32 15
entry:
%ptr = getelementptr i32, i32* %base, i32 15
%ptr2 = getelementptr i32, i32* %base, i32 12
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}
@ -38,9 +38,9 @@ define i32 @test_sor_ooo(i32* %base) gc "statepoint-example" {
; CHECK: getelementptr i32, i32* %base-new, i32 15
entry:
%ptr = getelementptr i32, i32* %base, i32 15
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}
@ -50,9 +50,9 @@ define i32 @test_sor_gep_smallint([3 x i32]* %base) gc "statepoint-example" {
; CHECK: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 2
entry:
%ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 2
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr)
%base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr)
%base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}
@ -62,23 +62,23 @@ define i32 @test_sor_gep_largeint([3 x i32]* %base) gc "statepoint-example" {
; CHECK-NOT: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 21
entry:
%ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 21
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr)
%base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr)
%base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}
define i32 @test_sor_noop(i32* %base) gc "statepoint-example" {
; CHECK: getelementptr i32, i32* %base, i32 15
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
entry:
%ptr = getelementptr i32, i32* %base, i32 15
%ptr2 = getelementptr i32, i32* %base, i32 12
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
%ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
%tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2)
%ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
%ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
%ret = load i32, i32* %ptr-new
ret i32 %ret
}

View File

@ -15,7 +15,7 @@ define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) gc
; CHECK: call dereferenceable(8)
entry:
%load = load i32, i32 addrspace(1)* %dparam
%tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
%relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4)
%tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam)
%relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5)
ret i32 addrspace(1)* %relocate
}

View File

@ -7,8 +7,8 @@ declare void @func()
define i1 @test_negative(i32 addrspace(1)* %p) gc "statepoint-example" {
entry:
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%cmp = icmp eq i32 addrspace(1)* %pnew, null
ret i1 %cmp
; CHECK-LABEL: test_negative
@ -18,8 +18,8 @@ entry:
define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) gc "statepoint-example" {
entry:
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%cmp = icmp eq i32 addrspace(1)* %pnew, null
ret i1 %cmp
; CHECK-LABEL: test_nonnull
@ -28,8 +28,8 @@ entry:
define i1 @test_null() gc "statepoint-example" {
entry:
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* null)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* null)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%cmp = icmp eq i32 addrspace(1)* %pnew, null
ret i1 %cmp
; CHECK-LABEL: test_null
@ -39,8 +39,8 @@ entry:
define i1 @test_undef() gc "statepoint-example" {
entry:
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* undef)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
%safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* undef)
%pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
%cmp = icmp eq i32 addrspace(1)* %pnew, null
ret i1 %cmp
; CHECK-LABEL: test_undef

View File

@ -73,7 +73,7 @@ define i1 @test_call_with_result() gc "statepoint-example" {
; inserted for a function that takes 1 argument.
; CHECK: gc.statepoint.p0f_isVoidf
; CHECK: gc.statepoint.p0f_i1i1f
; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0)
; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0, i32 0)
; CHECK: %call12 = call i1 @llvm.experimental.gc.result.i1
entry:
%call1 = tail call i1 (i1) @i1_return_i1(i1 false)

View File

@ -20,7 +20,7 @@ merge:
; CHECK-LABEL: merge:
; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %here ], [ %base_obj_y, %there ]
%merged_value = phi i64 addrspace(1)* [ %x, %here ], [ %y, %there ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %merged_value
}

View File

@ -30,7 +30,7 @@ false:
merge:
%next = phi i64 addrspace(1)* [ %next_x, %true ], [ %next_y, %false ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -19,7 +19,7 @@ loop: ; preds = %loop, %entry
; CHECK-DAG: [ %next.relocated, %loop ]
%current = phi i64 addrspace(1)* [ %obj, %entry ], [ %next, %loop ]
%next = getelementptr i64, i64 addrspace(1)* %current, i32 1
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -13,7 +13,7 @@ there:
merge:
%merged_value = phi i64 addrspace(1)* [ %base_obj, %entry ], [ %derived_obj, %there ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %merged_value
}

View File

@ -12,7 +12,7 @@ loop:
%current.i32 = bitcast i64 addrspace(1)* %current to i32 addrspace(1)*
%next.i32 = getelementptr i32, i32 addrspace(1)* %current.i32, i32 1
%next.i64 = bitcast i32 addrspace(1)* %next.i32 to i64 addrspace(1)*
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -13,9 +13,9 @@ entry:
loop:
; CHECK: loop:
; CHECK: %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i3
; CHECK: %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i3
; CHECK-NEXT: %obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result
%safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32 %safepoint_token1)
switch i32 %condition, label %dest_a [
i32 0, label %dest_b
@ -37,11 +37,11 @@ merge:
; CHECK: %obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ]
%obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ]
%safepoint_token3 = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @consume_obj, i32 1, i32 0, i64 addrspace(1)* %obj_to_consume, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token3 = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @consume_obj, i32 1, i32 0, i64 addrspace(1)* %obj_to_consume, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %merge.split
merge.split: ; preds = %merge
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -23,7 +23,7 @@ merge:
; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %base_obj_y, %there ]
; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ]
%merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %merged_value
}

View File

@ -33,7 +33,7 @@ merge:
; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %merge_here ], [ %base_obj_y, %there ]
; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
%merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %merged_value
}

View File

@ -44,7 +44,7 @@ merge:
; CHECK: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
%merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %merged_value
}

View File

@ -24,7 +24,7 @@ check_for_null:
loop_back:
%next_element_ptr = getelementptr i64 addrspace(1)*, i64 addrspace(1)* addrspace(1)* %current_element_ptr, i32 1
%next_index = add i32 %index, 1
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop_check
not_found:

View File

@ -13,7 +13,7 @@ loop:
%condition = call i1 @runtime_value()
%maybe_next = getelementptr i64, i64 addrspace(1)* %current, i32 1
%next = select i1 %condition, i64 addrspace(1)* %maybe_next, i64 addrspace(1)* %current
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -16,7 +16,7 @@ loop:
; CHECK-DAG: [ %obj.relocated, %loop ]
; CHECK-DAG: [ %obj, %entry ]
call void @use_obj(i64 addrspace(1)* %obj)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}
@ -57,7 +57,7 @@ define i64 addrspace(1)* @test1(i32 %caller, i8 addrspace(1)* %a, i8 addrspace(1
; CHECK: merge:
; CHECK-NEXT: %base_phi = phi i64 addrspace(1)* [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_R]], %right ], !is_base_value !0
%value = phi i64 addrspace(1)* [ %a.cast, %left], [ %a.cast, %left], [ %a.cast, %left], [ %b.cast, %right]
%safepoint_token = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @parse_point, i32 1, i32 0, i64 addrspace(1)* %value, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @parse_point, i32 1, i32 0, i64 addrspace(1)* %value, i32 0, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %value
}
@ -91,7 +91,7 @@ loop: ; preds = %loop, %entry
%nexta = getelementptr i64, i64 addrspace(1)* %current, i32 1
%next = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
%extra2 = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %loop
}

View File

@ -10,7 +10,7 @@ define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" {
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i8 addrspace(1)* %obj
}
@ -23,8 +23,8 @@ define i8 addrspace(1)* @test2(i8 addrspace(1)* %obj) gc "statepoint-example" {
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)*
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i8 addrspace(1)* %obj
}
@ -39,7 +39,7 @@ define i8 @test3(i8 addrspace(1)* %obj) gc "statepoint-example" {
; CHECK-NEXT: load i8, i8 addrspace(1)* %obj.relocated
entry:
%derived = getelementptr i8, i8 addrspace(1)* %obj, i64 10
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%a = load i8, i8 addrspace(1)* %derived
%b = load i8, i8 addrspace(1)* %obj
@ -57,14 +57,14 @@ taken:
; CHECK-LABEL: taken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %merge
untaken:
; CHECK-LABEL: untaken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)*
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %merge
merge:
@ -81,7 +81,7 @@ define i8 addrspace(1)* @test5(i8 addrspace(1)* %obj) gc "ocaml" {
; CHECK-NEXT: gc.statepoint
; CHECK-NOT: %obj.relocated = call coldcc i8 addrspace(1)*
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i8 addrspace(1)* %obj
}

View File

@ -9,7 +9,7 @@ define i8 @test() gc "statepoint-example" {
; CHECK: gc.statepoint
; CHECK-NEXT: load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
%res = load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
ret i8 %res
}
@ -22,7 +22,7 @@ define i8 @test2(i8 addrspace(1)* %p) gc "statepoint-example" {
; CHECK-NEXT: gc.relocate
; CHECK-NEXT: icmp
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
%cmp = icmp eq i8 addrspace(1)* %p, null
br i1 %cmp, label %taken, label %not_taken
@ -52,7 +52,7 @@ define i8 @test3(i1 %always_true) gc "statepoint-example" {
; CHECK: gc.statepoint
; CHECK-NEXT: load i8, i8 addrspace(1)* @G
entry:
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
%res = load i8, i8 addrspace(1)* @G, align 1
ret i8 %res
}

View File

@ -9,7 +9,7 @@ define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" {
; CHECK-NEXT: gc.relocate
; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated
entry:
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %obj
}
@ -25,7 +25,7 @@ define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoi
; CHECK-NEXT: insertelement
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5
entry:
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
ret <2 x i64 addrspace(1)*> %obj
}
@ -43,7 +43,7 @@ define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepo
; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5
entry:
%obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
ret <2 x i64 addrspace(1)*> %obj
}
@ -58,7 +58,7 @@ define <2 x i64 addrspace(1)*> @test4(<2 x i64 addrspace(1)*>* %ptr) gc "statepo
; CHECK-NEXT: gc.statepoint
entry:
%obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
to label %normal_return unwind label %exceptional_return
; CHECK-LABEL: normal_return:

View File

@ -15,7 +15,7 @@ taken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
; CHECK-NEXT: br label %merge
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %merge
untaken:
@ -23,7 +23,7 @@ untaken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)*
; CHECK-NEXT: br label %merge
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %merge
merge:
@ -40,7 +40,7 @@ entry:
; CHECK-LABEL: entry:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: br
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br i1 %cmp, label %taken, label %untaken
taken:
@ -51,7 +51,7 @@ taken:
; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated
%obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %obj
untaken:
@ -72,16 +72,16 @@ taken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
; CHECK-NEXT: br label %merge
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
%obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %merge
untaken:
; CHECK-LABEL: taken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: br label %merge
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %merge
merge:
@ -106,9 +106,9 @@ entry:
; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1
;
%derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
ret i64 addrspace(1)* %derived
}
@ -127,7 +127,7 @@ taken:
; CHECK-NEXT: gc.statepoint
; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
; CHECK-NEXT: br label %merge
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %merge
untaken:

View File

@ -16,7 +16,7 @@ next:
; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated)
; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated)
%obj2 = phi i64 addrspace(1)* [ %obj, %entry ]
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
call void (...) @consume(i64 addrspace(1)* %obj2)
call void (...) @consume(i64 addrspace(1)* %obj)
ret void
@ -32,7 +32,7 @@ define void @test7() gc "statepoint-example" {
unreached:
%obj = phi i64 addrspace(1)* [null, %unreached]
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
call void (...) @consume(i64 addrspace(1)* %obj)
br label %unreached
}
@ -45,7 +45,7 @@ define void @test8() gc "statepoint-example" {
ret void
unreached:
invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
to label %normal_return unwind label %exceptional_return
normal_return: ; preds = %entry

View File

@ -24,7 +24,7 @@ normal_dest:
;; CHECK-LABEL: normal_dest:
;; CHECK-NEXT: gc.statepoint
;; CHECK-NEXT: %obj.relocated = call coldcc i64* addrspace(1)*
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret i64* addrspace(1)* %obj
}

View File

@ -9,7 +9,7 @@ entry:
; CHECK-LABEL: @test1
; CHECK-DAG: %obj.relocated
; CHECK-DAG: %obj2.relocated
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %joint
joint:
@ -61,7 +61,7 @@ loop_x:
br label %loop.backedge
loop.backedge:
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
br label %loop
loop_y:
@ -79,14 +79,14 @@ if_branch:
; CHECK-LABEL: if_branch:
; CHECK: gc.statepoint
; CHECK: gc.relocate
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %join
else_branch:
; CHECK-LABEL: else_branch:
; CHECK: gc.statepoint
; CHECK: gc.relocate
%safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
br label %join
join:
@ -109,8 +109,8 @@ entry:
; CHECK: gc.statepoint
; CHECK-NEXT: gc.relocate
; CHECK-NEXT: gc.statepoint
%safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
ret void
}
@ -123,9 +123,9 @@ define void @test4() gc "statepoint-example" {
; CHECK: gc.statepoint
; CHECK: gc.relocate
; CHECK: @use(i8 addrspace(1)* %res.relocated)
%safepoint_token2 = tail call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
%safepoint_token2 = tail call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
%res = call i8 addrspace(1)* @llvm.experimental.gc.result.ptr.p1i8(i32 %safepoint_token2)
call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
call void (...) @use(i8 addrspace(1)* %res)
unreachable
}
@ -135,7 +135,7 @@ define void @test4() gc "statepoint-example" {
define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" {
; CHECK-LABEL: test5
entry:
call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0)
switch i32 undef, label %kill [
i32 10, label %merge
i32 13, label %merge
@ -169,7 +169,7 @@ do_safepoint:
; CHECK: arg1.relocated =
; CHECK: arg2.relocated =
; CHECK: arg3.relocated =
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3)
br label %gc.safepoint_poll.exit2
gc.safepoint_poll.exit2:
@ -208,7 +208,7 @@ outer-inc:
; CHECK-LABEL: outer-inc:
; CHECK: %arg1.relocated
; CHECK: %arg2.relocated
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
br label %outer-loop
}
@ -237,7 +237,7 @@ inner-loop:
; CHECK: gc.statepoint
; CHECK: %arg1.relocated
; CHECK: %arg2.relocated
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2)
br i1 %cmp, label %inner-loop, label %outer-inc
outer-inc:
@ -257,7 +257,7 @@ branch2:
br i1 %condition, label %callbb, label %join2
callbb:
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0)
br label %join
join:

View File

@ -12,8 +12,8 @@ declare i32 @"personality_function"()
define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg, i32 %val) gc "statepoint-example" {
entry:
%cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
ret i64 addrspace(1)* %reloc
}

View File

@ -10,11 +10,11 @@ declare i32 @"personality_function"()
define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" {
entry:
%cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
;; It is perfectly legal to relocate the same value multiple times...
%reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
%reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 10, i32 9)
%reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
%reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 11, i32 10)
ret i64 addrspace(1)* %reloc
; CHECK-LABEL: test1
; CHECK: statepoint
@ -39,8 +39,8 @@ notequal:
ret void
equal:
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
%safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg)
%reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
call void undef(i64 addrspace(1)* %reloc)
ret void
; CHECK-LABEL: test2
@ -57,7 +57,7 @@ define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc
entry:
; CHECK-LABEL: entry
; CHECK: statepoint
%0 = invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1)
%0 = invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1)
to label %normal_dest unwind label %exceptional_return
normal_dest:
@ -65,7 +65,7 @@ normal_dest:
; CHECK: gc.relocate
; CHECK: gc.relocate
; CHECK: ret
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
%obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10)
%obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10)
ret i8 addrspace(1)* %obj.relocated
@ -76,7 +76,7 @@ exceptional_return:
%landing_pad = landingpad { i8*, i32 } personality i32 ()* @"personality_function"
cleanup
%relocate_token = extractvalue { i8*, i32 } %landing_pad, 1
%obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 9, i32 9)
%obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10)
%obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10)
ret i8 addrspace(1)* %obj1.relocated1
}