From 5c7f7462e40e98bf6fa02baadec7337586192b7e Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Fri, 8 May 2015 18:07:42 +0000 Subject: [PATCH] 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 --- docs/Statepoints.rst | 113 +++++++++++++-- include/llvm/CodeGen/ISDOpcodes.h | 9 ++ include/llvm/IR/Statepoint.h | 47 ++++++- .../SelectionDAG/SelectionDAGDumper.cpp | 2 + .../SelectionDAG/StatepointLowering.cpp | 102 ++++++++++++-- lib/IR/IRBuilder.cpp | 4 +- lib/IR/Verifier.cpp | 37 ++++- lib/Target/X86/X86ISelLowering.cpp | 49 +++++++ lib/Target/X86/X86ISelLowering.h | 2 + .../ValueTracking/memory-dereferenceable.ll | 4 +- .../Generic/overloaded-intrinsic-name.ll | 20 +-- test/CodeGen/X86/statepoint-allocas.ll | 4 +- test/CodeGen/X86/statepoint-call-lowering.ll | 14 +- test/CodeGen/X86/statepoint-forward.ll | 12 +- .../statepoint-gctransition-call-lowering.ll | 133 ++++++++++++++++++ test/CodeGen/X86/statepoint-invoke.ll | 2 +- test/CodeGen/X86/statepoint-stack-usage.ll | 32 ++--- .../CodeGen/X86/statepoint-stackmap-format.ll | 6 +- .../CodeGenPrepare/statepoint-relocate.ll | 44 +++--- test/Transforms/InstCombine/gc.relocate.ll | 4 +- test/Transforms/InstCombine/statepoint.ll | 16 +-- test/Transforms/PlaceSafepoints/basic.ll | 2 +- .../base-pointers-1.ll | 2 +- .../base-pointers-10.ll | 2 +- .../base-pointers-11.ll | 2 +- .../base-pointers-2.ll | 2 +- .../base-pointers-3.ll | 2 +- .../base-pointers-4.ll | 8 +- .../base-pointers-5.ll | 2 +- .../base-pointers-6.ll | 2 +- .../base-pointers-7.ll | 2 +- .../base-pointers-8.ll | 2 +- .../base-pointers-9.ll | 2 +- .../RewriteStatepointsForGC/base-pointers.ll | 6 +- .../RewriteStatepointsForGC/basics.ll | 14 +- .../RewriteStatepointsForGC/constants.ll | 6 +- .../RewriteStatepointsForGC/live-vector.ll | 8 +- .../liveness-basics.ll | 20 +-- .../RewriteStatepointsForGC/preprocess.ll | 6 +- .../relocate_invoke_result.ll | 2 +- .../RewriteStatepointsForGC/relocation.ll | 26 ++-- test/Verifier/invalid-statepoint2.ll | 4 +- test/Verifier/statepoint.ll | 18 +-- 43 files changed, 616 insertions(+), 180 deletions(-) create mode 100644 test/CodeGen/X86/statepoint-gctransition-call-lowering.ll diff --git a/docs/Statepoints.rst b/docs/Statepoints.rst index 9741c93cc81..438171cb932 100644 --- a/docs/Statepoints.rst +++ b/docs/Statepoints.rst @@ -142,8 +142,8 @@ resulting relocation sequence is: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4) ret i8 addrspace(1)* %obj.relocated } @@ -207,7 +207,82 @@ This example was taken from the tests for the :ref:`RewriteStatepointsForGC` uti opt -rewrite-statepoints-for-gc test/Transforms/RewriteStatepointsForGC/basics.ll -S | llc -debug-only=stackmaps +GC Transitions +^^^^^^^^^^^^^^^^^^ + +As a practical consideration, many garbage-collected systems allow code that is +collector-aware ("managed code") to call code that is not collector-aware +("unmanaged code"). It is common that such calls must also be safepoints, since +it is desirable to allow the collector to run during the execution of +unmanaged code. Futhermore, it is common that coordinating the transition from +managed to unmanaged code requires extra code generation at the call site to +inform the collector of the transition. In order to support these needs, a +statepoint may be marked as a GC transition, and data that is necessary to +perform the transition (if any) may be provided as additional arguments to the +statepoint. + + Note that although in many cases statepoints may be inferred to be GC + transitions based on the function symbols involved (e.g. a call from a + function with GC strategy "foo" to a function with GC strategy "bar"), + indirect calls that are also GC transitions must also be supported. This + requirement is the driving force behing the decision to require that GC + transitions are explicitly marked. + +Let's revisit the sample given above, this time treating the call to ``@foo`` +as a GC transition. Depending on our target, the transition code may need to +access some extra state in order to inform the collector of the transition. +Let's assume a hypothetical GC--somewhat unimaginatively named "hypothetical-gc" +--that requires that a TLS variable must be written to before and after a call +to unmanaged code. The resulting relocation sequence is: + +.. code-block:: llvm + + @flag = thread_local global i32 0, align 4 + define i8 addrspace(1)* @test1(i8 addrspace(1) *%obj) + gc "hypothetical-gc" { + + %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 1, i32* @Flag, i32 0, i8 addrspace(1)* %obj) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 4, i32 4) + ret i8 addrspace(1)* %obj.relocated + } + +During lowering, this will result in a instruction selection DAG that looks +something like: + +.. code-block:: + + CALLSEQ_START + ... + GC_TRANSITION_START (lowered i32 *@Flag), SRCVALUE i32* Flag + STATEPOINT + GC_TRANSITION_END (lowered i32 *@Flag), SRCVALUE i32 *Flag + ... + CALLSEQ_END + +In order to generate the necessary transition code, the backend for each target +supported by "hypothetical-gc" must be modified to lower ``GC_TRANSITION_START`` +and ``GC_TRANSITION_END`` nodes appropriately when the "hypothetical-gc" +strategy is in use for a particular function. Assuming that such lowering has +been added for X86, the generated assembly would be: + +.. code-block:: gas + + .globl test1 + .align 16, 0x90 + pushq %rax + movl $1, %fs:Flag@TPOFF + callq foo + movl $0, %fs:Flag@TPOFF + .Ltmp1: + movq (%rsp), %rax # This load is redundant (oops!) + popq %rdx + retq + +Note that the design as presented above is not fully implemented: in particular, +strategy-specific lowering is not present, and all GC transitions are emitted as +as single no-op before and after the call instruction. These no-ops are often +removed by the backend during dead machine instruction elimination. Intrinsics @@ -223,8 +298,9 @@ Syntax: declare i32 @llvm.experimental.gc.statepoint(func_type , - i64 <#call args>. i64 , + i64 <#call args>. i64 , ... (call parameters), + i64 <# transition args>, ... (transition parameters), i64 <# deopt args>, ... (deopt parameters), ... (gc parameters)) @@ -247,8 +323,19 @@ The '#call args' operand is the number of arguments to the actual call. It must exactly match the number of arguments passed in the 'call parameters' variable length section. -The 'unused' operand is unused and likely to be removed. Please do -not use. +The 'flags' operand is used to specify extra information about the +statepoint. This is currently only used to mark certain statepoints +as GC transitions. This operand is a 64-bit integer with the following +layout, where bit 0 is the least significant bit: + + +-------+---------------------------------------------------+ + | Bit # | Usage | + +=======+===================================================+ + | 0 | Set if the statepoint is a GC transition, cleared | + | | otherwise. | + +-------+---------------------------------------------------+ + | 1-63 | Reserved for future use; must be cleared. | + +-------+---------------------------------------------------+ The 'call parameters' arguments are simply the arguments which need to be passed to the call target. They will be lowered according to the @@ -257,6 +344,14 @@ instruction. The number of arguments must exactly match what is specified in '# call args'. The types must match the signature of 'target'. +The 'transition parameters' arguments contain an arbitrary list of +Values which need to be passed to GC transition code. They will be +lowered and passed as operands to the appropriate GC_TRANSITION nodes +in the selection DAG. It is assumed that these arguments must be +available before and after (but not necessarily during) the execution +of the callee. The '# transition args' field indicates how many operands +are to be interpreted as 'transition parameters'. + The 'deopt parameters' arguments contain an arbitrary list of Values which is meaningful to the runtime. The runtime may read any of these values, but is assumed not to modify them. If the garbage collector @@ -471,7 +566,7 @@ As an example, given this code: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i8 addrspace(1)* %obj } @@ -481,7 +576,7 @@ The pass would produce this IR: define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { - %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) + %0 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj) %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) ret i8 addrspace(1)* %obj.relocated } @@ -535,8 +630,8 @@ This pass would produce the following IR: .. code-block:: llvm define void @test() gc "statepoint-example" { - %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) - %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (void ()*, i32, i32, ...)* @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) ret void } diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 1891086ec3a..a60519da810 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -701,6 +701,15 @@ namespace ISD { /// is the chain and the second operand is the alloca pointer. LIFETIME_START, LIFETIME_END, + /// GC_TRANSITION_START/GC_TRANSITION_END - These operators mark the + /// beginning and end of GC transition sequence, and carry arbitrary + /// information that target might need for lowering. The first operand is + /// a chain, the rest are specified by the target and not touched by the DAG + /// optimizers. GC_TRANSITION_START..GC_TRANSITION_END pairs may not be + /// nested. + GC_TRANSITION_START, + GC_TRANSITION_END, + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END diff --git a/include/llvm/IR/Statepoint.h b/include/llvm/IR/Statepoint.h index a337222e08e..a349edae7d7 100644 --- a/include/llvm/IR/Statepoint.h +++ b/include/llvm/IR/Statepoint.h @@ -24,6 +24,15 @@ #include "llvm/Support/Compiler.h" namespace llvm { +/// The statepoint intrinsic accepts a set of flags as its third argument. +/// Valid values come out of this set. +enum class StatepointFlags { + None = 0, + GCTransition = 1, ///< Indicates that this statepoint is a transition from + ///< GC-aware code to code that is not GC-aware. + + MaskAll = GCTransition ///< A bitmask that includes all valid flags. +}; class GCRelocateOperands; class ImmutableStatepoint; @@ -72,6 +81,10 @@ public: /// Return the underlying CallSite. CallSiteTy getCallSite() { return StatepointCS; } + uint64_t getFlags() const { + return cast(StatepointCS.getArgument(2))->getZExtValue(); + } + /// Return the value actually being called or invoked. ValueTy *getActualCallee() { return StatepointCS.getArgument(ActualCalleePos); @@ -106,16 +119,42 @@ public: return iterator_range(call_args_begin(), call_args_end()); } + /// Number of GC transition args. + int getNumTotalGCTransitionArgs() { + const Value *NumGCTransitionArgs = *gc_transition_args_begin(); + return cast(NumGCTransitionArgs)->getZExtValue(); + } + typename CallSiteTy::arg_iterator gc_transition_args_begin() { + int Offset = call_args_end() - StatepointCS.arg_begin(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + typename CallSiteTy::arg_iterator gc_transition_args_end() { + int Offset = (gc_transition_args_begin() + 1 + + getNumTotalGCTransitionArgs()) - StatepointCS.arg_begin(); + assert(Offset <= (int)StatepointCS.arg_size()); + return StatepointCS.arg_begin() + Offset; + } + + /// range adapter for GC transition arguments + iterator_range gc_transition_args() { + return iterator_range(gc_transition_args_begin(), + gc_transition_args_end()); + } + /// Number of additional arguments excluding those intended /// for garbage collection. int getNumTotalVMSArgs() { - Value *NumVMSArgs = *call_args_end(); + Value *NumVMSArgs = *vm_state_begin(); return cast(NumVMSArgs)->getZExtValue(); } - typename CallSiteTy::arg_iterator vm_state_begin() { return call_args_end(); } + typename CallSiteTy::arg_iterator vm_state_begin() { + return gc_transition_args_end(); + } typename CallSiteTy::arg_iterator vm_state_end() { - int Offset = CallArgsBeginPos + getNumCallArgs() + 1 + getNumTotalVMSArgs(); + int Offset = (gc_transition_args_end() + 1 + getNumTotalVMSArgs()) - + StatepointCS.arg_begin(); assert(Offset <= (int)StatepointCS.arg_size()); return StatepointCS.arg_begin() + Offset; } @@ -152,6 +191,8 @@ public: // The internal asserts in the iterator accessors do the rest. (void)call_args_begin(); (void)call_args_end(); + (void)gc_transition_args_begin(); + (void)gc_transition_args_end(); (void)vm_state_begin(); (void)vm_state_end(); (void)gc_args_begin(); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp index 84151025612..9970540946a 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -288,6 +288,8 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::DEBUGTRAP: return "debugtrap"; case ISD::LIFETIME_START: return "lifetime.start"; case ISD::LIFETIME_END: return "lifetime.end"; + case ISD::GC_TRANSITION_START: return "gc_transition.start"; + case ISD::GC_TRANSITION_END: return "gc_transition.end"; // Bit manipulation case ISD::BSWAP: return "bswap"; diff --git a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index 49c08d977bc..6c40053cb46 100644 --- a/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -585,24 +585,66 @@ void SelectionDAGBuilder::LowerStatepoint( SDNode *CallNode = lowerCallFromStatepoint(ISP, LandingPad, *this, PendingExports); - // Construct the actual STATEPOINT node with all the appropriate arguments - // and return values. + // Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END + // nodes with all the appropriate arguments and return values. // TODO: Currently, all of these operands are being marked as read/write in // PrologEpilougeInserter.cpp, we should special case the VMState arguments // and flags to be read-only. SmallVector Ops; - // Calculate and push starting position of vmstate arguments // Call Node: Chain, Target, {Args}, RegMask, [Glue] + SDValue Chain = CallNode->getOperand(0); + SDValue Glue; - if (CallNode->getGluedNode()) { + bool CallHasIncomingGlue = CallNode->getGluedNode(); + if (CallHasIncomingGlue) { // Glue is always last operand Glue = CallNode->getOperand(CallNode->getNumOperands() - 1); } + + // Build the GC_TRANSITION_START node if necessary. + // + // The operands to the GC_TRANSITION_{START,END} nodes are laid out in the + // order in which they appear in the call to the statepoint intrinsic. If + // any of the operands is a pointer-typed, that operand is immediately + // followed by a SRCVALUE for the pointer that may be used during lowering + // (e.g. to form MachinePointerInfo values for loads/stores). + const bool IsGCTransition = + (ISP.getFlags() & (uint64_t)StatepointFlags::GCTransition) == + (uint64_t)StatepointFlags::GCTransition; + if (IsGCTransition) { + SmallVector TSOps; + + // Add chain + TSOps.push_back(Chain); + + // Add GC transition arguments + for (auto I = ISP.gc_transition_args_begin() + 1, + E = ISP.gc_transition_args_end(); + I != E; ++I) { + TSOps.push_back(getValue(*I)); + if ((*I)->getType()->isPointerTy()) + TSOps.push_back(DAG.getSrcValue(*I)); + } + + // Add glue if necessary + if (CallHasIncomingGlue) + TSOps.push_back(Glue); + + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + + SDValue GCTransitionStart = + DAG.getNode(ISD::GC_TRANSITION_START, getCurSDLoc(), NodeTys, TSOps); + + Chain = GCTransitionStart.getValue(0); + Glue = GCTransitionStart.getValue(1); + } + + // Calculate and push starting position of vmstate arguments // Get number of arguments incoming directly into call node unsigned NumCallRegArgs = - CallNode->getNumOperands() - (Glue.getNode() ? 4 : 3); + CallNode->getNumOperands() - (CallHasIncomingGlue ? 4 : 3); Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, getCurSDLoc(), MVT::i32)); // Add call target @@ -612,7 +654,7 @@ void SelectionDAGBuilder::LowerStatepoint( // Add call arguments // Get position of register mask in the call SDNode::op_iterator RegMaskIt; - if (Glue.getNode()) + if (CallHasIncomingGlue) RegMaskIt = CallNode->op_end() - 2; else RegMaskIt = CallNode->op_end() - 1; @@ -621,11 +663,17 @@ void SelectionDAGBuilder::LowerStatepoint( // Add a leading constant argument with the Flags and the calling convention // masked together CallingConv::ID CallConv = CS.getCallingConv(); - int Flags = cast(CS.getArgument(2))->getZExtValue(); - assert(Flags == 0 && "not expected to be used"); + uint64_t Flags = cast(CS.getArgument(2))->getZExtValue(); + assert( + ((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0) + && "unknown flag used"); + const int Shift = 1; + static_assert( + ((~(uint64_t)0 << Shift) & (uint64_t)StatepointFlags::MaskAll) == 0, + "shift width too small"); Ops.push_back(DAG.getTargetConstant(StackMaps::ConstantOp, getCurSDLoc(), MVT::i64)); - Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << 1), + Ops.push_back(DAG.getTargetConstant(Flags | ((unsigned)CallConv << Shift), getCurSDLoc(), MVT::i64)); // Insert all vmstate and gcstate arguments @@ -635,7 +683,7 @@ void SelectionDAGBuilder::LowerStatepoint( Ops.push_back(*RegMaskIt); // Add chain - Ops.push_back(CallNode->getOperand(0)); + Ops.push_back(Chain); // Same for the glue, but we add it only if original call had it if (Glue.getNode()) @@ -648,8 +696,40 @@ void SelectionDAGBuilder::LowerStatepoint( SDNode *StatepointMCNode = DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops); + SDNode *SinkNode = StatepointMCNode; + + // Build the GC_TRANSITION_END node if necessary. + // + // See the comment above regarding GC_TRANSITION_START for the layout of + // the operands to the GC_TRANSITION_END node. + if (IsGCTransition) { + SmallVector TEOps; + + // Add chain + TEOps.push_back(SDValue(StatepointMCNode, 0)); + + // Add GC transition arguments + for (auto I = ISP.gc_transition_args_begin() + 1, + E = ISP.gc_transition_args_end(); + I != E; ++I) { + TEOps.push_back(getValue(*I)); + if ((*I)->getType()->isPointerTy()) + TEOps.push_back(DAG.getSrcValue(*I)); + } + + // Add glue + TEOps.push_back(SDValue(StatepointMCNode, 1)); + + SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); + + SDValue GCTransitionStart = + DAG.getNode(ISD::GC_TRANSITION_END, getCurSDLoc(), NodeTys, TEOps); + + SinkNode = GCTransitionStart.getNode(); + } + // Replace original call - DAG.ReplaceAllUsesWith(CallNode, StatepointMCNode); // This may update Root + DAG.ReplaceAllUsesWith(CallNode, SinkNode); // This may update Root // Remove originall call node DAG.DeleteNode(CallNode); diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index c526c862bdc..87fca8c8610 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Statepoint.h" using namespace llvm; /// CreateGlobalString - Make a new global variable with an initializer that @@ -252,8 +253,9 @@ static std::vector getStatepointArgs(IRBuilderBase &B, std::vector Args; Args.push_back(ActualCallee); Args.push_back(B.getInt32(CallArgs.size())); - Args.push_back(B.getInt32(0)); // unused + Args.push_back(B.getInt32((unsigned)StatepointFlags::None)); Args.insert(Args.end(), CallArgs.begin(), CallArgs.end()); + Args.push_back(B.getInt32(0 /* no transition args */)); Args.push_back(B.getInt32(DeoptArgs.size())); Args.insert(Args.end(), DeoptArgs.begin(), DeoptArgs.end()); Args.insert(Args.end(), GCArgs.begin(), GCArgs.end()); diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 4b54f278219..374f8f210be 100644 --- a/lib/IR/Verifier.cpp +++ b/lib/IR/Verifier.cpp @@ -1529,9 +1529,12 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) { Assert(NumCallArgs == NumParams, "gc.statepoint mismatch in number of call args", &CI); - const Value *Unused = CS.getArgument(2); - Assert(isa(Unused) && cast(Unused)->isNullValue(), - "gc.statepoint parameter #3 must be zero", &CI); + const Value *FlagsV = CS.getArgument(2); + Assert(isa(FlagsV), + "gc.statepoint flags must be constant integer", &CI); + const uint64_t Flags = cast(FlagsV)->getZExtValue(); + Assert((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0, + "unknown flag used in gc.statepoint flags argument", &CI); // Verify that the types of the call parameter arguments match // the type of the wrapped callee. @@ -1544,7 +1547,19 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) { &CI); } const int EndCallArgsInx = 2+NumCallArgs; - const Value *NumDeoptArgsV = CS.getArgument(EndCallArgsInx+1); + + const Value *NumTransitionArgsV = CS.getArgument(EndCallArgsInx+1); + Assert(isa(NumTransitionArgsV), + "gc.statepoint number of transition arguments " + "must be constant integer", + &CI); + const int NumTransitionArgs = + cast(NumTransitionArgsV)->getZExtValue(); + Assert(NumTransitionArgs >= 0, + "gc.statepoint number of transition arguments must be positive", &CI); + const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; + + const Value *NumDeoptArgsV = CS.getArgument(EndTransitionArgsInx+1); Assert(isa(NumDeoptArgsV), "gc.statepoint number of deoptimization arguments " "must be constant integer", @@ -1554,7 +1569,9 @@ void Verifier::VerifyStatepoint(ImmutableCallSite CS) { "must be positive", &CI); - Assert(4 + NumCallArgs + NumDeoptArgs <= (int)CS.arg_size(), + const int ExpectedNumArgs = + 5 + NumCallArgs + NumTransitionArgs + NumDeoptArgs; + Assert(ExpectedNumArgs <= (int)CS.arg_size(), "gc.statepoint too few arguments according to length fields", &CI); // Check that the only uses of this gc.statepoint are gc.result or @@ -3346,11 +3363,17 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) { Assert(StatepointCS.arg_size() > NumCallArgs+3, "gc.statepoint: mismatch in number of call arguments"); Assert(isa(StatepointCS.getArgument(NumCallArgs+3)), + "gc.statepoint: number of transition arguments must be " + "a constant integer"); + const int NumTransitionArgs = + cast(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue(); + const int DeoptArgsStart = 2 + NumCallArgs + 1 + NumTransitionArgs + 1; + Assert(isa(StatepointCS.getArgument(DeoptArgsStart)), "gc.statepoint: number of deoptimization arguments must be " "a constant integer"); const int NumDeoptArgs = - cast(StatepointCS.getArgument(NumCallArgs + 3))->getZExtValue(); - const int GCParamArgsStart = NumCallArgs + NumDeoptArgs + 4; + cast(StatepointCS.getArgument(DeoptArgsStart))->getZExtValue(); + const int GCParamArgsStart = DeoptArgsStart + 1 + NumDeoptArgs; const int GCParamArgsEnd = StatepointCS.arg_size(); Assert(GCParamArgsStart <= BaseIndex && BaseIndex < GCParamArgsEnd, "gc.relocate: statepoint base index doesn't fall within the " diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 35517212acc..7f24ab43490 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -513,6 +513,10 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::DYNAMIC_STACKALLOC, getPointerTy(), Custom); + // GC_TRANSITION_START and GC_TRANSITION_END need custom lowering. + setOperationAction(ISD::GC_TRANSITION_START, MVT::Other, Custom); + setOperationAction(ISD::GC_TRANSITION_END, MVT::Other, Custom); + if (!TM.Options.UseSoftFloat && X86ScalarSSEf64) { // f32 and f64 use SSE. // Set up the FP register classes. @@ -17425,6 +17429,48 @@ static SDValue LowerMGATHER(SDValue Op, const X86Subtarget *Subtarget, return Op; } +SDValue X86TargetLowering::LowerGC_TRANSITION_START(SDValue Op, + SelectionDAG &DAG) const { + // TODO: Eventually, the lowering of these nodes should be informed by or + // deferred to the GC strategy for the function in which they appear. For + // now, however, they must be lowered to something. Since they are logically + // no-ops in the case of a null GC strategy (or a GC strategy which does not + // require special handling for these nodes), lower them as literal NOOPs for + // the time being. + SmallVector Ops; + + Ops.push_back(Op.getOperand(0)); + if (Op->getGluedNode()) + Ops.push_back(Op->getOperand(Op->getNumOperands() - 1)); + + SDLoc OpDL(Op); + SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0); + + return NOOP; +} + +SDValue X86TargetLowering::LowerGC_TRANSITION_END(SDValue Op, + SelectionDAG &DAG) const { + // TODO: Eventually, the lowering of these nodes should be informed by or + // deferred to the GC strategy for the function in which they appear. For + // now, however, they must be lowered to something. Since they are logically + // no-ops in the case of a null GC strategy (or a GC strategy which does not + // require special handling for these nodes), lower them as literal NOOPs for + // the time being. + SmallVector Ops; + + Ops.push_back(Op.getOperand(0)); + if (Op->getGluedNode()) + Ops.push_back(Op->getOperand(Op->getNumOperands() - 1)); + + SDLoc OpDL(Op); + SDVTList VTs = DAG.getVTList(MVT::Other, MVT::Glue); + SDValue NOOP(DAG.getMachineNode(X86::NOOP, SDLoc(Op), VTs, Ops), 0); + + return NOOP; +} + /// LowerOperation - Provide custom lowering hooks for some operations. /// SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { @@ -17514,6 +17560,9 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { case ISD::FSINCOS: return LowerFSINCOS(Op, Subtarget, DAG); case ISD::MGATHER: return LowerMGATHER(Op, Subtarget, DAG); case ISD::MSCATTER: return LowerMSCATTER(Op, Subtarget, DAG); + case ISD::GC_TRANSITION_START: + return LowerGC_TRANSITION_START(Op, DAG); + case ISD::GC_TRANSITION_END: return LowerGC_TRANSITION_END(Op, DAG); } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index a7e440c25e4..bc6138c67ec 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -969,6 +969,8 @@ namespace llvm { SDValue LowerINIT_TRAMPOLINE(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG) const; SDValue LowerWin64_i128OP(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGC_TRANSITION_START(SDValue Op, SelectionDAG &DAG) const; + SDValue LowerGC_TRANSITION_END(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFormalArguments(SDValue Chain, diff --git a/test/Analysis/ValueTracking/memory-dereferenceable.ll b/test/Analysis/ValueTracking/memory-dereferenceable.ll index bfee5c78df6..218dab6b20a 100644 --- a/test/Analysis/ValueTracking/memory-dereferenceable.ll +++ b/test/Analysis/ValueTracking/memory-dereferenceable.ll @@ -22,8 +22,8 @@ entry: %alloca = alloca i1 %load2 = load i1, i1* %alloca %load3 = load i32, i32 addrspace(1)* %dparam - %tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) - %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4) + %tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5) %load4 = load i32, i32 addrspace(1)* %relocate %nparam = getelementptr i32, i32 addrspace(1)* %dparam, i32 5 %load5 = load i32, i32 addrspace(1)* %nparam diff --git a/test/CodeGen/Generic/overloaded-intrinsic-name.ll b/test/CodeGen/Generic/overloaded-intrinsic-name.ll index 915ba9fae51..9c88d8d232f 100644 --- a/test/CodeGen/Generic/overloaded-intrinsic-name.ll +++ b/test/CodeGen/Generic/overloaded-intrinsic-name.ll @@ -13,29 +13,29 @@ ; function and integer define i32* @test_iAny(i32* %v) gc "statepoint-example" { - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %v) - %v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %v) + %v-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5) ret i32* %v-new } ; float define float* @test_fAny(float* %v) gc "statepoint-example" { - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, float* %v) - %v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, float* %v) + %v-new = call float* @llvm.experimental.gc.relocate.p0f32(i32 %tok, i32 5, i32 5) ret float* %v-new } ; array of integers define [3 x i32]* @test_aAny([3 x i32]* %v) gc "statepoint-example" { - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %v) - %v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %v) + %v-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5) ret [3 x i32]* %v-new } ; vector of integers define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" { - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, <3 x i32>* %v) - %v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, <3 x i32>* %v) + %v-new = call <3 x i32>* @llvm.experimental.gc.relocate.p0v3i32(i32 %tok, i32 5, i32 5) ret <3 x i32>* %v-new } @@ -43,8 +43,8 @@ define <3 x i32>* @test_vAny(<3 x i32>* %v) gc "statepoint-example" { ; struct define %struct.test* @test_struct(%struct.test* %v) gc "statepoint-example" { - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, %struct.test* %v) - %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, %struct.test* %v) + %v-new = call %struct.test* @llvm.experimental.gc.relocate.p0struct.test(i32 %tok, i32 5, i32 5) ret %struct.test* %v-new } diff --git a/test/CodeGen/X86/statepoint-allocas.ll b/test/CodeGen/X86/statepoint-allocas.ll index eb34a42f462..fe11990a718 100644 --- a/test/CodeGen/X86/statepoint-allocas.ll +++ b/test/CodeGen/X86/statepoint-allocas.ll @@ -21,7 +21,7 @@ define i32 addrspace(1)* @test(i32 addrspace(1)* %ptr) gc "statepoint-example" { entry: %alloca = alloca i32 addrspace(1)*, align 8 store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca - call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca) + call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)** %alloca) %rel = load i32 addrspace(1)*, i32 addrspace(1)** %alloca ret i32 addrspace(1)* %rel } @@ -38,7 +38,7 @@ define i32 addrspace(1)* @test2(i32 addrspace(1)* %ptr) gc "statepoint-example" entry: %alloca = alloca i32 addrspace(1)*, align 8 store i32 addrspace(1)* %ptr, i32 addrspace(1)** %alloca - call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca) + call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 1, i32 addrspace(1)** %alloca) ret i32 addrspace(1)* null } diff --git a/test/CodeGen/X86/statepoint-call-lowering.ll b/test/CodeGen/X86/statepoint-call-lowering.ll index 9f6e4f967c9..7380702184b 100644 --- a/test/CodeGen/X86/statepoint-call-lowering.ll +++ b/test/CodeGen/X86/statepoint-call-lowering.ll @@ -20,7 +20,7 @@ define i1 @test_i1_return() gc "statepoint-example" { ; CHECK: popq %rdx ; CHECK: retq entry: - %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0) + %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0) %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) ret i1 %call1 } @@ -32,7 +32,7 @@ define i32 @test_i32_return() gc "statepoint-example" { ; CHECK: popq %rdx ; CHECK: retq entry: - %safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0) + %safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 0, i32 0, i32 0) %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token) ret i32 %call1 } @@ -44,7 +44,7 @@ define i32* @test_i32ptr_return() gc "statepoint-example" { ; CHECK: popq %rdx ; CHECK: retq entry: - %safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0) + %safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 0, i32 0, i32 0) %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token) ret i32* %call1 } @@ -56,7 +56,7 @@ define float @test_float_return() gc "statepoint-example" { ; CHECK: popq %rax ; CHECK: retq entry: - %safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0) + %safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 0, i32 0, i32 0) %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token) ret float %call1 } @@ -70,8 +70,8 @@ define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" { ; CHECK-NEXT: popq %rdx ; CHECK-NEXT: retq entry: - %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a) - %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %a) + %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) ret i1 %call2 } @@ -81,7 +81,7 @@ define void @test_void_vararg() gc "statepoint-example" { ; Check a statepoint wrapping a *void* returning vararg function works ; CHECK: callq varargf entry: - %safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0) + %safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 0, i32 42, i32 43, i32 0, i32 0) ;; if we try to use the result from a statepoint wrapping a ;; non-void-returning varargf, we will experience a crash. ret void diff --git a/test/CodeGen/X86/statepoint-forward.ll b/test/CodeGen/X86/statepoint-forward.ll index 0b296cf0a84..52b2ab39cfe 100644 --- a/test/CodeGen/X86/statepoint-forward.ll +++ b/test/CodeGen/X86/statepoint-forward.ll @@ -25,8 +25,8 @@ entry: %before = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %p %cmp1 = call i1 @f(i32 addrspace(1)* %before) call void @llvm.assume(i1 %cmp1) - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p) - %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p) + %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5) %after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew %cmp2 = call i1 @f(i32 addrspace(1)* %after) ret i1 %cmp2 @@ -44,8 +44,8 @@ entry: %cmp1 = call i1 @f(i32 addrspace(1)* %v) call void @llvm.assume(i1 %cmp1) store i32 addrspace(1)* %v, i32 addrspace(1)* addrspace(1)* %p - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p) - %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* addrspace(1)* %p) + %pnew = call i32 addrspace(1)* addrspace(1)* @llvm.experimental.gc.relocate.p1p1i32(i32 %safepoint_token, i32 5, i32 5) %after = load i32 addrspace(1)*, i32 addrspace(1)* addrspace(1)* %pnew %cmp2 = call i1 @f(i32 addrspace(1)* %after) ret i1 %cmp2 @@ -72,7 +72,7 @@ entry: %before = load i32 addrspace(1)*, i32 addrspace(1)** %p %cmp1 = call i1 @f(i32 addrspace(1)* %before) call void @llvm.assume(i1 %cmp1) - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0) %after = load i32 addrspace(1)*, i32 addrspace(1)** %p %cmp2 = call i1 @f(i32 addrspace(1)* %after) ret i1 %cmp2 @@ -90,7 +90,7 @@ entry: %cmp1 = call i1 @f(i32 addrspace(1)* %v) call void @llvm.assume(i1 %cmp1) store i32 addrspace(1)* %v, i32 addrspace(1)** %p - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0) %after = load i32 addrspace(1)*, i32 addrspace(1)** %p %cmp2 = call i1 @f(i32 addrspace(1)* %after) ret i1 %cmp2 diff --git a/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll b/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll new file mode 100644 index 00000000000..db642fb29f9 --- /dev/null +++ b/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll @@ -0,0 +1,133 @@ +; RUN: llc < %s | FileCheck %s +; This file contains a collection of basic tests to ensure we didn't +; screw up normal call lowering when a statepoint is a GC transition. + +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +declare zeroext i1 @return_i1() +declare zeroext i32 @return_i32() +declare zeroext i32 @return_i32_with_args(i32, i8*) +declare i32* @return_i32ptr() +declare float @return_float() +declare void @varargf(i32, ...) + +define i1 @test_i1_return() gc "statepoint-example" { +; CHECK-LABEL: test_i1_return +; This is just checking that a i1 gets lowered normally when there's no extra +; state arguments to the statepoint +; CHECK: pushq %rax +; CHECK: callq return_i1 +; CHECK: popq %rdx +; CHECK: retq +entry: + %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0) + %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) + ret i1 %call1 +} + +define i32 @test_i32_return() gc "statepoint-example" { +; CHECK-LABEL: test_i32_return +; CHECK: pushq %rax +; CHECK: callq return_i32 +; CHECK: popq %rdx +; CHECK: retq +entry: + %safepoint_token = tail call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 1, i32 0, i32 0) + %call1 = call zeroext i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token) + ret i32 %call1 +} + +define i32* @test_i32ptr_return() gc "statepoint-example" { +; CHECK-LABEL: test_i32ptr_return +; CHECK: pushq %rax +; CHECK: callq return_i32ptr +; CHECK: popq %rdx +; CHECK: retq +entry: + %safepoint_token = tail call i32 (i32* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()* @return_i32ptr, i32 0, i32 1, i32 0, i32 0) + %call1 = call i32* @llvm.experimental.gc.result.p0i32(i32 %safepoint_token) + ret i32* %call1 +} + +define float @test_float_return() gc "statepoint-example" { +; CHECK-LABEL: test_float_return +; CHECK: pushq %rax +; CHECK: callq return_float +; CHECK: popq %rax +; CHECK: retq +entry: + %safepoint_token = tail call i32 (float ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_f32f(float ()* @return_float, i32 0, i32 1, i32 0, i32 0) + %call1 = call float @llvm.experimental.gc.result.f32(i32 %safepoint_token) + ret float %call1 +} + +define i1 @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" { +; CHECK-LABEL: test_relocate +; Check that an ununsed relocate has no code-generation impact +; CHECK: pushq %rax +; CHECK: callq return_i1 +; CHECK-NEXT: .Ltmp9: +; CHECK-NEXT: popq %rdx +; CHECK-NEXT: retq +entry: + %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 1, i32 0, i32 0, i32 addrspace(1)* %a) + %call1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) + %call2 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) + ret i1 %call2 +} + +define void @test_void_vararg() gc "statepoint-example" { +; CHECK-LABEL: test_void_vararg +; Check a statepoint wrapping a *void* returning vararg function works +; CHECK: callq varargf +entry: + %safepoint_token = tail call i32 (void (i32, ...)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)* @varargf, i32 2, i32 1, i32 42, i32 43, i32 0, i32 0) + ;; if we try to use the result from a statepoint wrapping a + ;; non-void-returning varargf, we will experience a crash. + ret void +} + +define i32 @test_transition_args() gc "statepoint-example" { +; CHECK-LABEL: test_transition_args +; CHECK: pushq %rax +; CHECK: callq return_i32 +; CHECK: popq %rdx +; CHECK: retq +entry: + %val = alloca i32 + %safepoint_token = call i32 (i32 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()* @return_i32, i32 0, i32 1, i32 2, i32* %val, i64 42, i32 0) + %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token) + ret i32 %call1 +} + +define i32 @test_transition_args_2() gc "statepoint-example" { +; CHECK-LABEL: test_transition_args_2 +; CHECK: pushq %rax +; CHECK: callq return_i32 +; CHECK: popq %rdx +; CHECK: retq +entry: + %val = alloca i32 + %arg = alloca i8 + %safepoint_token = call i32 (i32 (i32, i8*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i32 (i32, i8*)* @return_i32_with_args, i32 2, i32 1, i32 0, i8* %arg, i32 2, i32* %val, i64 42, i32 0) + %call1 = call i32 @llvm.experimental.gc.result.i32(i32 %safepoint_token) + ret i32 %call1 +} + +declare i32 @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()*, i32, i32, ...) +declare i1 @llvm.experimental.gc.result.i1(i32) + +declare i32 @llvm.experimental.gc.statepoint.p0f_i32f(i32 ()*, i32, i32, ...) +declare i32 @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i32 (i32, i8*)*, i32, i32, ...) +declare i32 @llvm.experimental.gc.result.i32(i32) + +declare i32 @llvm.experimental.gc.statepoint.p0f_p0i32f(i32* ()*, i32, i32, ...) +declare i32* @llvm.experimental.gc.result.p0i32(i32) + +declare i32 @llvm.experimental.gc.statepoint.p0f_f32f(float ()*, i32, i32, ...) +declare float @llvm.experimental.gc.result.f32(i32) + +declare i32 @llvm.experimental.gc.statepoint.p0f_isVoidi32varargf(void (i32, ...)*, i32, i32, ...) + +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32, i32, i32) diff --git a/test/CodeGen/X86/statepoint-invoke.ll b/test/CodeGen/X86/statepoint-invoke.ll index 17f71ea39cb..3817453c93f 100644 --- a/test/CodeGen/X86/statepoint-invoke.ll +++ b/test/CodeGen/X86/statepoint-invoke.ll @@ -13,7 +13,7 @@ entry: ; CHECK: .Ltmp{{[0-9]+}}: ; CHECK: callq some_other_call ; CHECK: .Ltmp{{[0-9]+}}: - %0 = invoke i32 (i64 addrspace(1)* (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64p1i64f(i64 addrspace(1)* (i64 addrspace(1)*)* @some_other_call, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) + %0 = invoke i32 (i64 addrspace(1)* (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64p1i64f(i64 addrspace(1)* (i64 addrspace(1)*)* @some_other_call, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i64 addrspace(1)* %obj, i64 addrspace(1)* %obj1) to label %normal_return unwind label %exceptional_return normal_return: diff --git a/test/CodeGen/X86/statepoint-stack-usage.ll b/test/CodeGen/X86/statepoint-stack-usage.ll index a968c037b27..c40fabf71c3 100644 --- a/test/CodeGen/X86/statepoint-stack-usage.ll +++ b/test/CodeGen/X86/statepoint-stack-usage.ll @@ -14,17 +14,17 @@ define i32 @back_to_back_calls(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 a ; CHECK: movq %rdx, 16(%rsp) ; CHECK: movq %rdi, 8(%rsp) ; CHECK: movq %rsi, (%rsp) - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) - %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9) - %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10) - %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) + %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10) + %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11) + %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12) ; CHECK: callq ; This is the key check. There should NOT be any memory moves here ; CHECK-NOT: movq - %safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1) - %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11) - %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10) - %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9) + %safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1) + %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12) + %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11) + %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10) ; CHECK: callq ret i32 1 } @@ -37,17 +37,17 @@ define i32 @reserve_first(i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrsp ; CHECK: movq %rdx, 16(%rsp) ; CHECK: movq %rdi, 8(%rsp) ; CHECK: movq %rsi, (%rsp) - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) - %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 9) - %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 10) - %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 9, i32 11) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i32 addrspace(1)* %a, i32 addrspace(1)* %b, i32 addrspace(1)* %c) + %a1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 10) + %b1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 11) + %c1 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 10, i32 12) ; CHECK: callq ; This is the key check. There should NOT be any memory moves here ; CHECK-NOT: movq - %safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 addrspace(1)* %a1, i32 0, i32 addrspace(1)* %c1, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1) - %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 11) - %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 10) - %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 9, i32 9) + %safepoint_token2 = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 addrspace(1)* %a1, i32 0, i32 addrspace(1)* %c1, i32 0, i32 0, i32 addrspace(1)* %c1, i32 addrspace(1)* %b1, i32 addrspace(1)* %a1) + %a2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 12) + %b2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 11) + %c2 = tail call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token2, i32 10, i32 10) ; CHECK: callq ret i32 1 } diff --git a/test/CodeGen/X86/statepoint-stackmap-format.ll b/test/CodeGen/X86/statepoint-stackmap-format.ll index 9593c4082ea..371af83527d 100644 --- a/test/CodeGen/X86/statepoint-stackmap-format.ll +++ b/test/CodeGen/X86/statepoint-stackmap-format.ll @@ -21,10 +21,10 @@ define i1 @test(i32 addrspace(1)* %ptr) gc "statepoint-example" { entry: %metadata1 = alloca i32 addrspace(1)*, i32 2, align 8 store i32 addrspace(1)* null, i32 addrspace(1)** %metadata1 - %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null) + %safepoint_token = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 2, i32 addrspace(1)* %ptr, i32 addrspace(1)* null, i32 addrspace(1)* %ptr, i32 addrspace(1)* null) %call1 = call zeroext i1 @llvm.experimental.gc.result.i1(i32 %safepoint_token) - %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 6, i32 6) - %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %a = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 7, i32 7) + %b = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 8, i32 8) ; ret i1 %call1 } diff --git a/test/Transforms/CodeGenPrepare/statepoint-relocate.ll b/test/Transforms/CodeGenPrepare/statepoint-relocate.ll index 1baf4abbc94..83d79b4b380 100644 --- a/test/Transforms/CodeGenPrepare/statepoint-relocate.ll +++ b/test/Transforms/CodeGenPrepare/statepoint-relocate.ll @@ -10,9 +10,9 @@ define i32 @test_sor_basic(i32* %base) gc "statepoint-example" { ; CHECK: getelementptr i32, i32* %base-new, i32 15 entry: %ptr = getelementptr i32, i32* %base, i32 15 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr) - %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr) + %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) %ret = load i32, i32* %ptr-new ret i32 %ret } @@ -20,15 +20,15 @@ entry: define i32 @test_sor_two_derived(i32* %base) gc "statepoint-example" { ; CHECK: getelementptr i32, i32* %base, i32 15 ; CHECK: getelementptr i32, i32* %base, i32 12 -; CHECK: getelementptr i32, i32* %base-new, i32 15 ; CHECK: getelementptr i32, i32* %base-new, i32 12 +; CHECK: getelementptr i32, i32* %base-new, i32 15 entry: %ptr = getelementptr i32, i32* %base, i32 15 %ptr2 = getelementptr i32, i32* %base, i32 12 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2) - %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) - %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2) + %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) + %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7) %ret = load i32, i32* %ptr-new ret i32 %ret } @@ -38,9 +38,9 @@ define i32 @test_sor_ooo(i32* %base) gc "statepoint-example" { ; CHECK: getelementptr i32, i32* %base-new, i32 15 entry: %ptr = getelementptr i32, i32* %base, i32 15 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) - %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 4) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) + %base-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 5) %ret = load i32, i32* %ptr-new ret i32 %ret } @@ -50,9 +50,9 @@ define i32 @test_sor_gep_smallint([3 x i32]* %base) gc "statepoint-example" { ; CHECK: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 2 entry: %ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 2 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr) - %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr) + %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) %ret = load i32, i32* %ptr-new ret i32 %ret } @@ -62,23 +62,23 @@ define i32 @test_sor_gep_largeint([3 x i32]* %base) gc "statepoint-example" { ; CHECK-NOT: getelementptr [3 x i32], [3 x i32]* %base-new, i32 0, i32 21 entry: %ptr = getelementptr [3 x i32], [3 x i32]* %base, i32 0, i32 21 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr) - %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 4, i32 4) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, [3 x i32]* %base, i32* %ptr) + %base-new = call [3 x i32]* @llvm.experimental.gc.relocate.p0a3i32(i32 %tok, i32 5, i32 5) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) %ret = load i32, i32* %ptr-new ret i32 %ret } define i32 @test_sor_noop(i32* %base) gc "statepoint-example" { ; CHECK: getelementptr i32, i32* %base, i32 15 -; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) -; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6) +; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) +; CHECK: call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7) entry: %ptr = getelementptr i32, i32* %base, i32 15 %ptr2 = getelementptr i32, i32* %base, i32 12 - %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2) - %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 5) - %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 4, i32 6) + %tok = call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32* %base, i32* %ptr, i32* %ptr2) + %ptr-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 6) + %ptr2-new = call i32* @llvm.experimental.gc.relocate.p0i32(i32 %tok, i32 5, i32 7) %ret = load i32, i32* %ptr-new ret i32 %ret } diff --git a/test/Transforms/InstCombine/gc.relocate.ll b/test/Transforms/InstCombine/gc.relocate.ll index 5ecde19b7a4..53782661f3d 100644 --- a/test/Transforms/InstCombine/gc.relocate.ll +++ b/test/Transforms/InstCombine/gc.relocate.ll @@ -15,7 +15,7 @@ define i32 addrspace(1)* @deref(i32 addrspace(1)* dereferenceable(8) %dparam) gc ; CHECK: call dereferenceable(8) entry: %load = load i32, i32 addrspace(1)* %dparam - %tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) - %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 4, i32 4) + %tok = tail call i32 (i1 ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i1f(i1 ()* @return_i1, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %dparam) + %relocate = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %tok, i32 5, i32 5) ret i32 addrspace(1)* %relocate } diff --git a/test/Transforms/InstCombine/statepoint.ll b/test/Transforms/InstCombine/statepoint.ll index ec991176da3..67f6e9103ad 100644 --- a/test/Transforms/InstCombine/statepoint.ll +++ b/test/Transforms/InstCombine/statepoint.ll @@ -7,8 +7,8 @@ declare void @func() define i1 @test_negative(i32 addrspace(1)* %p) gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_negative @@ -18,8 +18,8 @@ entry: define i1 @test_nonnull(i32 addrspace(1)* nonnull %p) gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* %p) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_nonnull @@ -28,8 +28,8 @@ entry: define i1 @test_null() gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* null) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* null) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_null @@ -39,8 +39,8 @@ entry: define i1 @test_undef() gc "statepoint-example" { entry: - %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 addrspace(1)* undef) - %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 4, i32 4) + %safepoint_token = tail call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @func, i32 0, i32 0, i32 0, i32 0, i32 addrspace(1)* undef) + %pnew = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(i32 %safepoint_token, i32 5, i32 5) %cmp = icmp eq i32 addrspace(1)* %pnew, null ret i1 %cmp ; CHECK-LABEL: test_undef diff --git a/test/Transforms/PlaceSafepoints/basic.ll b/test/Transforms/PlaceSafepoints/basic.ll index 4dbff586582..4559a94f3fd 100644 --- a/test/Transforms/PlaceSafepoints/basic.ll +++ b/test/Transforms/PlaceSafepoints/basic.ll @@ -73,7 +73,7 @@ define i1 @test_call_with_result() gc "statepoint-example" { ; inserted for a function that takes 1 argument. ; CHECK: gc.statepoint.p0f_isVoidf ; CHECK: gc.statepoint.p0f_i1i1f -; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0) +; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0, i32 0) ; CHECK: %call12 = call i1 @llvm.experimental.gc.result.i1 entry: %call1 = tail call i1 (i1) @i1_return_i1(i1 false) diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-1.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-1.ll index e6e5efcc26d..4bcd47d45b7 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-1.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-1.ll @@ -20,7 +20,7 @@ merge: ; CHECK-LABEL: merge: ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %here ], [ %base_obj_y, %there ] %merged_value = phi i64 addrspace(1)* [ %x, %here ], [ %y, %there ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %merged_value } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-10.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-10.ll index fa800eadc55..6f62e2fa023 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-10.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-10.ll @@ -30,7 +30,7 @@ false: merge: %next = phi i64 addrspace(1)* [ %next_x, %true ], [ %next_y, %false ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll index c7fd32e6a2e..2fc9d42ee1f 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-11.ll @@ -19,7 +19,7 @@ loop: ; preds = %loop, %entry ; CHECK-DAG: [ %next.relocated, %loop ] %current = phi i64 addrspace(1)* [ %obj, %entry ], [ %next, %loop ] %next = getelementptr i64, i64 addrspace(1)* %current, i32 1 - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-2.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-2.ll index 6509d23ca03..d1a1eca6260 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-2.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-2.ll @@ -13,7 +13,7 @@ there: merge: %merged_value = phi i64 addrspace(1)* [ %base_obj, %entry ], [ %derived_obj, %there ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %merged_value } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-3.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-3.ll index 7a80f3163b4..69bb3d7bbc8 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-3.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-3.ll @@ -12,7 +12,7 @@ loop: %current.i32 = bitcast i64 addrspace(1)* %current to i32 addrspace(1)* %next.i32 = getelementptr i32, i32 addrspace(1)* %current.i32, i32 1 %next.i64 = bitcast i32 addrspace(1)* %next.i32 to i64 addrspace(1)* - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll index 33619ad4e48..5dcb9be3108 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-4.ll @@ -13,9 +13,9 @@ entry: loop: ; CHECK: loop: -; CHECK: %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i3 +; CHECK: %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i3 ; CHECK-NEXT: %obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result - %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (i64 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i64f(i64 addrspace(1)* ()* @generate_obj, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) %obj2 = call i64 addrspace(1)* @llvm.experimental.gc.result.p1i64(i32 %safepoint_token1) switch i32 %condition, label %dest_a [ i32 0, label %dest_b @@ -37,11 +37,11 @@ merge: ; CHECK: %obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ] %obj_to_consume = phi i64 addrspace(1)* [ %obj2, %dest_a ], [ null, %dest_b ], [ null, %dest_c ] - %safepoint_token3 = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @consume_obj, i32 1, i32 0, i64 addrspace(1)* %obj_to_consume, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token3 = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @consume_obj, i32 1, i32 0, i64 addrspace(1)* %obj_to_consume, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %merge.split merge.split: ; preds = %merge - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-5.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-5.ll index 0800504e041..3ed75901c41 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-5.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-5.ll @@ -23,7 +23,7 @@ merge: ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %base_obj_y, %there ] ; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ] %merged_value = phi i64 addrspace(1)* [ %base_obj_x, %bump ], [ %y, %there ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %merged_value } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-6.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-6.ll index f286ed9d60b..fe1059dcd26 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-6.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-6.ll @@ -33,7 +33,7 @@ merge: ; CHECK: %base_phi = phi i64 addrspace(1)* [ %base_obj_x, %merge_here ], [ %base_obj_y, %there ] ; CHECK-NEXT: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ] %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %merged_value } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-7.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-7.ll index f51e1179717..d3d5a1127c2 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-7.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-7.ll @@ -44,7 +44,7 @@ merge: ; CHECK: %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ] %merged_value = phi i64 addrspace(1)* [ %x, %merge_here ], [ %y, %there ] - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @site_for_call_safpeoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %merged_value } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-8.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-8.ll index 07bc42b2ea4..47f196faeb6 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-8.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-8.ll @@ -24,7 +24,7 @@ check_for_null: loop_back: %next_element_ptr = getelementptr i64 addrspace(1)*, i64 addrspace(1)* addrspace(1)* %current_element_ptr, i32 1 %next_index = add i32 %index, 1 - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop_check not_found: diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers-9.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers-9.ll index 973ac7eaf36..6f3e5eaaa17 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers-9.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers-9.ll @@ -13,7 +13,7 @@ loop: %condition = call i1 @runtime_value() %maybe_next = getelementptr i64, i64 addrspace(1)* %current, i32 1 %next = select i1 %condition, i64 addrspace(1)* %maybe_next, i64 addrspace(1)* %current - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/base-pointers.ll b/test/Transforms/RewriteStatepointsForGC/base-pointers.ll index eab963f79f6..e88f6dfe152 100644 --- a/test/Transforms/RewriteStatepointsForGC/base-pointers.ll +++ b/test/Transforms/RewriteStatepointsForGC/base-pointers.ll @@ -16,7 +16,7 @@ loop: ; CHECK-DAG: [ %obj.relocated, %loop ] ; CHECK-DAG: [ %obj, %entry ] call void @use_obj(i64 addrspace(1)* %obj) - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } @@ -57,7 +57,7 @@ define i64 addrspace(1)* @test1(i32 %caller, i8 addrspace(1)* %a, i8 addrspace(1 ; CHECK: merge: ; CHECK-NEXT: %base_phi = phi i64 addrspace(1)* [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_L]], %left ], [ [[CAST_R]], %right ], !is_base_value !0 %value = phi i64 addrspace(1)* [ %a.cast, %left], [ %a.cast, %left], [ %a.cast, %left], [ %b.cast, %right] - %safepoint_token = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @parse_point, i32 1, i32 0, i64 addrspace(1)* %value, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i64f(void (i64 addrspace(1)*)* @parse_point, i32 1, i32 0, i64 addrspace(1)* %value, i32 0, i32 5, i32 0, i32 0, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %value } @@ -91,7 +91,7 @@ loop: ; preds = %loop, %entry %nexta = getelementptr i64, i64 addrspace(1)* %current, i32 1 %next = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2 %extra2 = select i1 %cnd, i64 addrspace(1)* %nexta, i64 addrspace(1)* %base_arg2 - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %loop } diff --git a/test/Transforms/RewriteStatepointsForGC/basics.ll b/test/Transforms/RewriteStatepointsForGC/basics.ll index 1720cc1c7a3..d5eaa85359d 100644 --- a/test/Transforms/RewriteStatepointsForGC/basics.ll +++ b/test/Transforms/RewriteStatepointsForGC/basics.ll @@ -10,7 +10,7 @@ define i8 addrspace(1)* @test1(i8 addrspace(1)* %obj) gc "statepoint-example" { ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i8 addrspace(1)* %obj } @@ -23,8 +23,8 @@ define i8 addrspace(1)* @test2(i8 addrspace(1)* %obj) gc "statepoint-example" { ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)* entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i8 addrspace(1)* %obj } @@ -39,7 +39,7 @@ define i8 @test3(i8 addrspace(1)* %obj) gc "statepoint-example" { ; CHECK-NEXT: load i8, i8 addrspace(1)* %obj.relocated entry: %derived = getelementptr i8, i8 addrspace(1)* %obj, i64 10 - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) %a = load i8, i8 addrspace(1)* %derived %b = load i8, i8 addrspace(1)* %obj @@ -57,14 +57,14 @@ taken: ; CHECK-LABEL: taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated = call coldcc i8 addrspace(1)* - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %merge untaken: ; CHECK-LABEL: untaken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated1 = call coldcc i8 addrspace(1)* - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %merge merge: @@ -81,7 +81,7 @@ define i8 addrspace(1)* @test5(i8 addrspace(1)* %obj) gc "ocaml" { ; CHECK-NEXT: gc.statepoint ; CHECK-NOT: %obj.relocated = call coldcc i8 addrspace(1)* entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i8 addrspace(1)* %obj } diff --git a/test/Transforms/RewriteStatepointsForGC/constants.ll b/test/Transforms/RewriteStatepointsForGC/constants.ll index 235e3144b88..1fdbce7323d 100644 --- a/test/Transforms/RewriteStatepointsForGC/constants.ll +++ b/test/Transforms/RewriteStatepointsForGC/constants.ll @@ -9,7 +9,7 @@ define i8 @test() gc "statepoint-example" { ; CHECK: gc.statepoint ; CHECK-NEXT: load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*) entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) %res = load i8, i8 addrspace(1)* inttoptr (i64 15 to i8 addrspace(1)*) ret i8 %res } @@ -22,7 +22,7 @@ define i8 @test2(i8 addrspace(1)* %p) gc "statepoint-example" { ; CHECK-NEXT: gc.relocate ; CHECK-NEXT: icmp entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) %cmp = icmp eq i8 addrspace(1)* %p, null br i1 %cmp, label %taken, label %not_taken @@ -52,7 +52,7 @@ define i8 @test3(i1 %always_true) gc "statepoint-example" { ; CHECK: gc.statepoint ; CHECK-NEXT: load i8, i8 addrspace(1)* @G entry: - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) %res = load i8, i8 addrspace(1)* @G, align 1 ret i8 %res } diff --git a/test/Transforms/RewriteStatepointsForGC/live-vector.ll b/test/Transforms/RewriteStatepointsForGC/live-vector.ll index bc3711ebebc..451368147a6 100644 --- a/test/Transforms/RewriteStatepointsForGC/live-vector.ll +++ b/test/Transforms/RewriteStatepointsForGC/live-vector.ll @@ -9,7 +9,7 @@ define i64 addrspace(1)* @test(i64 addrspace(1)* %obj) gc "statepoint-example" { ; CHECK-NEXT: gc.relocate ; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated entry: - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %obj } @@ -25,7 +25,7 @@ define <2 x i64 addrspace(1)*> @test2(<2 x i64 addrspace(1)*> %obj) gc "statepoi ; CHECK-NEXT: insertelement ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5 entry: - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) ret <2 x i64 addrspace(1)*> %obj } @@ -43,7 +43,7 @@ define <2 x i64 addrspace(1)*> @test3(<2 x i64 addrspace(1)*>* %ptr) gc "statepo ; CHECK-NEXT: ret <2 x i64 addrspace(1)*> %5 entry: %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) ret <2 x i64 addrspace(1)*> %obj } @@ -58,7 +58,7 @@ define <2 x i64 addrspace(1)*> @test4(<2 x i64 addrspace(1)*>* %ptr) gc "statepo ; CHECK-NEXT: gc.statepoint entry: %obj = load <2 x i64 addrspace(1)*>, <2 x i64 addrspace(1)*>* %ptr - invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) to label %normal_return unwind label %exceptional_return ; CHECK-LABEL: normal_return: diff --git a/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll b/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll index 0990c68daf9..6da6b7c189e 100644 --- a/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll +++ b/test/Transforms/RewriteStatepointsForGC/liveness-basics.ll @@ -15,7 +15,7 @@ taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* ; CHECK-NEXT: br label %merge - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge untaken: @@ -23,7 +23,7 @@ untaken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated1 = call coldcc i64 addrspace(1)* ; CHECK-NEXT: br label %merge - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge merge: @@ -40,7 +40,7 @@ entry: ; CHECK-LABEL: entry: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: br - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br i1 %cmp, label %taken, label %untaken taken: @@ -51,7 +51,7 @@ taken: ; CHECK-NEXT: ret i64 addrspace(1)* %obj.relocated %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %obj untaken: @@ -72,16 +72,16 @@ taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* ; CHECK-NEXT: br label %merge - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) %obj = load i64 addrspace(1)*, i64 addrspace(1)** %loc - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge untaken: ; CHECK-LABEL: taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: br label %merge - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge merge: @@ -106,9 +106,9 @@ entry: ; CHECK-NEXT: ret i64 addrspace(1)* %derived.relocated1 ; %derived = getelementptr i64, i64 addrspace(1)* %obj, i64 8 - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) ret i64 addrspace(1)* %derived } @@ -127,7 +127,7 @@ taken: ; CHECK-NEXT: gc.statepoint ; CHECK-NEXT: %obj.relocated = call coldcc i64 addrspace(1)* ; CHECK-NEXT: br label %merge - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %merge untaken: diff --git a/test/Transforms/RewriteStatepointsForGC/preprocess.ll b/test/Transforms/RewriteStatepointsForGC/preprocess.ll index c75d242f870..ffdfe5be350 100644 --- a/test/Transforms/RewriteStatepointsForGC/preprocess.ll +++ b/test/Transforms/RewriteStatepointsForGC/preprocess.ll @@ -16,7 +16,7 @@ next: ; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated) ; CHECK-NEXT: @consume(i64 addrspace(1)* %obj.relocated) %obj2 = phi i64 addrspace(1)* [ %obj, %entry ] - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) call void (...) @consume(i64 addrspace(1)* %obj2) call void (...) @consume(i64 addrspace(1)* %obj) ret void @@ -32,7 +32,7 @@ define void @test7() gc "statepoint-example" { unreached: %obj = phi i64 addrspace(1)* [null, %unreached] - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) call void (...) @consume(i64 addrspace(1)* %obj) br label %unreached } @@ -45,7 +45,7 @@ define void @test8() gc "statepoint-example" { ret void unreached: - invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) to label %normal_return unwind label %exceptional_return normal_return: ; preds = %entry diff --git a/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll b/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll index 73ebf2f86d6..80579e66050 100644 --- a/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll +++ b/test/Transforms/RewriteStatepointsForGC/relocate_invoke_result.ll @@ -24,7 +24,7 @@ normal_dest: ;; CHECK-LABEL: normal_dest: ;; CHECK-NEXT: gc.statepoint ;; CHECK-NEXT: %obj.relocated = call coldcc i64* addrspace(1)* - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @gc_call, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret i64* addrspace(1)* %obj } diff --git a/test/Transforms/RewriteStatepointsForGC/relocation.ll b/test/Transforms/RewriteStatepointsForGC/relocation.ll index da092ee3d24..f604885162e 100644 --- a/test/Transforms/RewriteStatepointsForGC/relocation.ll +++ b/test/Transforms/RewriteStatepointsForGC/relocation.ll @@ -9,7 +9,7 @@ entry: ; CHECK-LABEL: @test1 ; CHECK-DAG: %obj.relocated ; CHECK-DAG: %obj2.relocated - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %joint joint: @@ -61,7 +61,7 @@ loop_x: br label %loop.backedge loop.backedge: - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @do_safepoint, i32 0, i32 0, i32 0, i32 0) br label %loop loop_y: @@ -79,14 +79,14 @@ if_branch: ; CHECK-LABEL: if_branch: ; CHECK: gc.statepoint ; CHECK: gc.relocate - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %join else_branch: ; CHECK-LABEL: else_branch: ; CHECK: gc.statepoint ; CHECK: gc.relocate - %safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 0) br label %join join: @@ -109,8 +109,8 @@ entry: ; CHECK: gc.statepoint ; CHECK-NEXT: gc.relocate ; CHECK-NEXT: gc.statepoint - %safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) - %safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void (i64)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidi64f(void (i64)* undef, i32 1, i32 0, i64 undef, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token1 = call i32 (i32 (i64 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32p1i64f(i32 (i64 addrspace(1)*)* undef, i32 1, i32 0, i64 addrspace(1)* %obj, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) ret void } @@ -123,9 +123,9 @@ define void @test4() gc "statepoint-example" { ; CHECK: gc.statepoint ; CHECK: gc.relocate ; CHECK: @use(i8 addrspace(1)* %res.relocated) - %safepoint_token2 = tail call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0) + %safepoint_token2 = tail call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0) %res = call i8 addrspace(1)* @llvm.experimental.gc.result.ptr.p1i8(i32 %safepoint_token2) - call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0) + call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0) call void (...) @use(i8 addrspace(1)* %res) unreachable } @@ -135,7 +135,7 @@ define void @test4() gc "statepoint-example" { define void @test5(i8 addrspace(1)* %arg) gc "statepoint-example" { ; CHECK-LABEL: test5 entry: - call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0) + call i32 (i8 addrspace(1)* ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_p1i8f(i8 addrspace(1)* ()* undef, i32 0, i32 0, i32 0, i32 0) switch i32 undef, label %kill [ i32 10, label %merge i32 13, label %merge @@ -169,7 +169,7 @@ do_safepoint: ; CHECK: arg1.relocated = ; CHECK: arg2.relocated = ; CHECK: arg3.relocated = - call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3) + call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 3, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2, i8 addrspace(1)* %arg3) br label %gc.safepoint_poll.exit2 gc.safepoint_poll.exit2: @@ -208,7 +208,7 @@ outer-inc: ; CHECK-LABEL: outer-inc: ; CHECK: %arg1.relocated ; CHECK: %arg2.relocated - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2) br label %outer-loop } @@ -237,7 +237,7 @@ inner-loop: ; CHECK: gc.statepoint ; CHECK: %arg1.relocated ; CHECK: %arg2.relocated - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 2, i8 addrspace(1)* %arg1, i8 addrspace(1)* %arg2) br i1 %cmp, label %inner-loop, label %outer-inc outer-inc: @@ -257,7 +257,7 @@ branch2: br i1 %condition, label %callbb, label %join2 callbb: - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* @foo, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0) br label %join join: diff --git a/test/Verifier/invalid-statepoint2.ll b/test/Verifier/invalid-statepoint2.ll index e3dd9225e91..0d5c2c9baf5 100644 --- a/test/Verifier/invalid-statepoint2.ll +++ b/test/Verifier/invalid-statepoint2.ll @@ -12,8 +12,8 @@ declare i32 @"personality_function"() define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg, i32 %val) gc "statepoint-example" { entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 %val, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11) ret i64 addrspace(1)* %reloc } diff --git a/test/Verifier/statepoint.ll b/test/Verifier/statepoint.ll index 228bfd16d0e..7c1cb3e75ef 100644 --- a/test/Verifier/statepoint.ll +++ b/test/Verifier/statepoint.ll @@ -10,11 +10,11 @@ declare i32 @"personality_function"() define i64 addrspace(1)* @test1(i8 addrspace(1)* %arg) gc "statepoint-example" { entry: %cast = bitcast i8 addrspace(1)* %arg to i64 addrspace(1)* - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11) ;; It is perfectly legal to relocate the same value multiple times... - %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10) - %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 10, i32 9) + %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11) + %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %safepoint_token, i32 11, i32 10) ret i64 addrspace(1)* %reloc ; CHECK-LABEL: test1 ; CHECK: statepoint @@ -39,8 +39,8 @@ notequal: ret void equal: - %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) - %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 9, i32 10) + %safepoint_token = call i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 0, i32 0, i32 10, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(i32 %safepoint_token, i32 10, i32 11) call void undef(i64 addrspace(1)* %reloc) ret void ; CHECK-LABEL: test2 @@ -57,7 +57,7 @@ define i8 addrspace(1)* @test3(i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) gc entry: ; CHECK-LABEL: entry ; CHECK: statepoint - %0 = invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) + %0 = invoke i32 (void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(void ()* undef, i32 0, i32 0, i32 0, i32 5, i32 0, i32 -1, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) to label %normal_dest unwind label %exceptional_return normal_dest: @@ -65,7 +65,7 @@ normal_dest: ; CHECK: gc.relocate ; CHECK: gc.relocate ; CHECK: ret - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 9, i32 9) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10) %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %0, i32 10, i32 10) ret i8 addrspace(1)* %obj.relocated @@ -76,7 +76,7 @@ exceptional_return: %landing_pad = landingpad { i8*, i32 } personality i32 ()* @"personality_function" cleanup %relocate_token = extractvalue { i8*, i32 } %landing_pad, 1 - %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 9, i32 9) + %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10) %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(i32 %relocate_token, i32 10, i32 10) ret i8 addrspace(1)* %obj1.relocated1 } -- 2.34.1