diff --git a/llvm/docs/LangRef.rst b/llvm/docs/LangRef.rst --- a/llvm/docs/LangRef.rst +++ b/llvm/docs/LangRef.rst @@ -2182,6 +2182,12 @@ generated code. For more details, see :ref:`GC Transitions `. +The bundle 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. + .. _assume_opbundles: Assume Operand Bundles diff --git a/llvm/docs/Statepoints.rst b/llvm/docs/Statepoints.rst --- a/llvm/docs/Statepoints.rst +++ b/llvm/docs/Statepoints.rst @@ -449,8 +449,7 @@ func_type , i64 <#call args>, i64 , ... (call parameters), - i64 <# transition args>, ... (transition parameters), - i64 <# deopt args>, ... (deopt parameters), + i64 0, i64 0, ... (gc parameters)) Overview: @@ -515,17 +514,11 @@ 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 '# deopt args' field -indicates how many operands are to be interpreted as 'deopt parameters'. +The 'call parameter' attributes must be followed by two 'i64 0' constants. +These were originally the length prefixes for 'gc transition parameter' and +'deopt parameter' arguments, but the role of these parameter sets have been +entirely replaced with the corresponding operand bundles. In a future +revision, these now redundant arguments will be removed. The 'gc parameters' arguments contain every pointer to a garbage collector object which potentially needs to be updated by the garbage @@ -676,13 +669,12 @@ these identifiers. * Constant which describes the flags passed to the statepoint intrinsic * Constant which describes number of following deopt *Locations* (not - operands) -* Variable number of Locations, one for each deopt parameter listed in - the IR statepoint (same number as described by previous Constant). At - the moment, only deopt parameters with a bitwidth of 64 bits or less - are supported. Values of a type larger than 64 bits can be specified - and reported only if a) the value is constant at the call site, and b) - the constant can be represented with less than 64 bits (assuming zero + operands). Will be 0 if no "deopt" bundle is provided. +* Variable number of Locations, one for each deopt parameter listed in the + "deopt" operand bundle. At the moment, only deopt parameters with a bitwidth + of 64 bits or less are supported. Values of a type larger than 64 bits can be + specified and reported only if a) the value is constant at the call site, and + b) the constant can be represented with less than 64 bits (assuming zero extension to the original bitwidth). * Variable number of relocation records, each of which consists of exactly two Locations. Relocation records are described in detail diff --git a/llvm/lib/CodeGen/TargetInstrInfo.cpp b/llvm/lib/CodeGen/TargetInstrInfo.cpp --- a/llvm/lib/CodeGen/TargetInstrInfo.cpp +++ b/llvm/lib/CodeGen/TargetInstrInfo.cpp @@ -499,19 +499,14 @@ // Return false if any operands requested for folding are not foldable (not // part of the stackmap's live values). for (unsigned Op : Ops) { + // Caller is expected to avoid passing in tied operands + assert(!MI.getOperand(Op).isTied()); if (Op < NumDefs) { assert(DefToFoldIdx == MI.getNumOperands() && "Folding multiple defs"); DefToFoldIdx = Op; } else if (Op < StartIdx) { return nullptr; } - // When called from regalloc (InlineSpiller), operands must be untied, - // and regalloc will take care of (re)loading operand from memory. - // But when called from other places (e.g. peephole pass), - // we cannot fold operand which are tied - callers are unaware they - // need to reload destination register. - if (MI.getOperand(Op).isTied()) - return nullptr; } MachineInstr *NewMI = diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -2123,34 +2123,18 @@ Call); const int NumTransitionArgs = cast(NumTransitionArgsV)->getZExtValue(); - Assert(NumTransitionArgs >= 0, - "gc.statepoint number of transition arguments must be positive", Call); + Assert(NumTransitionArgs == 0, + "gc.statepoint w/inline transition bundle is deprecated", 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 " "must be constant integer", Call); const int NumDeoptArgs = cast(NumDeoptArgsV)->getZExtValue(); - Assert(NumDeoptArgs >= 0, - "gc.statepoint number of deoptimization arguments " - "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"); - } + Assert(NumDeoptArgs == 0, + "gc.statepoint w/inline deopt operands is deprecated", Call); const int ExpectedNumArgs = 7 + NumCallArgs + NumTransitionArgs + NumDeoptArgs; diff --git a/llvm/test/Verifier/statepoint.ll b/llvm/test/Verifier/statepoint.ll --- a/llvm/test/Verifier/statepoint.ll +++ b/llvm/test/Verifier/statepoint.ll @@ -11,11 +11,11 @@ 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 token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, 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(token %safepoint_token, i32 12, i32 13) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) ["deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)] + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 7, i32 8) ;; It is perfectly legal to relocate the same value multiple times... - %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 12, i32 13) - %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 13, i32 12) + %reloc2 = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 7, i32 8) + %reloc3 = call i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %safepoint_token, i32 8, i32 7) ret i64 addrspace(1)* %reloc ; CHECK-LABEL: test1 ; CHECK: statepoint @@ -40,8 +40,8 @@ ret void equal: - %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, 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(token %safepoint_token, i32 12, i32 13) + %safepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %arg, i64 addrspace(1)* %cast, i8 addrspace(1)* %arg, i8 addrspace(1)* %arg) ["deopt" (i32 0, i32 0, i32 0, i32 10, i32 0)] + %reloc = call i64 addrspace(1)* @llvm.experimental.gc.relocate.p1i64(token %safepoint_token, i32 7, i32 7) call void undef(i64 addrspace(1)* %reloc) ret void ; CHECK-LABEL: test2 @@ -58,7 +58,7 @@ entry: ; CHECK-LABEL: entry ; CHECK: statepoint - %0 = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, 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) + %0 = invoke token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* undef, i32 0, i32 0, i32 0, i32 0, i8 addrspace(1)* %obj, i8 addrspace(1)* %obj1) ["deopt" (i32 0, i32 -1, i32 0, i32 0, i32 0)] to label %normal_dest unwind label %exceptional_return normal_dest: @@ -66,8 +66,8 @@ ; CHECK: gc.relocate ; CHECK: gc.relocate ; CHECK: ret - %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) - %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 12, i32 12) + %obj.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 7, i32 7) + %obj1.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 8, i32 8) ret i8 addrspace(1)* %obj.relocated exceptional_return: @@ -76,8 +76,8 @@ ; CHECK: gc.relocate %landing_pad = landingpad token cleanup - %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) - %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 12, i32 12) + %obj.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 7, i32 7) + %obj1.relocated1 = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %landing_pad, i32 8, i32 8) ret i8 addrspace(1)* %obj1.relocated1 }