RegUnitSet UsedInInstr;
RegUnitSet PhysRegUses;
SmallVector<uint16_t, 8> DefOperandIndexes;
+ // Register masks attached to the current instruction.
+ SmallVector<const uint32_t *> RegMasks;
void setPhysRegState(MCPhysReg PhysReg, unsigned NewState);
bool isPhysRegFree(MCPhysReg PhysReg) const;
UsedInInstr.insert(*Units);
}
+ // Check if physreg is clobbered by instruction's regmask(s).
+ bool isClobberedByRegMasks(MCPhysReg PhysReg) const {
+ return llvm::any_of(RegMasks, [PhysReg](const uint32_t *Mask) {
+ return MachineOperand::clobbersPhysReg(Mask, PhysReg);
+ });
+ }
+
/// Check if a physreg or any of its aliases are used in this instruction.
bool isRegUsedInInstr(MCPhysReg PhysReg, bool LookAtPhysRegUses) const {
+ if (LookAtPhysRegUses && isClobberedByRegMasks(PhysReg))
+ return true;
for (MCRegUnitIterator Units(PhysReg, TRI); Units.isValid(); ++Units) {
if (UsedInInstr.count(*Units))
return true;
// operands and early-clobbers.
UsedInInstr.clear();
+ RegMasks.clear();
BundleVirtRegsMap.clear();
// Scan for special cases; Apply pre-assigned register defs to state.
}
} else if (MO.isRegMask()) {
HasRegMask = true;
+ RegMasks.push_back(MO.getRegMask());
}
}
continue;
}
+ assert((!MO.isTied() || !isClobberedByRegMasks(MO.getReg())) &&
+ "tied def assigned to clobbered register");
+
// Do not free tied operands and early clobbers.
if (MO.isTied() || MO.isEarlyClobber())
continue;
// Displace clobbered registers.
if (HasRegMask) {
- for (const MachineOperand &MO : MI.operands()) {
- if (MO.isRegMask()) {
- // MRI bookkeeping.
- MRI->addPhysRegsUsedFromRegMask(MO.getRegMask());
-
- // Displace clobbered registers.
- const uint32_t *Mask = MO.getRegMask();
- for (const LiveReg &LR : LiveVirtRegs) {
- MCPhysReg PhysReg = LR.PhysReg;
- if (PhysReg != 0 && MachineOperand::clobbersPhysReg(Mask, PhysReg))
- displacePhysReg(MI, PhysReg);
- }
- }
+ assert(!RegMasks.empty() && "expected RegMask");
+ // MRI bookkeeping.
+ for (const auto *RM : RegMasks)
+ MRI->addPhysRegsUsedFromRegMask(RM);
+
+ // Displace clobbered registers.
+ for (const LiveReg &LR : LiveVirtRegs) {
+ MCPhysReg PhysReg = LR.PhysReg;
+ if (PhysReg != 0 && isClobberedByRegMasks(PhysReg))
+ displacePhysReg(MI, PhysReg);
}
}
--- /dev/null
+# RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s
+
+# Check that fastregalloc does not displace register assigned to tied def when
+# RegMask operand is present. STATEPOINT is an example of such instruction.
+# Tied def/use must be assigned to the same register.
+---
+name: test_relocate
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $rdi
+
+ ; CHECK: renamable [[REG:\$[a-z0-9]+]] = STATEPOINT 0, 0, 0, target-flags(x86-plt) 0, 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) 0, 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
+...
+
+# Same as above but with multiple RegMask operands per instruction.
+# These regmasks have no real meaning and chosen to allow only single register to be assignable ($r12)
+---
+name: test_relocate_multi_regmasks
+tracksRegLiveness: true
+body: |
+ bb.0.entry:
+ liveins: $rdi
+
+ ; CHECK: renamable $r12 = STATEPOINT 0, 0, 0, target-flags(x86-plt) 0, 2, 0, 2, 0, 2, 0, 2, 1, renamable $r12(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) 0, 2, 0, 2, 0, 2, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64_rt_allregs, csr_64_hhvm, 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
+...