RegMasks.clear();
BundleVirtRegsMap.clear();
+ auto TiedOpIsUndef = [&](const MachineOperand &MO, unsigned Idx) {
+ assert(MO.isTied());
+ unsigned TiedIdx = MI.findTiedOperandIdx(Idx);
+ const MachineOperand &TiedMO = MI.getOperand(TiedIdx);
+ return TiedMO.isUndef();
+ };
// Scan for special cases; Apply pre-assigned register defs to state.
bool HasPhysRegUse = false;
bool HasRegMask = false;
bool HasDef = false;
bool HasEarlyClobber = false;
bool NeedToAssignLiveThroughs = false;
- for (MachineOperand &MO : MI.operands()) {
+ for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
+ MachineOperand &MO = MI.getOperand(I);
if (MO.isReg()) {
Register Reg = MO.getReg();
if (Reg.isVirtual()) {
HasEarlyClobber = true;
NeedToAssignLiveThroughs = true;
}
- if (MO.isTied() || (MO.getSubReg() != 0 && !MO.isUndef()))
+ if ((MO.isTied() && !TiedOpIsUndef(MO, I)) ||
+ (MO.getSubReg() != 0 && !MO.isUndef()))
NeedToAssignLiveThroughs = true;
}
} else if (Reg.isPhysical()) {
MachineOperand &MO = MI.getOperand(OpIdx);
LLVM_DEBUG(dbgs() << "Allocating " << MO << '\n');
unsigned Reg = MO.getReg();
- if (MO.isEarlyClobber() || MO.isTied() ||
+ if (MO.isEarlyClobber() ||
+ (MO.isTied() && !TiedOpIsUndef(MO, OpIdx)) ||
(MO.getSubReg() && !MO.isUndef())) {
defineLiveThroughVirtReg(MI, OpIdx, Reg);
} else {
// Free registers occupied by defs.
// Iterate operands in reverse order, so we see the implicit super register
// defs first (we added them earlier in case of <def,read-undef>).
- for (MachineOperand &MO : llvm::reverse(MI.operands())) {
+ for (signed I = MI.getNumOperands() - 1; I >= 0; --I) {
+ MachineOperand &MO = MI.getOperand(I);
if (!MO.isReg() || !MO.isDef())
continue;
"tied def assigned to clobbered register");
// Do not free tied operands and early clobbers.
- if (MO.isTied() || MO.isEarlyClobber())
+ if ((MO.isTied() && !TiedOpIsUndef(MO, I)) || MO.isEarlyClobber())
continue;
Register Reg = MO.getReg();
if (!Reg)
--- /dev/null
+# RUN: llc -mtriple=x86_64-- -run-pass=regallocfast -o - %s | FileCheck %s
+
+# If the tied use is undef value, fastregalloc should free the def register.
+# There is no reload needed for the undef value.
+...
+---
+name: foo
+alignment: 16
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: vr128 }
+frameInfo:
+ maxAlignment: 16
+stack:
+ - { id: 0, size: 64, alignment: 16 }
+ - { id: 1, size: 16, alignment: 16 }
+machineFunctionInfo: {}
+body: |
+ bb.0.entry:
+ ; CHECK-LABEL: bb.0.entry
+ ; CHECK-NEXT: renamable $xmm0 = PXORrr undef renamable $xmm0, undef renamable $xmm0
+ ; CHECK-NEXT: MOVAPSmr %stack.1, 1, $noreg, 0, $noreg, renamable $xmm0
+ ; CHECK-NEXT: MOVAPSmr %stack.0, 1, $noreg, 0, $noreg, renamable $xmm0
+ ; CHECK-NEXT: MOVAPSmr %stack.0, 1, $noreg, 16, $noreg, renamable $xmm0
+ ; CHECK-NEXT: MOVAPSmr %stack.0, 1, $noreg, 32, $noreg, renamable $xmm0
+ ; CHECK-NEXT: MOVAPSmr %stack.0, 1, $noreg, 48, $noreg, killed renamable $xmm0
+
+ %0:vr128 = PXORrr undef %0, undef %0
+ MOVAPSmr %stack.1, 1, $noreg, 0, $noreg, %0
+ MOVAPSmr %stack.0, 1, $noreg, 0, $noreg, %0
+ MOVAPSmr %stack.0, 1, $noreg, 16, $noreg, %0
+ MOVAPSmr %stack.0, 1, $noreg, 32, $noreg, %0
+ MOVAPSmr %stack.0, 1, $noreg, 48, $noreg, killed %0
+ RET 0
+
+...