diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -1210,7 +1210,40 @@ 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 @@ 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) { diff --git a/llvm/test/CodeGen/X86/statepoint-spill-lowering.ll b/llvm/test/CodeGen/X86/statepoint-spill-lowering.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/statepoint-spill-lowering.ll @@ -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)