Skip to content

Commit 65fb706

Browse files
author
Serguei Katkov
committed
[Statepoint Lowering] Consider dead deopt gc values together with other gc values
Currently dead gc value mentioned in the deopt section are not listed in gc section and so are processed separately. With this CL all deopt gc values are considered as base pointers and processed in the same way as other gc values. The fact that deopt gc pointer is a base pointer was used all the time but it is explicitly documented here by putting the value in SI.Base. The idea of the patch comes from Philip Reames. Reviewers: reames, dantrushin Reviewed By: reames Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D97554
1 parent 99c24f7 commit 65fb706

File tree

4 files changed

+48
-26
lines changed

4 files changed

+48
-26
lines changed

llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,18 @@ lowerIncomingStatepointValue(SDValue Incoming, bool RequireSpillSlot,
489489

490490
}
491491

492+
/// Return true if value V represents the GC value. The behavior is conservative
493+
/// in case it is not sure that value is not GC the function returns true.
494+
static bool isGCValue(const Value *V, SelectionDAGBuilder &Builder) {
495+
auto *Ty = V->getType();
496+
if (!Ty->isPtrOrPtrVectorTy())
497+
return false;
498+
if (auto *GFI = Builder.GFI)
499+
if (auto IsManaged = GFI->getStrategy().isGCManagedPointer(Ty))
500+
return *IsManaged;
501+
return true; // conservative
502+
}
503+
492504
/// Lower deopt state and gc pointer arguments of the statepoint. The actual
493505
/// lowering is described in lowerIncomingStatepointValue. This function is
494506
/// responsible for lowering everything in the right position and playing some
@@ -607,21 +619,11 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
607619

608620
LLVM_DEBUG(dbgs() << LowerAsVReg.size() << " pointers will go in vregs\n");
609621

610-
auto isGCValue = [&](const Value *V) {
611-
auto *Ty = V->getType();
612-
if (!Ty->isPtrOrPtrVectorTy())
613-
return false;
614-
if (auto *GFI = Builder.GFI)
615-
if (auto IsManaged = GFI->getStrategy().isGCManagedPointer(Ty))
616-
return *IsManaged;
617-
return true; // conservative
618-
};
619-
620622
auto requireSpillSlot = [&](const Value *V) {
621623
if (!Builder.DAG.getTargetLoweringInfo().isTypeLegal(
622624
Builder.getValue(V).getValueType()))
623625
return true;
624-
if (isGCValue(V))
626+
if (isGCValue(V, Builder))
625627
return !LowerAsVReg.count(Builder.getValue(V));
626628
return !(LiveInDeopt || UseRegistersForDeoptValues);
627629
};
@@ -730,8 +732,7 @@ SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
730732
NumOfStatepoints++;
731733
// Clear state
732734
StatepointLowering.startNewStatepoint(*this);
733-
assert(SI.Bases.size() == SI.Ptrs.size() &&
734-
SI.Ptrs.size() <= SI.GCRelocates.size());
735+
assert(SI.Bases.size() == SI.Ptrs.size());
735736

736737
LLVM_DEBUG(dbgs() << "Lowering statepoint " << *SI.StatepointInstr << "\n");
737738
#ifndef NDEBUG
@@ -1045,6 +1046,21 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
10451046
}
10461047
}
10471048

1049+
// If we find a deopt value which isn't explicitly added, we need to
1050+
// ensure it gets lowered such that gc cycles occurring before the
1051+
// deoptimization event during the lifetime of the call don't invalidate
1052+
// the pointer we're deopting with. Note that we assume that all
1053+
// pointers passed to deopt are base pointers; relaxing that assumption
1054+
// would require relatively large changes to how we represent relocations.
1055+
for (Value *V : I.deopt_operands()) {
1056+
if (!isGCValue(V, *this))
1057+
continue;
1058+
if (Seen.insert(getValue(V)).second) {
1059+
SI.Bases.push_back(V);
1060+
SI.Ptrs.push_back(V);
1061+
}
1062+
}
1063+
10481064
SI.GCArgs = ArrayRef<const Use>(I.gc_args_begin(), I.gc_args_end());
10491065
SI.StatepointInstr = &I;
10501066
SI.ID = I.getID();

