llvm.org GIT mirror llvm / 5c7f746
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236888 91177308-0d34-0410-b5e6-96231b3b80d8 Pat Gavlin 4 years ago
43 changed file(s) with 617 addition(s) and 181 deletion(s). Raw diff Collapse all Expand all
141141
142142 define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
143143 gc "statepoint-example" {
144 %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)
145 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
144 %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj)
145 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4)
146146 ret i8 addrspace(1)* %obj.relocated
147147 }
148148
206206 opt -rewrite-statepoints-for-gc test/Transforms/RewriteStatepointsForGC/basics.ll -S | llc -debug-only=stackmaps
207207
208208
209
209 GC Transitions
210 ^^^^^^^^^^^^^^^^^^
211
212 As a practical consideration, many garbage-collected systems allow code that is
213 collector-aware ("managed code") to call code that is not collector-aware
214 ("unmanaged code"). It is common that such calls must also be safepoints, since
215 it is desirable to allow the collector to run during the execution of
216 unmanaged code. Futhermore, it is common that coordinating the transition from
217 managed to unmanaged code requires extra code generation at the call site to
218 inform the collector of the transition. In order to support these needs, a
219 statepoint may be marked as a GC transition, and data that is necessary to
220 perform the transition (if any) may be provided as additional arguments to the
221 statepoint.
222
223 Note that although in many cases statepoints may be inferred to be GC
224 transitions based on the function symbols involved (e.g. a call from a
225 function with GC strategy "foo" to a function with GC strategy "bar"),
226 indirect calls that are also GC transitions must also be supported. This
227 requirement is the driving force behing the decision to require that GC
228 transitions are explicitly marked.
229
230 Let's revisit the sample given above, this time treating the call to ``@foo``
231 as a GC transition. Depending on our target, the transition code may need to
232 access some extra state in order to inform the collector of the transition.
233 Let's assume a hypothetical GC--somewhat unimaginatively named "hypothetical-gc"
234 --that requires that a TLS variable must be written to before and after a call
235 to unmanaged code. The resulting relocation sequence is:
236
237 .. code-block:: llvm
238
239 @flag = thread_local global i32 0, align 4
240
241 define i8 addrspace(1)* @test1(i8 addrspace(1) *%obj)
242 gc "hypothetical-gc" {
243
244 %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)
245 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4)
246 ret i8 addrspace(1)* %obj.relocated
247 }
248
249 During lowering, this will result in a instruction selection DAG that looks
250 something like:
251
252 .. code-block::
253
254 CALLSEQ_START
255 ...
256 GC_TRANSITION_START (lowered i32 *@Flag), SRCVALUE i32* Flag
257 STATEPOINT
258 GC_TRANSITION_END (lowered i32 *@Flag), SRCVALUE i32 *Flag
259 ...
260 CALLSEQ_END
261
262 In order to generate the necessary transition code, the backend for each target
263 supported by "hypothetical-gc" must be modified to lower ``GC_TRANSITION_START``
264 and ``GC_TRANSITION_END`` nodes appropriately when the "hypothetical-gc"
265 strategy is in use for a particular function. Assuming that such lowering has
266 been added for X86, the generated assembly would be:
267
268 .. code-block:: gas
269
270 .globl test1
271 .align 16, 0x90
272 pushq %rax
273 movl $1, %fs:Flag@TPOFF
274 callq foo
275 movl $0, %fs:Flag@TPOFF
276 .Ltmp1:
277 movq (%rsp), %rax # This load is redundant (oops!)
278 popq %rdx
279 retq
280
281 Note that the design as presented above is not fully implemented: in particular,
282 strategy-specific lowering is not present, and all GC transitions are emitted as
283 as single no-op before and after the call instruction. These no-ops are often
284 removed by the backend during dead machine instruction elimination.
210285
211286
212287 Intrinsics
222297
223298 declare i32
224299 @llvm.experimental.gc.statepoint(func_type ,
225 i64 <#call args>. i64 <unused>,
300 i64 <#call args>. i64 <flags>,
226301 ... (call parameters),
302 i64 <# transition args>, ... (transition parameters),
227303 i64 <# deopt args>, ... (deopt parameters),
228304 ... (gc parameters))
229305
246322 call. It must exactly match the number of arguments passed in the
247323 'call parameters' variable length section.
248324
249 The 'unused' operand is unused and likely to be removed. Please do
250 not use.
325 The 'flags' operand is used to specify extra information about the
326 statepoint. This is currently only used to mark certain statepoints
327 as GC transitions. This operand is a 64-bit integer with the following
328 layout, where bit 0 is the least significant bit:
329
330 +-------+---------------------------------------------------+
331 | Bit # | Usage |
332 +=======+===================================================+
333 | 0 | Set if the statepoint is a GC transition, cleared |
334 | | otherwise. |
335 +-------+---------------------------------------------------+
336 | 1-63 | Reserved for future use; must be cleared. |
337 +-------+---------------------------------------------------+
251338
252339 The 'call parameters' arguments are simply the arguments which need to
253340 be passed to the call target. They will be lowered according to the
255342 instruction. The number of arguments must exactly match what is
256343 specified in '# call args'. The types must match the signature of
257344 'target'.
345
346 The 'transition parameters' arguments contain an arbitrary list of
347 Values which need to be passed to GC transition code. They will be
348 lowered and passed as operands to the appropriate GC_TRANSITION nodes
349 in the selection DAG. It is assumed that these arguments must be
350 available before and after (but not necessarily during) the execution
351 of the callee. The '# transition args' field indicates how many operands
352 are to be interpreted as 'transition parameters'.
258353
259354 The 'deopt parameters' arguments contain an arbitrary list of Values
260355 which is meaningful to the runtime. The runtime may read any of these
470565
471566 define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
472567 gc "statepoint-example" {
473 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)
568 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)
474569 ret i8 addrspace(1)* %obj
475570 }
476571
480575
481576 define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj)
482577 gc "statepoint-example" {
483 %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)
578 %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)
484579 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
485580 ret i8 addrspace(1)* %obj.relocated
486581 }
534629 .. code-block:: llvm
535630
536631 define void @test() gc "statepoint-example" {
537 %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
538 %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
632 %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
633 %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
539634 ret void
540635 }
541636
699699 /// This corresponds to the llvm.lifetime.* intrinsics. The first operand
700700 /// is the chain and the second operand is the alloca pointer.
701701 LIFETIME_START, LIFETIME_END,
702
703 /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the
704 /// beginning and end of GC transition sequence, and carry arbitrary
705 /// information that target might need for lowering. The first operand is
706 /// a chain, the rest are specified by the target and not touched by the DAG
707 /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be
708 /// nested.
709 GC_TRANSITION_START,
710 GC_TRANSITION_END,
702711
703712 /// BUILTIN_OP_END - This must be the last enum value in this list.
704713 /// The target-specific pre-isel opcode values start here.
2323 #include "llvm/Support/Compiler.h"
2424
2525 namespace llvm {
26 /// The statepoint intrinsic accepts a set of flags as its third argument.
27 /// Valid values come out of this set.
28 enum class StatepointFlags {
29 None = 0,
30 GCTransition = 1, ///< Indicates that this statepoint is a transition from
31 ///< GC-aware code to code that is not GC-aware.
32
33 MaskAll = GCTransition ///< A bitmask that includes all valid flags.
34 };
2635
2736 class GCRelocateOperands;
2837 class ImmutableStatepoint;
7180 /// Return the underlying CallSite.
7281 CallSiteTy getCallSite() { return StatepointCS; }
7382
83 uint64_t getFlags() const {
84 return cast(StatepointCS.getArgument(2))->getZExtValue();
85 }
86
7487 /// Return the value actually being called or invoked.
7588 ValueTy *getActualCallee() {
7689 return StatepointCS.getArgument(ActualCalleePos);
105118 return iterator_range(call_args_begin(), call_args_end());
106119 }
107120
121 /// Number of GC transition args.
122 int getNumTotalGCTransitionArgs() {
123 const Value *NumGCTransitionArgs = *gc_transition_args_begin();
124 return cast(NumGCTransitionArgs)->getZExtValue();
125 }
126 typename CallSiteTy::arg_iterator gc_transition_args_begin() {
127 int Offset = call_args_end() - StatepointCS.arg_begin();
128 assert(Offset <= (int)StatepointCS.arg_size());
129 return StatepointCS.arg_begin() + Offset;
130 }
131 typename CallSiteTy::arg_iterator gc_transition_args_end() {
132 int Offset = (gc_transition_args_begin() + 1 +
133 getNumTotalGCTransitionArgs()) - StatepointCS.arg_begin();
134 assert(Offset <= (int)StatepointCS.arg_size());
135 return StatepointCS.arg_begin() + Offset;
136 }
137
138 /// range adapter for GC transition arguments
139 iterator_range gc_transition_args() {
140 return iterator_range(gc_transition_args_begin(),
141 gc_transition_args_end());
142 }
143
108144 /// Number of additional arguments excluding those intended
109145 /// for garbage collection.
110146 int getNumTotalVMSArgs() {
111 Value *NumVMSArgs = *call_args_end();
147 Value *NumVMSArgs = *vm_state_begin();
112148 return cast(NumVMSArgs)->getZExtValue();
113149 }
114150
115 typename CallSiteTy::arg_iterator vm_state_begin() { return call_args_end(); }
151 typename CallSiteTy::arg_iterator vm_state_begin() {
152 return gc_transition_args_end();
153 }
116154 typename CallSiteTy::arg_iterator vm_state_end() {
117 int Offset = CallArgsBeginPos + getNumCallArgs() + 1 + getNumTotalVMSArgs();
155 int Offset = (gc_transition_args_end() + 1 + getNumTotalVMSArgs()) -
156 StatepointCS.arg_begin();
118157 assert(Offset <= (int)StatepointCS.arg_size());
119158 return StatepointCS.arg_begin() + Offset;
120159 }
151190 // The internal asserts in the iterator accessors do the rest.
152191 (void)call_args_begin();
153192 (void)call_args_end();
193 (void)gc_transition_args_begin();
194 (void)gc_transition_args_end();
154195 (void)vm_state_begin();
155196 (void)vm_state_end();
156197 (void)gc_args_begin();
287287 case ISD::DEBUGTRAP: return "debugtrap";
288288 case ISD::LIFETIME_START: return "lifetime.start";
289289 case ISD::LIFETIME_END: return "lifetime.end";
290 case ISD::GC_TRANSITION_START: return "gc_transition.start";
291 case ISD::GC_TRANSITION_END: return "gc_transition.end";
290292
291293 // Bit manipulation
292294 case ISD::BSWAP: return "bswap";
584584 SDNode *CallNode =
585585 lowerCallFromStatepoint(ISP, LandingPad, *this, PendingExports);
586586
587 // Construct the actual STATEPOINT node with all the appropriate arguments
588 // and return values.
587 // Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END
588 // nodes with all the appropriate arguments and return values.
589589
590590 // TODO: Currently, all of these operands are being marked as read/write in
591591 // PrologEpilougeInserter.cpp, we should special case the VMState arguments
592592 // and flags to be read-only.
593593 SmallVector Ops;
594594
595 // Calculate and push starting position of vmstate arguments
596595 // Call Node: Chain, Target, {Args}, RegMask, [Glue]
596 SDValue Chain = CallNode->getOperand(0);
597
597598 SDValue Glue;
598 if (CallNode->getGluedNode()) {
599 bool CallHasIncomingGlue = CallNode->getGluedNode();
600 if (CallHasIncomingGlue) {
599601 // Glue is always last operand
600602 Glue = CallNode->getOperand(CallNode->getNumOperands() - 1);
601603 }
604
605 // Build the GC_TRANSITION_START node if necessary.
606 //
607 // The operands to the GC_TRANSITION_{START,END} nodes are laid out in the
608 // order in which they appear in the call to the statepoint intrinsic. If
609 // any of the operands is a pointer-typed, that operand is immediately
610 // followed by a SRCVALUE for the pointer that may be used during lowering
611 // (e.g. to form MachinePointerInfo values for loads/stores).
612 const bool IsGCTransition =
613 (ISP.getFlags() & (uint64_t)StatepointFlags::GCTransition) ==
614 (uint64_t)StatepointFlags::GCTransition;
615 if (IsGCTransition) {
616 SmallVector TSOps;
617
618 // Add chain
619 TSOps.push_back(Chain);
620
621 // Add GC transition arguments
622 for (auto I = ISP.gc_transition_args_begin() + 1,
623 E = ISP.gc_transition_args_end();
624 I != E; ++I) {
625 TSOps.push_back(getValue(*I));
626 if ((*I)->getType()->isPointerTy())
627 TSOps.push_back(DAG.getSrcValue(*I));
628 }
629
630 // Add glue if necessary
631 if (CallHasIncomingGlue)
632 TSOps.push_back(Glue);
633
634 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
635
636 SDValue GCTransitionStart =
637 DAG.getNode(ISD::GC_TRANSITION_START, getCurSDLoc(), NodeTys, TSOps);
638
639 Chain = GCTransitionStart.getValue(0);
640 Glue = GCTransitionStart.getValue(1);
641 }
642
643 // Calculate and push starting position of vmstate arguments
602644 // Get number of arguments incoming directly into call node
603645 unsigned NumCallRegArgs =
604 CallNode->getNumOperands() - (Glue.getNode() ? 4 : 3);
646 CallNode->getNumOperands() - (CallHasIncomingGlue ? 4 : 3);
605647 Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, getCurSDLoc(), MVT::i32));
606648
607649 // Add call target
611653 // Add call arguments
612654 // Get position of register mask in the call
613655 SDNode::op_iterator RegMaskIt;
614 if (Glue.getNode())
656 if (CallHasIncomingGlue)
615657 RegMaskIt = CallNode->op_end() - 2;
616658 else
617659 RegMaskIt = CallNode->op_end() - 1;
620662 // Add a leading constant argument with the Flags and the calling convention
621663 // masked together
622664 CallingConv::ID CallConv = CS.getCallingConv();
623 int Flags = cast(CS.getArgument(2))->getZExtValue();
624 assert(Flags == 0 && "not expected to be used");
665 uint64_t Flags = cast(CS.getArgument(2))->getZExtValue();
666 assert(
667 ((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0)
668 && "unknown flag used");
669 const int Shift = 1;
670 static_assert(
671 ((~(uint64_t)0 << Shift) & (uint64_t)StatepointFlags::MaskAll) == 0,
672 "shift width too small");
625673 Ops.push_back(DAG.getTargetConstant(StackMaps::ConstantOp, getCurSDLoc(),
626674 MVT::i64));
627 Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << 1),
675 Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << Shift),
628676 getCurSDLoc(), MVT::i64));
629677
630678 // Insert all vmstate and gcstate arguments
634682 Ops.push_back(*RegMaskIt);
635683
636684 // Add chain
637 Ops.push_back(CallNode->getOperand(0));
685 Ops.push_back(Chain);
638686
639687 // Same for the glue, but we add it only if original call had it
640688 if (Glue.getNode())
647695 SDNode *StatepointMCNode =
648696 DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops);
649697
698 SDNode *SinkNode = StatepointMCNode;
699
700 // Build the GC_TRANSITION_END node if necessary.
701 //
702 // See the comment above regarding GC_TRANSITION_START for the layout of
703 // the operands to the GC_TRANSITION_END node.
704 if (IsGCTransition) {
705 SmallVector TEOps;
706
707 // Add chain
708 TEOps.push_back(SDValue(StatepointMCNode, 0));
709
710 // Add GC transition arguments
711 for (auto I = ISP.gc_transition_args_begin() + 1,
712 E = ISP.gc_transition_args_end();
713 I != E; ++I) {
714 TEOps.push_back(getValue(*I));
715 if ((*I)->getType()->isPointerTy())
716 TEOps.push_back(DAG.getSrcValue(*I));
717 }
718
719 // Add glue
720 TEOps.push_back(SDValue(StatepointMCNode, 1));
721
722 SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
723
724 SDValue GCTransitionStart =
725 DAG.getNode(ISD::GC_TRANSITION_END, getCurSDLoc(), NodeTys, TEOps);
726
727 SinkNode = GCTransitionStart.getNode();
728 }
729
650730 // Replace original call
651 DAG.ReplaceAllUsesWith(CallNode, StatepointMCNode); // This may update Root
731 DAG.ReplaceAllUsesWith(CallNode, SinkNode); // This may update Root
652732 // Remove originall call node
653733 DAG.DeleteNode(CallNode);
654734
1616 #include "llvm/IR/IRBuilder.h"
1717 #include "llvm/IR/Intrinsics.h"
1818 #include "llvm/IR/LLVMContext.h"
19 #include "llvm/IR/Statepoint.h"
1920 using namespace llvm;
2021
2122 /// CreateGlobalString - Make a new global variable with an initializer that
251252 std::vector Args;
252253 Args.push_back(ActualCallee);
253254 Args.push_back(B.getInt32(CallArgs.size()));
254 Args.push_back(B.getInt32(0)); // unused
255 Args.push_back(B.getInt32((unsigned)StatepointFlags::None));
255256 Args.insert(Args.end(), CallArgs.begin(), CallArgs.end());
257 Args.push_back(B.getInt32(0 /* no transition args */));
256258 Args.push_back(B.getInt32(DeoptArgs.size()));
257259 Args.insert(Args.end(), DeoptArgs.begin(), DeoptArgs.end());
258260 Args.insert(Args.end(), GCArgs.begin(), GCArgs.end());
15281528 Assert(NumCallArgs == NumParams,
15291529 "gc.statepoint mismatch in number of call args", &CI);
15301530
1531 const Value *Unused = CS.getArgument(2);
1532 Assert(isa(Unused) && cast(Unused)->isNullValue(),
1533 "gc.statepoint parameter #3 must be zero", &CI);
1531 const Value *FlagsV = CS.getArgument(2);
1532 Assert(isa(FlagsV),
1533 "gc.statepoint flags must be constant integer", &CI);
1534 const uint64_t Flags = cast(FlagsV)->getZExtValue();
1535 Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0,
1536 "unknown flag used in gc.statepoint flags argument", &CI);
15341537
15351538 // Verify that the types of the call parameter arguments match
15361539 // the type of the wrapped callee.
15431546 &CI);
15441547 }
15451548 const int EndCallArgsInx = 2+NumCallArgs;
1546 const Value *NumDeoptArgsV = CS.getArgument(EndCallArgsInx+1);
1549
1550 const Value *NumTransitionArgsV = CS.getArgument(EndCallArgsInx+1);
1551 Assert(isa(NumTransitionArgsV),
1552 "gc.statepoint number of transition arguments "
1553 "must be constant integer",
1554 &CI);
1555 const int NumTransitionArgs =
1556 cast(NumTransitionArgsV)->getZExtValue();
1557 Assert(NumTransitionArgs >= 0,
1558 "gc.statepoint number of transition arguments must be positive", &CI);
1559 const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs;
1560
1561 const Value *NumDeoptArgsV = CS.getArgument(EndTransitionArgsInx+1);
15471562 Assert(isa(NumDeoptArgsV),
15481563 "gc.statepoint number of deoptimization arguments "
15491564 "must be constant integer",
15531568 "must be positive",
15541569 &CI);
15551570
1556 Assert(4 + NumCallArgs + NumDeoptArgs <= (int)CS.arg_size(),
1571 const int ExpectedNumArgs =
1572 5 + NumCallArgs + NumTransitionArgs + NumDeoptArgs;
1573 Assert(ExpectedNumArgs <= (int)CS.arg_size(),
15571574 "gc.statepoint too few arguments according to length fields", &CI);
15581575
15591576 // Check that the only uses of this gc.statepoint are gc.result or
33453362 Assert(StatepointCS.arg_size() > NumCallArgs+3,
33463363 "gc.statepoint: mismatch in number of call arguments");
33473364 Assert(isa(StatepointCS.getArgument(NumCallArgs+3)),
3365 "gc.statepoint: number of transition arguments must be "
3366 "a constant integer");
3367 const int NumTransitionArgs =
3368 cast(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
3369 const int DeoptArgsStart = 2 + NumCallArgs + 1 + NumTransitionArgs + 1;
3370 Assert(isa(StatepointCS.getArgument(DeoptArgsStart)),
33483371 "gc.statepoint: number of deoptimization arguments must be "
33493372 "a constant integer");
33503373 const int NumDeoptArgs =
3351 cast(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue();
3352 const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4;
3374 cast(StatepointCS.getArgument(DeoptArgsStart))->getZExtValue();
3375 const int GCParamArgsStart = DeoptArgsStart + 1 + NumDeoptArgs;
33533376 const int GCParamArgsEnd = StatepointCS.arg_size();
33543377 Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd,
33553378 "gc.relocate: statepoint base index doesn't fall within the "
511511 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
512512
513513 setOperationAction(ISD::DYNAMIC_STACKALLOC, getPointerTy(), Custom);
514
515 // GC_TRANSITION_START and GC_TRANSITION_END need custom lowering.
516 setOperationAction(ISD::GC_TRANSITION_START, MVT::Other, Custom);
517 setOperationAction(ISD::GC_TRANSITION_END, MVT::Other, Custom);
514518
515519 if (!TM.Options.UseSoftFloat && X86ScalarSSEf64) {
516520 // f32 and f64 use SSE.
1742217426 DAG.UpdateNodeOperands(N, Ops);
1742317427 }
1742417428 return Op;
17429 }
17430
17431 SDValue X86TargetLowering::LowerGC_TRANSITION_START(SDValue Op,
17432 SelectionDAG &DAG) const {
17433 // TODO: Eventually, the lowering of these nodes should be informed by or
17434 // deferred to the GC strategy for the function in which they appear. For
17435 // now, however, they must be lowered to something. Since they are logically
17436 // no-ops in the case of a null GC strategy (or a GC strategy which does not
17437 // require special handling for these nodes), lower them as literal NOOPs for
17438 // the time being.
17439 SmallVector Ops;
17440
17441 Ops.push_back(Op.getOperand(0));
17442 if (Op->getGluedNode())
17443 Ops.push_back(Op->getOperand(Op->getNumOperands() - 1));
17444
17445 SDLoc OpDL(Op);
17446 SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue);
17447 SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0);
17448
17449 return NOOP;
17450 }
17451
17452 SDValue X86TargetLowering::LowerGC_TRANSITION_END(SDValue Op,
17453 SelectionDAG &DAG) const {
17454 // TODO: Eventually, the lowering of these nodes should be informed by or
17455 // deferred to the GC strategy for the function in which they appear. For
17456 // now, however, they must be lowered to something. Since they are logically
17457 // no-ops in the case of a null GC strategy (or a GC strategy which does not
17458 // require special handling for these nodes), lower them as literal NOOPs for
17459 // the time being.
17460 SmallVector Ops;
17461
17462 Ops.push_back(Op.getOperand(0));
17463 if (Op->getGluedNode())
17464 Ops.push_back(Op->getOperand(Op->getNumOperands() - 1));
17465
17466 SDLoc OpDL(Op);
17467 SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue);
17468 SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0);
17469
17470 return NOOP;
1742517471 }
1742617472
1742717473 /// LowerOperation - Provide custom lowering hooks for some operations.
1751317559 case ISD::FSINCOS: return LowerFSINCOS(Op, Subtarget, DAG);
1751417560 case ISD::MGATHER: return LowerMGATHER(Op, Subtarget, DAG);
1751517561 case ISD::MSCATTER: return LowerMSCATTER(Op, Subtarget, DAG);
17562 case ISD::GC_TRANSITION_START:
17563 return LowerGC_TRANSITION_START(Op, DAG);
17564 case ISD::GC_TRANSITION_END: return LowerGC_TRANSITION_END(Op, DAG);
1751617565 }
1751717566 }
1751817567
968968 SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const;
969969 SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const;
970970 SDValue LowerWin64_i128OP(SDValue Op, SelectionDAG &DAG) const;
971 SDValue LowerGC_TRANSITION_START(SDValue Op, SelectionDAG &DAG) const;
972 SDValue LowerGC_TRANSITION_END(SDValue Op, SelectionDAG &DAG) const;
971973
972974 SDValue
973975 LowerFormalArguments(SDValue Chain,
2121 %alloca = alloca i1
2222 %load2 = load i1, i1* %alloca
2323 %load3 = load i32, i32 addrspace(1)* %dparam
24 %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)
25 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4)
24 %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)
25 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5)
2626 %load4 = load i32, i32 addrspace(1)* %relocate
2727 %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5
2828 %load5 = load i32, i32 addrspace(1)* %nparam
1212
1313 ; function and integer
1414 define i32* @test_iAny(i32* %v) gc "statepoint-example" {
15 %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %v)
16 %v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
15 %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)
16 %v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
1717 ret i32* %v-new
1818 }
1919
2020 ; float
2121 define float* @test_fAny(float* %v) gc "statepoint-example" {
22 %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, float* %v)
23 %v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 4, i32 4)
22 %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)
23 %v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 5, i32 5)
2424 ret float* %v-new
2525 }
2626
2727 ; array of integers
2828 define [3 x i32]* @test_aAny([3 x i32]* %v) gc "statepoint-example" {
29 %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)
30 %v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
29 %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)
30 %v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
3131 ret [3 x i32]* %v-new
3232 }
3333
3434 ; vector of integers
3535 define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" {
36 %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)
37 %v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 4, i32 4)
36 %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)
37 %v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 5, i32 5)
3838 ret <3 x i32>* %v-new
3939 }
4040
4242
4343 ; struct
4444 define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" {
45 %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, %struct.test* %v)
46 %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 4, i32 4)
45 %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)
46 %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 5, i32 5)
4747 ret %struct.test* %v-new
4848 }
4949
2020 entry:
2121 %alloca = alloca i32 addrspace(1)*, align 8
2222 store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
23 call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca)
23 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)
2424 %rel = load i32 addrspace(1)*, i32 addrspace(1)** %alloca
2525 ret i32 addrspace(1)* %rel
2626 }
3737 entry:
3838 %alloca = alloca i32 addrspace(1)*, align 8
3939 store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca
40 call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca)
40 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)
4141 ret i32 addrspace(1)* null
4242 }
4343
1919 ; CHECK: popq %rdx
2020 ; CHECK: retq
2121 entry:
22 %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0)
22 %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)
2323 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
2424 ret i1 %call1
2525 }
3131 ; CHECK: popq %rdx
3232 ; CHECK: retq
3333 entry:
34 %safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0)
34 %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)
3535 %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
3636 ret i32 %call1
3737 }
4343 ; CHECK: popq %rdx
4444 ; CHECK: retq
4545 entry:
46 %safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0)
46 %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)
4747 %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
4848 ret i32* %call1
4949 }
5555 ; CHECK: popq %rax
5656 ; CHECK: retq
5757 entry:
58 %safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0)
58 %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)
5959 %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
6060 ret float %call1
6161 }
6969 ; CHECK-NEXT: popq %rdx
7070 ; CHECK-NEXT: retq
7171 entry:
72 %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)
73 %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
72 %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)
73 %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
7474 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
7575 ret i1 %call2
7676 }
8080 ; Check a statepoint wrapping a *void* returning vararg function works
8181 ; CHECK: callq varargf
8282 entry:
83 %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)
83 %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)
8484 ;; if we try to use the result from a statepoint wrapping a
8585 ;; non-void-returning varargf, we will experience a crash.
8686 ret void
2424 %before = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p
2525 %cmp1 = call i1 @f(i32 addrspace(1)* %before)
2626 call void @llvm.assume(i1 %cmp1)
27 %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)
28 %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4)
27 %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)
28 %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5)
2929 %after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew
3030 %cmp2 = call i1 @f(i32 addrspace(1)* %after)
3131 ret i1 %cmp2
4343 %cmp1 = call i1 @f(i32 addrspace(1)* %v)
4444 call void @llvm.assume(i1 %cmp1)
4545 store i32 addrspace(1)* %v, i32 addrspace(1)* addrspace(1)* %p
46 %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)
47 %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4)
46 %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)
47 %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5)
4848 %after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew
4949 %cmp2 = call i1 @f(i32 addrspace(1)* %after)
5050 ret i1 %cmp2
7171 %before = load i32 addrspace(1)*, i32 addrspace(1)** %p
7272 %cmp1 = call i1 @f(i32 addrspace(1)* %before)
7373 call void @llvm.assume(i1 %cmp1)
74 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0)
74 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0)
7575 %after = load i32 addrspace(1)*, i32 addrspace(1)** %p
7676 %cmp2 = call i1 @f(i32 addrspace(1)* %after)
7777 ret i1 %cmp2
8989 %cmp1 = call i1 @f(i32 addrspace(1)* %v)
9090 call void @llvm.assume(i1 %cmp1)
9191 store i32 addrspace(1)* %v, i32 addrspace(1)** %p
92 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0)
92 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0)
9393 %after = load i32 addrspace(1)*, i32 addrspace(1)** %p
9494 %cmp2 = call i1 @f(i32 addrspace(1)* %after)
9595 ret i1 %cmp2
0 ; RUN: llc < %s | FileCheck %s
1 ; This file contains a collection of basic tests to ensure we didn't
2 ; screw up normal call lowering when a statepoint is a GC transition.
3
4 target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128"
5 target triple = "x86_64-pc-linux-gnu"
6
7 declare zeroext i1 @return_i1()
8 declare zeroext i32 @return_i32()
9 declare zeroext i32 @return_i32_with_args(i32, i8*)
10 declare i32* @return_i32ptr()
11 declare float @return_float()
12 declare void @varargf(i32, ...)
13
14 define i1 @test_i1_return() gc "statepoint-example" {
15 ; CHECK-LABEL: test_i1_return
16 ; This is just checking that a i1 gets lowered normally when there's no extra
17 ; state arguments to the statepoint
18 ; CHECK: pushq %rax
19 ; CHECK: callq return_i1
20 ; CHECK: popq %rdx
21 ; CHECK: retq
22 entry:
23 %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)
24 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
25 ret i1 %call1
26 }
27
28 define i32 @test_i32_return() gc "statepoint-example" {
29 ; CHECK-LABEL: test_i32_return
30 ; CHECK: pushq %rax
31 ; CHECK: callq return_i32
32 ; CHECK: popq %rdx
33 ; CHECK: retq
34 entry:
35 %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)
36 %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
37 ret i32 %call1
38 }
39
40 define i32* @test_i32ptr_return() gc "statepoint-example" {
41 ; CHECK-LABEL: test_i32ptr_return
42 ; CHECK: pushq %rax
43 ; CHECK: callq return_i32ptr
44 ; CHECK: popq %rdx
45 ; CHECK: retq
46 entry:
47 %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)
48 %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token)
49 ret i32* %call1
50 }
51
52 define float @test_float_return() gc "statepoint-example" {
53 ; CHECK-LABEL: test_float_return
54 ; CHECK: pushq %rax
55 ; CHECK: callq return_float
56 ; CHECK: popq %rax
57 ; CHECK: retq
58 entry:
59 %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)
60 %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token)
61 ret float %call1
62 }
63
64 define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" {
65 ; CHECK-LABEL: test_relocate
66 ; Check that an ununsed relocate has no code-generation impact
67 ; CHECK: pushq %rax
68 ; CHECK: callq return_i1
69 ; CHECK-NEXT: .Ltmp9:
70 ; CHECK-NEXT: popq %rdx
71 ; CHECK-NEXT: retq
72 entry:
73 %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)
74 %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
75 %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
76 ret i1 %call2
77 }
78
79 define void @test_void_vararg() gc "statepoint-example" {
80 ; CHECK-LABEL: test_void_vararg
81 ; Check a statepoint wrapping a *void* returning vararg function works
82 ; CHECK: callq varargf
83 entry:
84 %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)
85 ;; if we try to use the result from a statepoint wrapping a
86 ;; non-void-returning varargf, we will experience a crash.
87 ret void
88 }
89
90 define i32 @test_transition_args() gc "statepoint-example" {
91 ; CHECK-LABEL: test_transition_args
92 ; CHECK: pushq %rax
93 ; CHECK: callq return_i32
94 ; CHECK: popq %rdx
95 ; CHECK: retq
96 entry:
97 %val = alloca i32
98 %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)
99 %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
100 ret i32 %call1
101 }
102
103 define i32 @test_transition_args_2() gc "statepoint-example" {
104 ; CHECK-LABEL: test_transition_args_2
105 ; CHECK: pushq %rax
106 ; CHECK: callq return_i32
107 ; CHECK: popq %rdx
108 ; CHECK: retq
109 entry:
110 %val = alloca i32
111 %arg = alloca i8
112 %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)
113 %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token)
114 ret i32 %call1
115 }
116
117 declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...)
118 declare i1 @llvm.experimental.gc.result.i1(i32)
119
120 declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()*, i32, i32, ...)
121 declare i32 @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i32 (i32, i8*)*, i32, i32, ...)
122 declare i32 @llvm.experimental.gc.result.i32(i32)
123
124 declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...)
125 declare i32* @llvm.experimental.gc.result.p0i32(i32)
126
127 declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...)
128 declare float @llvm.experimental.gc.result.f32(i32)
129
130 declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...)
131
132 declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32)
1212 ; CHECK: .Ltmp{{[0-9]+}}:
1313 ; CHECK: callq some_other_call
1414 ; CHECK: .Ltmp{{[0-9]+}}:
15 %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)
15 %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)
1616 to label %normal_return unwind label %exceptional_return
1717
1818 normal_return:
1313 ; CHECK: movq %rdx, 16(%rsp)
1414 ; CHECK: movq %rdi, 8(%rsp)
1515 ; CHECK: movq %rsi, (%rsp)
16 %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)
17 %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9)
18 %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10)
19 %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11)
16 %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)
17 %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10)
18 %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11)
19 %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12)
2020 ; CHECK: callq
2121 ; This is the key check. There should NOT be any memory moves here
2222 ; CHECK-NOT: movq
23 %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)
24 %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11)
25 %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10)
26 %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9)
23 %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)
24 %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12)
25 %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11)
26 %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10)
2727 ; CHECK: callq
2828 ret i32 1
2929 }
3636 ; CHECK: movq %rdx, 16(%rsp)
3737 ; CHECK: movq %rdi, 8(%rsp)
3838 ; CHECK: movq %rsi, (%rsp)
39 %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)
40 %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9)
41 %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10)
42 %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11)
39 %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)
40 %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10)
41 %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11)
42 %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12)
4343 ; CHECK: callq
4444 ; This is the key check. There should NOT be any memory moves here
4545 ; CHECK-NOT: movq
46 %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)
47 %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11)
48 %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10)
49 %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9)
46 %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)
47 %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12)
48 %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11)
49 %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10)
5050 ; CHECK: callq
5151 ret i32 1
5252 }
2020 entry:
2121 %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8
2222 store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1
23 %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)
23 %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)
2424 %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token)
25 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6)
26 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
25 %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7)
26 %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 8, i32 8)
2727 ;
2828 ret i1 %call1
2929 }
99 ; CHECK: getelementptr i32, i32* %base-new, i32 15
1010 entry:
1111 %ptr = getelementptr i32, i32* %base, i32 15
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)
13 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
14 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
12 %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)
13 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
14 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
1515 %ret = load i32, i32* %ptr-new
1616 ret i32 %ret
1717 }
1919 define i32 @test_sor_two_derived(i32* %base) gc "statepoint-example" {
2020 ; CHECK: getelementptr i32, i32* %base, i32 15
2121 ; CHECK: getelementptr i32, i32* %base, i32 12
22 ; CHECK: getelementptr i32, i32* %base-new, i32 12
2223 ; CHECK: getelementptr i32, i32* %base-new, i32 15
23 ; CHECK: getelementptr i32, i32* %base-new, i32 12
2424 entry:
2525 %ptr = getelementptr i32, i32* %base, i32 15
2626 %ptr2 = getelementptr i32, i32* %base, i32 12
27 %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)
28 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
29 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
30 %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
27 %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)
28 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
29 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
30 %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
3131 %ret = load i32, i32* %ptr-new
3232 ret i32 %ret
3333 }
3737 ; CHECK: getelementptr i32, i32* %base-new, i32 15
3838 entry:
3939 %ptr = getelementptr i32, i32* %base, i32 15
40 %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)
41 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
42 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4)
40 %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)
41 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
42 %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5)
4343 %ret = load i32, i32* %ptr-new
4444 ret i32 %ret
4545 }
4949 ; CHECK: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 2
5050 entry:
5151 %ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 2
52 %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)
53 %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
54 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
52 %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)
53 %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
54 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
5555 %ret = load i32, i32* %ptr-new
5656 ret i32 %ret
5757 }
6161 ; CHECK-NOT: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 21
6262 entry:
6363 %ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 21
64 %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)
65 %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4)
66 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
64 %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)
65 %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5)
66 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
6767 %ret = load i32, i32* %ptr-new
6868 ret i32 %ret
6969 }
7070
7171 define i32 @test_sor_noop(i32* %base) gc "statepoint-example" {
7272 ; CHECK: getelementptr i32, i32* %base, i32 15
73 ; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
74 ; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
73 ; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
74 ; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
7575 entry:
7676 %ptr = getelementptr i32, i32* %base, i32 15
7777 %ptr2 = getelementptr i32, i32* %base, i32 12
78 %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)
79 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5)
80 %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6)
78 %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)
79 %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6)
80 %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7)
8181 %ret = load i32, i32* %ptr-new
8282 ret i32 %ret
8383 }
1414 ; CHECK: call dereferenceable(8)
1515 entry:
1616 %load = load i32, i32 addrspace(1)* %dparam
17 %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)
18 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4)
17 %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)
18 %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5)
1919 ret i32 addrspace(1)* %relocate
2020 }
66
77 define i1 @test_negative(i32 addrspace(1)* %p) gc "statepoint-example" {
88 entry:
9 %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)
10 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
9 %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)
10 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
1111 %cmp = icmp eq i32 addrspace(1)* %pnew, null
1212 ret i1 %cmp
1313 ; CHECK-LABEL: test_negative
1717
1818 define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) gc "statepoint-example" {
1919 entry:
20 %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)
21 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
20 %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)
21 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
2222 %cmp = icmp eq i32 addrspace(1)* %pnew, null
2323 ret i1 %cmp
2424 ; CHECK-LABEL: test_nonnull
2727
2828 define i1 @test_null() gc "statepoint-example" {
2929 entry:
30 %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)
31 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
30 %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)
31 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
3232 %cmp = icmp eq i32 addrspace(1)* %pnew, null
3333 ret i1 %cmp
3434 ; CHECK-LABEL: test_null
3838
3939 define i1 @test_undef() gc "statepoint-example" {
4040 entry:
41 %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)
42 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4)
41 %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)
42 %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5)
4343 %cmp = icmp eq i32 addrspace(1)* %pnew, null
4444 ret i1 %cmp
4545 ; CHECK-LABEL: test_undef
7272 ; inserted for a function that takes 1 argument.
7373 ; CHECK: gc.statepoint.p0f_isVoidf
7474 ; CHECK: gc.statepoint.p0f_i1i1f
75 ; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0)
75 ; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0, i32 0)
7676 ; CHECK: %call12 = call i1 @llvm.experimental.gc.result.i1
7777 entry:
7878 %call1 = tail call i1 (i1) @i1_return_i1(i1 false)
1919 ; CHECK-LABEL: merge:
2020 ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %here ], [ %base_obj_y, %there ]
2121 %merged_value = phi i64 addrspace(1)* [ %x, %here ], [ %y, %there ]
22 %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)
22 %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)
2323 ret i64 addrspace(1)* %merged_value
2424 }
2525
2929
3030 merge:
3131 %next = phi i64 addrspace(1)* [ %next_x, %true ], [ %next_y, %false ]
32 %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)
32 %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)
3333 br label %loop
3434 }
3535
1818 ; CHECK-DAG: [ %next.relocated, %loop ]
1919 %current = phi i64 addrspace(1)* [ %obj, %entry ], [ %next, %loop ]
2020 %next = getelementptr i64, i64 addrspace(1)* %current, i32 1
21 %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)
21 %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)
2222 br label %loop
2323 }
2424
1212
1313 merge:
1414 %merged_value = phi i64 addrspace(1)* [ %base_obj, %entry ], [ %derived_obj, %there ]
15 %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)
15 %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)
1616 ret i64 addrspace(1)* %merged_value
1717 }
1818
1111 %current.i32 = bitcast i64 addrspace(1)* %current to i32 addrspace(1)*
1212 %next.i32 = getelementptr i32, i32 addrspace(1)* %current.i32, i32 1
1313 %next.i64 = bitcast i32 addrspace(1)* %next.i32 to i64 addrspace(1)*
14 %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)
14 %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)
1515 br label %loop
1616 }
1717
1212
1313 loop:
1414 ; CHECK: loop:
15 ; 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
15 ; 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
1616 ; CHECK-NEXT: %obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result
17 %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)
17 %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)
1818 %obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32 %safepoint_token1)
1919 switch i32 %condition, label %dest_a [
2020 i32 0, label %dest_b
3636 ; CHECK: %obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ]
3737
3838 %obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ]
39 %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)
39 %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)
4040 br label %merge.split
4141
4242 merge.split: ; preds = %merge
43 %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)
43 %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)
4444 br label %loop
4545 }
4646
2222 ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %base_obj_y, %there ]
2323 ; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ]
2424 %merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ]
25 %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)
25 %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)
2626 ret i64 addrspace(1)* %merged_value
2727 }
2828
3232 ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %merge_here ], [ %base_obj_y, %there ]
3333 ; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
3434 %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
35 %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)
35 %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)
3636 ret i64 addrspace(1)* %merged_value
3737 }
3838
4343 ; CHECK: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
4444 %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ]
4545
46 %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)
46 %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)
4747 ret i64 addrspace(1)* %merged_value
4848 }
4949
2323 loop_back:
2424 %next_element_ptr = getelementptr i64 addrspace(1)*, i64 addrspace(1)* addrspace(1)* %current_element_ptr, i32 1
2525 %next_index = add i32 %index, 1
26 %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)
26 %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)
2727 br label %loop_check
2828
2929 not_found:
1212 %condition = call i1 @runtime_value()
1313 %maybe_next = getelementptr i64, i64 addrspace(1)* %current, i32 1
1414 %next = select i1 %condition, i64 addrspace(1)* %maybe_next, i64 addrspace(1)* %current
15 %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)
15 %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)
1616 br label %loop
1717 }
1818
1515 ; CHECK-DAG: [ %obj.relocated, %loop ]
1616 ; CHECK-DAG: [ %obj, %entry ]
1717 call void @use_obj(i64 addrspace(1)* %obj)
18 %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)
18 %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)
1919 br label %loop
2020 }
2121
5656 ; CHECK: merge:
5757 ; CHECK-NEXT: %base_phi = phi i64 addrspace(1)* [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_R]], %right ], !is_base_value !0
5858 %value = phi i64 addrspace(1)* [ %a.cast, %left], [ %a.cast, %left], [ %a.cast, %left], [ %b.cast, %right]
59 %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)
59 %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)
6060
6161 ret i64 addrspace(1)* %value
6262 }
9090 %nexta = getelementptr i64, i64 addrspace(1)* %current, i32 1
9191 %next = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
9292 %extra2 = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2
93 %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)
93 %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)
9494 br label %loop
9595 }
9696
99 ; CHECK-NEXT: gc.statepoint
1010 ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
1111 entry:
12 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)
12 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)
1313 ret i8 addrspace(1)* %obj
1414 }
1515
2222 ; CHECK-NEXT: gc.statepoint
2323 ; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)*
2424 entry:
25 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)
26 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)
25 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)
26 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)
2727 ret i8 addrspace(1)* %obj
2828 }
2929
3838 ; CHECK-NEXT: load i8, i8 addrspace(1)* %obj.relocated
3939 entry:
4040 %derived = getelementptr i8, i8 addrspace(1)* %obj, i64 10
41 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)
41 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)
4242
4343 %a = load i8, i8 addrspace(1)* %derived
4444 %b = load i8, i8 addrspace(1)* %obj
5656 ; CHECK-LABEL: taken:
5757 ; CHECK-NEXT: gc.statepoint
5858 ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)*
59 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)
59 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)
6060 br label %merge
6161
6262 untaken:
6363 ; CHECK-LABEL: untaken:
6464 ; CHECK-NEXT: gc.statepoint
6565 ; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)*
66 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)
66 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)
6767 br label %merge
6868
6969 merge:
8080 ; CHECK-NEXT: gc.statepoint
8181 ; CHECK-NOT: %obj.relocated = call coldcc i8 addrspace(1)*
8282 entry:
83 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)
83 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)
8484 ret i8 addrspace(1)* %obj
8585 }
8686
88 ; CHECK: gc.statepoint
99 ; CHECK-NEXT: load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
1010 entry:
11 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
11 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
1212 %res = load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*)
1313 ret i8 %res
1414 }
2121 ; CHECK-NEXT: gc.relocate
2222 ; CHECK-NEXT: icmp
2323 entry:
24 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
24 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
2525 %cmp = icmp eq i8 addrspace(1)* %p, null
2626 br i1 %cmp, label %taken, label %not_taken
2727
5151 ; CHECK: gc.statepoint
5252 ; CHECK-NEXT: load i8, i8 addrspace(1)* @G
5353 entry:
54 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
54 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
5555 %res = load i8, i8 addrspace(1)* @G, align 1
5656 ret i8 %res
5757 }
88 ; CHECK-NEXT: gc.relocate
99 ; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated
1010 entry:
11 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
11 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
1212 ret i64 addrspace(1)* %obj
1313 }
1414
2424 ; CHECK-NEXT: insertelement
2525 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5
2626 entry:
27 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
27 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
2828 ret <2 x i64 addrspace(1)*> %obj
2929 }
3030
4242 ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5
4343 entry:
4444 %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
45 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
45 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
4646 ret <2 x i64 addrspace(1)*> %obj
4747 }
4848
5757 ; CHECK-NEXT: gc.statepoint
5858 entry:
5959 %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr
60 invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
60 invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
6161 to label %normal_return unwind label %exceptional_return
6262
6363 ; CHECK-LABEL: normal_return:
1414 ; CHECK-NEXT: gc.statepoint
1515 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
1616 ; CHECK-NEXT: br label %merge
17 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
17 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
1818 br label %merge
1919
2020 untaken:
2222 ; CHECK-NEXT: gc.statepoint
2323 ; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)*
2424 ; CHECK-NEXT: br label %merge
25 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
25 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
2626 br label %merge
2727
2828 merge:
3939 ; CHECK-LABEL: entry:
4040 ; CHECK-NEXT: gc.statepoint
4141 ; CHECK-NEXT: br
42 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
42 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
4343 br i1 %cmp, label %taken, label %untaken
4444
4545 taken:
5050 ; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated
5151
5252 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
53 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
53 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
5454 ret i64 addrspace(1)* %obj
5555
5656 untaken:
7171 ; CHECK-NEXT: gc.statepoint
7272 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
7373 ; CHECK-NEXT: br label %merge
74 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
74 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
7575 %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc
76 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
76 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
7777 br label %merge
7878
7979 untaken:
8080 ; CHECK-LABEL: taken:
8181 ; CHECK-NEXT: gc.statepoint
8282 ; CHECK-NEXT: br label %merge
83 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
83 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
8484 br label %merge
8585
8686 merge:
105105 ; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1
106106 ;
107107 %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8
108 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
108 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
109109
110 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
110 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
111111 ret i64 addrspace(1)* %derived
112112 }
113113
126126 ; CHECK-NEXT: gc.statepoint
127127 ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)*
128128 ; CHECK-NEXT: br label %merge
129 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
129 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
130130 br label %merge
131131
132132 untaken:
1515 ; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated)
1616 ; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated)
1717 %obj2 = phi i64 addrspace(1)* [ %obj, %entry ]
18 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
18 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
1919 call void (...) @consume(i64 addrspace(1)* %obj2)
2020 call void (...) @consume(i64 addrspace(1)* %obj)
2121 ret void
3131
3232 unreached:
3333 %obj = phi i64 addrspace(1)* [null, %unreached]
34 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
34 call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
3535 call void (...) @consume(i64 addrspace(1)* %obj)
3636 br label %unreached
3737 }
4444 ret void
4545
4646 unreached:
47 invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
47 invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
4848 to label %normal_return unwind label %exceptional_return
4949
5050 normal_return: ; preds = %entry
2323 ;; CHECK-LABEL: normal_dest:
2424 ;; CHECK-NEXT: gc.statepoint
2525 ;; CHECK-NEXT: %obj.relocated = call coldcc i64* addrspace(1)*
26 %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)
26 %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)
2727 ret i64* addrspace(1)* %obj
2828 }
2929
88 ; CHECK-LABEL: @test1
99 ; CHECK-DAG: %obj.relocated
1010 ; CHECK-DAG: %obj2.relocated
11 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
11 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
1212 br label %joint
1313
1414 joint:
6060 br label %loop.backedge
6161
6262 loop.backedge:
63 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0)
63 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0)
6464 br label %loop
6565
6666 loop_y:
7878 ; CHECK-LABEL: if_branch:
7979 ; CHECK: gc.statepoint
8080 ; CHECK: gc.relocate
81 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
81 %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
8282 br label %join
8383
8484 else_branch:
8585 ; CHECK-LABEL: else_branch:
8686 ; CHECK: gc.statepoint
8787 ; CHECK: gc.relocate
88 %safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0)
88 %safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0)
8989 br label %join
9090
9191 join:
108108 ; CHECK: gc.statepoint
109109 ; CHECK-NEXT: gc.relocate
110110 ; CHECK-NEXT: gc.statepoint
111 %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)
112 %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)
111 %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)
112 %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)
113113 ret void
114114 }
115115
122122 ; CHECK: gc.statepoint
123123 ; CHECK: gc.relocate
124124 ; CHECK: @use(i8 addrspace(1)* %res.relocated)
125 %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)
125 %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)
126126 %res = call i8 addrspace(1)* @llvm.experimental.gc.result.ptr.p1i8(i32 %safepoint_token2)
127 call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
127 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)
128128 call void (...) @use(i8 addrspace(1)* %res)
129129 unreachable
130130 }
134134 define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" {
135135 ; CHECK-LABEL: test5
136136 entry:
137 call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0)
137 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)
138138 switch i32 undef, label %kill [
139139 i32 10, label %merge
140140 i32 13, label %merge
168168 ; CHECK: arg1.relocated =
169169 ; CHECK: arg2.relocated =
170170 ; CHECK: arg3.relocated =
171 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)
171 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)
172172 br label %gc.safepoint_poll.exit2
173173
174174 gc.safepoint_poll.exit2:
207207 ; CHECK-LABEL: outer-inc:
208208 ; CHECK: %arg1.relocated
209209 ; CHECK: %arg2.relocated
210 %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)
210 %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)
211211 br label %outer-loop
212212 }
213213
236236 ; CHECK: gc.statepoint
237237 ; CHECK: %arg1.relocated
238238 ; CHECK: %arg2.relocated
239 %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)
239 %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)
240240 br i1 %cmp, label %inner-loop, label %outer-inc
241241
242242 outer-inc:
256256 br i1 %condition, label %callbb, label %join2
257257
258258 callbb:
259 %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)
259 %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)
260260 br label %join
261261
262262 join:
1111 define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg, i32 %val) gc "statepoint-example" {
1212 entry:
1313 %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
14 %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)
15 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
14 %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)
15 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
1616 ret i64 addrspace(1)* %reloc
1717 }
1818
99 define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" {
1010 entry:
1111 %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)*
12 %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)
13 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
12 %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)
13 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
1414 ;; It is perfectly legal to relocate the same value multiple times...
15 %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
16 %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 10, i32 9)
15 %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
16 %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 11, i32 10)
1717 ret i64 addrspace(1)* %reloc
1818 ; CHECK-LABEL: test1
1919 ; CHECK: statepoint
3838 ret void
3939
4040 equal:
41 %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)
42 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10)
41 %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)
42 %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11)
4343 call void undef(i64 addrspace(1)* %reloc)
4444 ret void
4545 ; CHECK-LABEL: test2
5656 entry:
5757 ; CHECK-LABEL: entry
5858 ; CHECK: statepoint
59 %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)
59 %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)
6060 to label %normal_dest unwind label %exceptional_return
6161
6262 normal_dest:
6464 ; CHECK: gc.relocate
6565 ; CHECK: gc.relocate
6666 ; CHECK: ret
67 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9)
67 %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10)
6868 %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10)
6969 ret i8 addrspace(1)* %obj.relocated
7070
7575 %landing_pad = landingpad { i8*, i32 } personality i32 ()* @"personality_function"
7676 cleanup
7777 %relocate_token = extractvalue { i8*, i32 } %landing_pad, 1
78 %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 9, i32 9)
78 %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10)
7979 %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10)
8080 ret i8 addrspace(1)* %obj1.relocated1
8181 }