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
|
@ -1211,34 +1211,17 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue SD = getValue(DerivedPtr);
|
if (Record.type == RecordType::Spill) {
|
||||||
|
unsigned Index = Record.payload.FI;
|
||||||
if (SD.isUndef() && SD.getValueType().getSizeInBits() <= 64) {
|
|
||||||
// Lowering relocate(undef) as arbitrary constant. Current constant value
|
|
||||||
// is chosen such that it's unlikely to be a valid pointer.
|
|
||||||
setValue(&Relocate, DAG.getTargetConstant(0xFEFEFEFE, SDLoc(SD), MVT::i64));
|
|
||||||
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());
|
SDValue SpillSlot = DAG.getTargetFrameIndex(Index, getFrameIndexTy());
|
||||||
|
|
||||||
// All the reloads are independent and are reading memory only modified by
|
// All the reloads are independent and are reading memory only modified by
|
||||||
// statepoints (i.e. no other aliasing stores); informing SelectionDAG of
|
// statepoints (i.e. no other aliasing stores); informing SelectionDAG of
|
||||||
// this this let's CSE kick in for free and allows reordering of instructions
|
// this this let's CSE kick in for free and allows reordering of
|
||||||
// if possible. The lowering for statepoint sets the root, so this is
|
// instructions if possible. The lowering for statepoint sets the root,
|
||||||
// ordering all reloads with the either a) the statepoint node itself, or b)
|
// so this is ordering all reloads with the either
|
||||||
// the entry of the current block for an invoke statepoint.
|
// a) the statepoint node itself, or
|
||||||
|
// b) the entry of the current block for an invoke statepoint.
|
||||||
const SDValue Chain = DAG.getRoot(); // != Builder.getRoot()
|
const SDValue Chain = DAG.getRoot(); // != Builder.getRoot()
|
||||||
|
|
||||||
auto &MF = DAG.getMachineFunction();
|
auto &MF = DAG.getMachineFunction();
|
||||||
|
@ -1251,12 +1234,28 @@ void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
|
||||||
auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
|
auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
|
||||||
Relocate.getType());
|
Relocate.getType());
|
||||||
|
|
||||||
SDValue SpillLoad = DAG.getLoad(LoadVT, getCurSDLoc(), Chain,
|
SDValue SpillLoad =
|
||||||
SpillSlot, LoadMMO);
|
DAG.getLoad(LoadVT, getCurSDLoc(), Chain, SpillSlot, LoadMMO);
|
||||||
PendingLoads.push_back(SpillLoad.getValue(1));
|
PendingLoads.push_back(SpillLoad.getValue(1));
|
||||||
|
|
||||||
assert(SpillLoad.getNode());
|
assert(SpillLoad.getNode());
|
||||||
setValue(&Relocate, SpillLoad);
|
setValue(&Relocate, SpillLoad);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(Record.type == RecordType::NoRelocate);
|
||||||
|
SDValue SD = getValue(DerivedPtr);
|
||||||
|
|
||||||
|
if (SD.isUndef() && SD.getValueType().getSizeInBits() <= 64) {
|
||||||
|
// Lowering relocate(undef) as arbitrary constant. Current constant value
|
||||||
|
// is chosen such that it's unlikely to be a valid pointer.
|
||||||
|
setValue(&Relocate, DAG.getTargetConstant(0xFEFEFEFE, SDLoc(SD), MVT::i64));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We didn't need to spill these special cases (constants and allocas).
|
||||||
|
// See the handling in spillIncomingValueForStatepoint for detail.
|
||||||
|
setValue(&Relocate, SD);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SelectionDAGBuilder::LowerDeoptimizeCall(const CallInst *CI) {
|
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