llvm/test/CodeGen/X86/statepoint-vreg-details.ll

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,15 @@ define void @test_deopt_gcpointer(i32 addrspace(1)* %a, i32 addrspace(1)* %b) gc
135135
; CHECK-VREG-LABEL: name: test_deopt_gcpointer
136136
; CHECK-VREG: %1:gr64 = COPY $rsi
137137
; CHECK-VREG: %0:gr64 = COPY $rdi
138-
; CHECK-VREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, %0 :: (store 8 into %stack.0)
139-
; CHECK-VREG: %2:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0)
138+
; CHECK-VREG: %2:gr64, %3:gr64 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, %0, 2, 2, %1(tied-def 0), %0(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp
140139
; CHECK-VREG: $rdi = COPY %2
141140
; CHECK-VREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
142141
; CHECK-VREG: RET 0
143142

144143
; CHECK-PREG-LABEL: name: test_deopt_gcpointer
145144
; CHECK-PREG: renamable $rbx = COPY $rsi
146-
; CHECK-PREG: MOV64mr %stack.0, 1, $noreg, 0, $noreg, killed renamable $rdi :: (store 8 into %stack.0)
147-
; CHECK-PREG: renamable $rbx = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 1, killed renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp :: (volatile load store 8 on %stack.0)
145+
; CHECK-PREG: renamable $r14 = COPY $rdi
146+
; CHECK-PREG: renamable $rbx, dead renamable $r14 = STATEPOINT 0, 0, 0, @func, 2, 0, 2, 0, 2, 1, killed renamable $r14, 2, 2, killed renamable $rbx(tied-def 0), renamable $r14(tied-def 1), 2, 0, 2, 2, 0, 0, 1, 1, csr_64, implicit-def $rsp, implicit-def $ssp
148147
; CHECK-PREG: $rdi = COPY killed renamable $rbx
149148
; CHECK-PREG: CALL64pcrel32 @consume, csr_64, implicit $rsp, implicit $ssp, implicit $rdi, implicit-def $rsp, implicit-def $ssp
150149

llvm/test/CodeGen/X86/statepoint-vreg-invoke.ll

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,11 +126,13 @@ define void @test_duplicate_ir_values() gc "statepoint-example" personality i32*
126126
; CHECK: STATEPOINT 1, 16, 5, undef renamable $rax, undef $edi, undef $rsi, undef $edx, undef $ecx, undef $r8d, 2, 0, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp, implicit-def dead $eax :: (volatile load store 8 on %stack.0)
127127
; CHECK: JMP_1 %bb.1
128128
; CHECK: bb.1.normal_continue:
129+
; CHECK: renamable $rbx = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)
129130
; CHECK: $edi = MOV32ri 10
130-
; CHECK: STATEPOINT 2882400000, 0, 1, target-flags(x86-plt) @__llvm_deoptimize, killed $edi, 2, 0, 2, 2, 2, 2, 1, 8, %stack.0, 0, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp
131+
; CHECK: dead renamable $rbx = STATEPOINT 2882400000, 0, 1, target-flags(x86-plt) @__llvm_deoptimize, killed $edi, 2, 0, 2, 2, 2, 2, killed renamable $rbx, renamable $rbx, 2, 1, renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
131132
; CHECK: bb.2.exceptional_return (landing-pad):
133+
; CHECK: renamable $rbx = MOV64rm %stack.0, 1, $noreg, 0, $noreg :: (load 8 from %stack.0)
132134
; CHECK: $edi = MOV32ri -271
133-
; CHECK: STATEPOINT 2882400000, 0, 1, target-flags(x86-plt) @__llvm_deoptimize, killed $edi, 2, 0, 2, 0, 2, 1, 1, 8, %stack.0, 0, 2, 0, 2, 0, 2, 0, csr_64, implicit-def $rsp, implicit-def $ssp
135+
; CHECK: dead renamable $rbx = STATEPOINT 2882400000, 0, 1, target-flags(x86-plt) @__llvm_deoptimize, killed $edi, 2, 0, 2, 0, 2, 1, killed renamable $rbx, 2, 1, renamable $rbx(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp
134136
entry:
135137
%val1 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* undef, align 8
136138
%val2 = load i8 addrspace(1)*, i8 addrspace(1)* addrspace(1)* undef, align 8

llvm/test/CodeGen/X86/statepoint-vreg.ll

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -159,24 +159,29 @@ define void @test_base_derived(i32 addrspace(1)* %base, i32 addrspace(1)* %deriv
159159
ret void
160160
}
161161

162-
; deopt GC pointer not present in GC args must be spilled
162+
; deopt GC pointer not present in GC args goes on reg.
163163
define void @test_deopt_gcpointer(i32 addrspace(1)* %a, i32 addrspace(1)* %b) gc "statepoint-example" {
164164
; CHECK-LABEL: test_deopt_gcpointer:
165165
; CHECK: # %bb.0:
166-
; CHECK-NEXT: pushq %rbx
166+
; CHECK-NEXT: pushq %r14
167167
; CHECK-NEXT: .cfi_def_cfa_offset 16
168-
; CHECK-NEXT: subq $16, %rsp
168+
; CHECK-NEXT: pushq %rbx
169+
; CHECK-NEXT: .cfi_def_cfa_offset 24
170+
; CHECK-NEXT: pushq %rax
169171
; CHECK-NEXT: .cfi_def_cfa_offset 32
170-
; CHECK-NEXT: .cfi_offset %rbx, -16
172+
; CHECK-NEXT: .cfi_offset %rbx, -24
173+
; CHECK-NEXT: .cfi_offset %r14, -16
171174
; CHECK-NEXT: movq %rsi, %rbx
172-
; CHECK-NEXT: movq %rdi, {{[0-9]+}}(%rsp)
175+
; CHECK-NEXT: movq %rdi, %r14
173176
; CHECK-NEXT: callq func
174177
; CHECK-NEXT: .Ltmp4:
175178
; CHECK-NEXT: movq %rbx, %rdi
176179
; CHECK-NEXT: callq consume
177-
; CHECK-NEXT: addq $16, %rsp
178-
; CHECK-NEXT: .cfi_def_cfa_offset 16
180+
; CHECK-NEXT: addq $8, %rsp
181+
; CHECK-NEXT: .cfi_def_cfa_offset 24
179182
; CHECK-NEXT: popq %rbx
183+
; CHECK-NEXT: .cfi_def_cfa_offset 16
184+
; CHECK-NEXT: popq %r14
180185
; CHECK-NEXT: .cfi_def_cfa_offset 8
181186
; CHECK-NEXT: retq
182187
%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)]

0 commit comments

Comments
 (0)