Index: llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -64,6 +64,10 @@ "use-registers-for-deopt-values", cl::Hidden, cl::init(false), cl::desc("Allow using registers for non pointer deopt args")); +cl::opt UseRegistersForDeadGCDeoptValues( + "use-registers-for-dead-gc-deopt-values", cl::Hidden, cl::init(true), + cl::desc("Use registers for pointer deopt args missing in gc section")); + cl::opt UseRegistersForGCPointersInLandingPad( "use-registers-for-gc-values-in-landing-pad", cl::Hidden, cl::init(false), cl::desc("Allow using registers for gc pointer in landing pad")); @@ -618,8 +622,13 @@ }; auto requireSpillSlot = [&](const Value *V) { - if (isGCValue(V)) - return !LowerAsVReg.count(Builder.getValue(V)); + if (isGCValue(V)) { + SDValue SDV = Builder.getValue(V); + if (LoweredGCPtrs.count(SDV)) + return false; + return !UseRegistersForDeadGCDeoptValues || !MaxVRegPtrs || + !canPassGCPtrOnVReg(SDV); + } return !(LiveInDeopt || UseRegistersForDeoptValues); }; Index: llvm/test/CodeGen/X86/statepoint-vreg-dead-gc-deopt.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/statepoint-vreg-dead-gc-deopt.ll @@ -0,0 +1,40 @@ +; This file contains some of the same basic tests as statepoint-vreg.ll, but +; focuses on examining the intermediate representation. It's separate so that +; the main file is easy to update with update_llc_test_checks.py + +; This run is to demonstrate what MIR SSA looks like. +; RUN: llc -use-registers-for-dead-gc-deopt-values=true -max-registers-for-gc-values=4 -stop-after finalize-isel < %s | FileCheck --check-prefix=CHECK-VREG %s +; This run is to demonstrate register allocator work. +; RUN: llc -use-registers-for-dead-gc-deopt-values=true -max-registers-for-gc-values=4 -stop-after virtregrewriter < %s | FileCheck --check-prefix=CHECK-PREG %s + +target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +declare dso_local void @func() +declare dso_local void @consume(i32 addrspace(1)*) + +; deopt GC pointer not present in GC args can use register. +define void @test_deopt_gcpointer(i32 addrspace(1)* %a, i32 addrspace(1)* %b) gc "statepoint-example" { +; CHECK-VREG-LABEL: name: test_deopt_gcpointer +; CHECK-VREG: %1:gr64 = COPY $rsi +; CHECK-VREG: %0:gr64 = COPY $rdi +; CHECK-VREG: %2:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, %0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp +; CHECK-VREG: $rdi = COPY %2 +; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp +; CHECK-VREG: RET 0 + +; CHECK-PREG-LABEL: name: test_deopt_gcpointer +; CHECK-PREG: renamable $rbx = COPY $rsi +; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, killed renamable $rdi, 2, 1, killed renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp +; CHECK-PREG: $rdi = COPY killed renamable $rbx +; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp + + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @func, i32 0, i32 0, i32 0, i32 0) ["deopt" (i32 addrspace(1)* %a), "gc-live" (i32 addrspace(1)* %b)] + %rel = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) + call void @consume(i32 addrspace(1)* %rel) + ret void +} + +declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64, i32, void ()*, i32, i32, ...) +declare dso_local i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32) + Index: llvm/test/CodeGen/X86/statepoint-vreg-details.ll =================================================================== --- llvm/test/CodeGen/X86/statepoint-vreg-details.ll +++ llvm/test/CodeGen/X86/statepoint-vreg-details.ll @@ -3,9 +3,9 @@ ; the main file is easy to update with update_llc_test_checks.py ; This run is to demonstrate what MIR SSA looks like. -; RUN: llc -max-registers-for-gc-values=4 -stop-after finalize-isel < %s | FileCheck --check-prefix=CHECK-VREG %s +; RUN: llc -use-registers-for-dead-gc-deopt-values=false -max-registers-for-gc-values=4 -stop-after finalize-isel < %s | FileCheck --check-prefix=CHECK-VREG %s ; This run is to demonstrate register allocator work. -; RUN: llc -max-registers-for-gc-values=4 -stop-after virtregrewriter < %s | FileCheck --check-prefix=CHECK-PREG %s +; RUN: llc -use-registers-for-dead-gc-deopt-values=false -max-registers-for-gc-values=4 -stop-after virtregrewriter < %s | FileCheck --check-prefix=CHECK-PREG %s target datalayout = "e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu"