From 764676b737db0f259ef018104edbc2aec9db7e7d Mon Sep 17 00:00:00 2001 From: "Luo, Yuanke" Date: Wed, 4 May 2022 11:24:48 +0800 Subject: [PATCH] [fastregalloc] Fix bug when undef value is tied to def. If the tied use is undef value, fastregalloc should free the def register. There is no reload needed for the undef value. Reviewed By: MatzeB Differential Revision: https://reviews.llvm.org/D124834 --- llvm/lib/CodeGen/RegAllocFast.cpp | 20 +++++++++---- llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir | 36 +++++++++++++++++++++++ 2 files changed, 51 insertions(+), 5 deletions(-) create mode 100644 llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir diff --git a/llvm/lib/CodeGen/RegAllocFast.cpp b/llvm/lib/CodeGen/RegAllocFast.cpp index dfe0876..bee811f 100644 --- a/llvm/lib/CodeGen/RegAllocFast.cpp +++ b/llvm/lib/CodeGen/RegAllocFast.cpp @@ -1112,6 +1112,12 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { 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; @@ -1119,7 +1125,8 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { 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()) { @@ -1130,7 +1137,8 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { 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()) { @@ -1230,7 +1238,8 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { 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 { @@ -1253,7 +1262,8 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { // 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 ). - 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; @@ -1268,7 +1278,7 @@ void RegAllocFast::allocateInstruction(MachineInstr &MI) { "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) diff --git a/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir b/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir new file mode 100644 index 0000000..8a6311e --- /dev/null +++ b/llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir @@ -0,0 +1,36 @@ +# 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 + +... -- 2.7.4