diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -1130,6 +1130,9 @@ } } + // Set of registers allocated to tied defs. + SmallSet AssignedTiedDefs; + // Allocate virtreg defs. if (HasDef) { if (HasVRegDef) { @@ -1203,6 +1206,7 @@ return I0 < I1; }); + bool isStatepoint = (MI.getOpcode() == TargetOpcode::STATEPOINT); for (uint16_t OpIdx : DefOperandIndexes) { MachineOperand &MO = MI.getOperand(OpIdx); LLVM_DEBUG(dbgs() << "Allocating " << MO << '\n'); @@ -1213,6 +1217,13 @@ } else { defineVirtReg(MI, OpIdx, Reg); } + if (isStatepoint) { + assert(MO.isTied() && "Only tied defs in statepoints"); + LiveRegMap::iterator LRI = findLiveVirtReg(Reg); + assert(LRI != LiveVirtRegs.end() && "LR must be processed"); + assert(LRI->PhysReg != 0 && "register must be allocated"); + AssignedTiedDefs.insert(LRI->PhysReg); + } } } else { // Assign virtual register defs. @@ -1267,6 +1278,8 @@ const uint32_t *Mask = MO.getRegMask(); for (const LiveReg &LR : LiveVirtRegs) { MCPhysReg PhysReg = LR.PhysReg; + if (AssignedTiedDefs.count(PhysReg)) + continue; if (PhysReg != 0 && MachineOperand::clobbersPhysReg(Mask, PhysReg)) displacePhysReg(MI, PhysReg); } diff --git a/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/X86/statepoint-fastregalloc.mir @@ -0,0 +1,80 @@ +# RUN: llc -run-pass=regallocfast -o - %s | FileCheck %s +--- | + ; ModuleID = 'test.ll' + source_filename = "test.ll" + target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + target triple = "x86_64-pc-linux-gnu" + + declare void @consume() + + define i32 addrspace(1)* @test_relocate(i32 addrspace(1)* %a) gc "statepoint-example" { + entry: + %safepoint_token = tail call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 0, i32 0, void ()* @consume, i32 0, i32 0, i32 0, i32 0) [ "gc-live"(i32 addrspace(1)* %a) ] + %rel1 = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token %safepoint_token, i32 0, i32 0) ; (%a, %a) + ret i32 addrspace(1)* %rel1 + } + + declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 immarg, i32 immarg, void ()*, i32 immarg, i32 immarg, ...) + + ; Function Attrs: nounwind readonly + declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32 immarg, i32 immarg) #0 + + attributes #0 = { nounwind readonly } + +... +--- +name: test_relocate +alignment: 16 +exposesReturnsTwice: false +legalized: false +regBankSelected: false +selected: false +failedISel: false +tracksRegLiveness: true +hasWinCFI: false +registers: + - { id: 0, class: gr64, preferred-register: '' } + - { id: 1, class: gr64, preferred-register: '' } +liveins: + - { reg: '$rdi', virtual-reg: '%0' } +frameInfo: + isFrameAddressTaken: false + isReturnAddressTaken: false + hasStackMap: false + hasPatchPoint: false + stackSize: 0 + offsetAdjustment: 0 + maxAlignment: 1 + adjustsStack: false + hasCalls: true + stackProtector: '' + maxCallFrameSize: 4294967295 + cvBytesOfCalleeSavedRegisters: 0 + hasOpaqueSPAdjustment: false + hasVAStart: false + hasMustTailInVarArgFunc: false + hasTailCall: false + localFrameSize: 0 + savePoint: '' + restorePoint: '' +fixedStack: [] +stack: [] +callSites: [] +debugValueSubstitutions: [] +constants: [] +machineFunctionInfo: {} +body: | + bb.0.entry: + liveins: $rdi + + ; CHECK-LABEL: name: test_relocate + ; CHECK: renamable [[REG:\$[a-z0-9]+]] = STATEPOINT 0, 0, 0, target-flags(x86-plt) @consume, 2, 0, 2, 0, 2, 0, 2, 1, renamable [[REG]](tied-def 0) + + %1:gr64 = COPY $rdi + ADJCALLSTACKDOWN64 0, 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + %1:gr64 = STATEPOINT 0, 0, 0, target-flags(x86-plt) @consume, 2, 0, 2, 0, 2, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64, implicit-def $rsp, implicit-def $ssp + ADJCALLSTACKUP64 0, 0, implicit-def dead $rsp, implicit-def dead $eflags, implicit-def dead $ssp, implicit $rsp, implicit $ssp + $rax = COPY %1 + RET 0, killed $rax + +...