forked from OSchip/llvm-project
[Statepoint Lowering] Fix the crash with gc.relocate in a separate block
If it was decided to relocate derived pointer using the spill its value is not exported in general case. When gc.relocate is located in an another block than a statepoint we cannot get SD for derived value but for spill case it is not required at all. However implementation of gc.relocate lowering unconditionally request SD value causing the assert triggering. The CL fixes this by handling spill case earlier than SD is really required. Reviewers: reames, dantrushin Reviewed By: dantrushin Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D98324
This commit is contained in:
parent
7d0cafba96
commit
2fccd1b00a
|
@ -1210,7 +1210,40 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
|
|||
setValue(&Relocate, Relocation);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (Record.type == RecordType::Spill) {
|
||||
unsigned Index = Record.payload.FI;
|
||||
SDValue SpillSlot = DAG.getTargetFrameIndex(Index, getFrameIndexTy());
|
||||
|
||||
// All the reloads are independent and are reading memory only modified by
|
||||
// statepoints (i.e. no other aliasing stores); informing SelectionDAG of
|
||||
// this this let's CSE kick in for free and allows reordering of
|
||||
// instructions if possible. The lowering for statepoint sets the root,
|
||||
// so this is ordering all reloads with the either
|
||||
// a) the statepoint node itself, or
|
||||
// b) the entry of the current block for an invoke statepoint.
|
||||
const SDValue Chain = DAG.getRoot(); // != Builder.getRoot()
|
||||
|
||||
auto &MF = DAG.getMachineFunction();
|
||||
auto &MFI = MF.getFrameInfo();
|
||||
auto PtrInfo = MachinePointerInfo::getFixedStack(MF, Index);
|
||||
auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
|
||||
MFI.getObjectSize(Index),
|
||||
MFI.getObjectAlign(Index));
|
||||
|
||||
auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
|
||||
Relocate.getType());
|
||||
|
||||
SDValue SpillLoad =
|
||||
DAG.getLoad(LoadVT, getCurSDLoc(), Chain, SpillSlot, LoadMMO);
|
||||
PendingLoads.push_back(SpillLoad.getValue(1));
|
||||
|
||||
assert(SpillLoad.getNode());
|
||||
setValue(&Relocate, SpillLoad);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Record.type == RecordType::NoRelocate);
|
||||
SDValue SD = getValue(DerivedPtr);
|
||||
|
||||
if (SD.isUndef() && SD.getValueType().getSizeInBits() <= 64) {
|
||||
|
@ -1220,43 +1253,9 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// We didn't need to spill these special cases (constants and allocas).
|
||||
// See the handling in spillIncomingValueForStatepoint for detail.
|
||||
if (Record.type == RecordType::NoRelocate) {
|
||||
setValue(&Relocate, SD);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(Record.type == RecordType::Spill);
|
||||
|
||||
unsigned Index = Record.payload.FI;;
|
||||
SDValue SpillSlot = DAG.getTargetFrameIndex(Index, getFrameIndexTy());
|
||||
|
||||
// All the reloads are independent and are reading memory only modified by
|
||||
// statepoints (i.e. no other aliasing stores); informing SelectionDAG of
|
||||
// this this let's CSE kick in for free and allows reordering of instructions
|
||||
// if possible. The lowering for statepoint sets the root, so this is
|
||||
// ordering all reloads with the either a) the statepoint node itself, or b)
|
||||
// the entry of the current block for an invoke statepoint.
|
||||
const SDValue Chain = DAG.getRoot(); // != Builder.getRoot()
|
||||
|
||||
auto &MF = DAG.getMachineFunction();
|
||||
auto &MFI = MF.getFrameInfo();
|
||||
auto PtrInfo = MachinePointerInfo::getFixedStack(MF, Index);
|
||||
auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
|
||||
MFI.getObjectSize(Index),
|
||||
MFI.getObjectAlign(Index));
|
||||
|
||||
auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
|
||||
Relocate.getType());
|
||||
|
||||
SDValue SpillLoad = DAG.getLoad(LoadVT, getCurSDLoc(), Chain,
|
||||
SpillSlot, LoadMMO);
|
||||
PendingLoads.push_back(SpillLoad.getValue(1));
|
||||
|
||||
assert(SpillLoad.getNode());
|
||||
setValue(&Relocate, SpillLoad);
|
||||
setValue(&Relocate, SD);
|
||||
}
|
||||
|
||||
void SelectionDAGBuilder::LowerDeoptimizeCall(const CallInst *CI) {
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: llc -verify-machineinstrs < %s | FileCheck %s
|
||||
|
||||
; Check that we can handle gc.relocate in a separate block in spill mode.
|
||||
|
||||
target triple = "x86_64-pc-linux-gnu"
|
||||
|
||||
declare void @"some_call"(i8 addrspace(1)*)
|
||||
declare i32 @"personality_function"()
|
||||
|
||||
; CHECK-LABEL: test_invoke:
|
||||
define i8 addrspace(1)* @test_invoke(i8 addrspace(1)* %a, i8 addrspace(1)* %b, i8 addrspace(1)* %c, i8 addrspace(1)* %d, i8 addrspace(1)* %e, i8 addrspace(1)* %f, i8 addrspace(1)* %g, i8 addrspace(1)* %h, i8 addrspace(1)* %j, i8 addrspace(1)* %k, i8 addrspace(1)* %l, i8 addrspace(1)* %m, i8 addrspace(1)* %n, i8 addrspace(1)* %o, i8 addrspace(1)* %p, i8 addrspace(1)* %q, i8 addrspace(1)* %r, i8 addrspace(1)* %s, i8 addrspace(1)* %t)
|
||||
gc "statepoint-example" personality i32 ()* @"personality_function" {
|
||||
entry:
|
||||
%0 = invoke token (i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64 0, i32 0, void (i8 addrspace(1)*)* @some_call, i32 1, i32 0, i8 addrspace(1)* %t, i32 0, i32 0) ["gc-live" (i8 addrspace(1)* %t)]
|
||||
to label %invoke_safepoint_normal_dest unwind label %exceptional_return
|
||||
|
||||
invoke_safepoint_normal_dest:
|
||||
%t.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %t.relocated
|
||||
|
||||
exceptional_return:
|
||||
%landing_pad = landingpad token
|
||||
cleanup
|
||||
ret i8 addrspace(1)* null
|
||||
}
|
||||
|
||||
; CHECK-LABEL: test_call:
|
||||
define i8 addrspace(1)* @test_call(i8 addrspace(1)* %a, i8 addrspace(1)* %b, i8 addrspace(1)* %c, i8 addrspace(1)* %d, i8 addrspace(1)* %e, i8 addrspace(1)* %f, i8 addrspace(1)* %g, i8 addrspace(1)* %h, i8 addrspace(1)* %j, i8 addrspace(1)* %k, i8 addrspace(1)* %l, i8 addrspace(1)* %m, i8 addrspace(1)* %n, i8 addrspace(1)* %o, i8 addrspace(1)* %p, i8 addrspace(1)* %q, i8 addrspace(1)* %r, i8 addrspace(1)* %s, i8 addrspace(1)* %t)
|
||||
gc "statepoint-example" personality i32 ()* @"personality_function" {
|
||||
entry:
|
||||
%0 = call token (i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64 0, i32 0, void (i8 addrspace(1)*)* @some_call, i32 1, i32 0, i8 addrspace(1)* %t, i32 0, i32 0) ["gc-live" (i8 addrspace(1)* %t)]
|
||||
br label %other_block
|
||||
|
||||
other_block:
|
||||
%t.relocated = call coldcc i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token %0, i32 0, i32 0)
|
||||
ret i8 addrspace(1)* %t.relocated
|
||||
}
|
||||
declare token @llvm.experimental.gc.statepoint.p0f_isVoidp1i8f(i64, i32, void (i8 addrspace(1)*)*, i32, i32, ...)
|
||||
declare i8 addrspace(1)* @llvm.experimental.gc.relocate.p1i8(token, i32, i32)
|
Loading…
Reference in New Issue