[fastregalloc] Fix bug when undef value is tied to def.
authorLuo, Yuanke <yuanke.luo@intel.com>
Wed, 4 May 2022 03:24:48 +0000 (11:24 +0800)
committerLuo, Yuanke <yuanke.luo@intel.com>
Wed, 4 May 2022 04:12:55 +0000 (12:12 +0800)
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
llvm/test/CodeGen/X86/fastregalloc-tied-undef.mir [new file with mode: 0644]

index dfe0876..bee811f 100644 (file)
@@ -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 <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;
 
@@ -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 (file)
index 0000000..8a6311e
--- /dev/null
@@ -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
+
+...