Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -2775,6 +2775,7 @@ // Deopt bundles are lowered in LowerCallSiteWithDeoptBundle, and we don't // have to do anything here to lower funclet bundles. assert(!I.hasOperandBundlesOtherThan({LLVMContext::OB_deopt, + LLVMContext::OB_gc_transition, LLVMContext::OB_funclet, LLVMContext::OB_cfguardtarget}) && "Cannot lower invokes with arbitrary operand bundles yet!"); Index: llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -866,10 +866,26 @@ SI.GCArgs = ArrayRef(ISP.gc_args_begin(), ISP.gc_args_end()); SI.StatepointInstr = ISP.getInstruction(); - SI.GCTransitionArgs = ArrayRef(ISP.gc_transition_args_begin(), - ISP.gc_transition_args_end()); SI.ID = ISP.getID(); - SI.DeoptState = ArrayRef(ISP.deopt_begin(), ISP.deopt_end()); + + if (auto Opt = ISP.getCall()->getOperandBundle(LLVMContext::OB_deopt)) { + assert(ISP.deopt_begin() == ISP.deopt_end() && + "can't list both deopt operands and deopt bundle"); + auto &Inputs = Opt->Inputs; + SI.DeoptState = ArrayRef(Inputs.begin(), Inputs.end()); + } else { + SI.DeoptState = ArrayRef(ISP.deopt_begin(), ISP.deopt_end()); + } + if (auto Opt = ISP.getCall()->getOperandBundle(LLVMContext::OB_gc_transition)) { + assert(ISP.gc_transition_args_begin() == ISP.gc_transition_args_end() && + "can't list both gc_transition operands and bundle"); + auto &Inputs = Opt->Inputs; + SI.GCTransitionArgs = ArrayRef(Inputs.begin(), Inputs.end()); + } else { + SI.GCTransitionArgs = ArrayRef(ISP.gc_transition_args_begin(), + ISP.gc_transition_args_end()); + } + SI.StatepointFlags = ISP.getFlags(); SI.NumPatchBytes = ISP.getNumPatchBytes(); SI.EHPadBB = EHPadBB; Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -2085,6 +2085,13 @@ "gc.statepoint number of transition arguments must be positive", Call); const int EndTransitionArgsInx = EndCallArgsInx + 1 + NumTransitionArgs; + // We're migrating away from inline operands to operand bundles, enforce + // the either/or property during transition. + if (Call.getOperandBundle(LLVMContext::OB_gc_transition)) { + Assert(NumTransitionArgs == 0, + "can't use both deopt operands and deopt bundle on a statepoint"); + } + const Value *NumDeoptArgsV = Call.getArgOperand(EndTransitionArgsInx + 1); Assert(isa(NumDeoptArgsV), "gc.statepoint number of deoptimization arguments " @@ -2096,6 +2103,13 @@ "must be positive", Call); + // We're migrating away from inline operands to operand bundles, enforce + // the either/or property during transition. + if (Call.getOperandBundle(LLVMContext::OB_deopt)) { + Assert(NumDeoptArgs == 0, + "can't use both deopt operands and deopt bundle on a statepoint"); + } + const int ExpectedNumArgs = 7 + NumCallArgs + NumTransitionArgs + NumDeoptArgs; Assert(ExpectedNumArgs <= (int)Call.arg_size(), Index: llvm/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll =================================================================== --- llvm/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll +++ llvm/test/CodeGen/X86/statepoint-gctransition-call-lowering.ll @@ -116,6 +116,21 @@ ret i32 %call1 } +; Same as test_transition_args_2 except using bundle format +define i32 @test_bundle() gc "statepoint-example" { +; CHECK-LABEL: test_bundle +; CHECK: pushq %rax +; CHECK: callq return_i32 +; CHECK: popq %rcx +; CHECK: retq +entry: + %val = alloca i32 + %arg = alloca i8 + %safepoint_token = call token (i64, i32, i32 (i32, i8*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_i32i32p0i8f(i64 0, i32 0, i32 (i32, i8*)* @return_i32_with_args, i32 2, i32 1, i32 0, i8* %arg, i32 0, i32 0) ["gc-transition" (i32* %val, i64 42)] + %call1 = call i32 @llvm.experimental.gc.result.i32(token %safepoint_token) + ret i32 %call1 +} + declare token @llvm.experimental.gc.statepoint.p0f_i1f(i64, i32, i1 ()*, i32, i32, ...) declare i1 @llvm.experimental.gc.result.i1(token) Index: llvm/test/CodeGen/X86/statepoint-regs.ll =================================================================== --- llvm/test/CodeGen/X86/statepoint-regs.ll +++ llvm/test/CodeGen/X86/statepoint-regs.ll @@ -691,6 +691,23 @@ %out = call coldcc i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %statepoint_token, i32 27, i32 27) ret i32 addrspace(1)* %out } + +; Same as test1, but using deopt bundle +define void @test1b(i32 %a) gc "statepoint-example" { +; CHECK-LABEL: test1b: +; CHECK: ## %bb.0: ## %entry +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movl %edi, {{[-0-9]+}}(%r{{[sb]}}p) ## 4-byte Spill +; CHECK-NEXT: callq _bar ## 4-byte Folded Reload +; CHECK-NEXT: Ltmp19: +; CHECK-NEXT: popq %rax +; CHECK-NEXT: retq +entry: + %statepoint_token1 = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* @bar, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 %a)] + ret void +} + ; CHECK-LABEL: __LLVM_StackMaps: ; CHECK: .long Ltmp18-_test_fpconst_deopt ; CHECK-NEXT: .short 0