[llvm] d1fd791 - [TwoAddressInstruction] Handle pointer compare sunk past statepoint.

Denis Antrushin via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 23 02:35:12 PDT 2022


Author: Denis Antrushin
Date: 2022-08-23T12:34:11+03:00
New Revision: d1fd791e72c0e00854dcd318b4b08e7ea55acd20

URL: https://github.com/llvm/llvm-project/commit/d1fd791e72c0e00854dcd318b4b08e7ea55acd20
DIFF: https://github.com/llvm/llvm-project/commit/d1fd791e72c0e00854dcd318b4b08e7ea55acd20.diff

LOG: [TwoAddressInstruction] Handle pointer compare sunk past statepoint.

CodeGenPrepare pass can sink pointer comparison across statepoint
to the point of use (see comment in IR/SafepointIRVerifier.cpp)
Due to specifics of statepoints, it is still legal to have tied
def and use rewritten to the same register in TwoAddress pass.
However, properly updating LiveIntervals and LiveVariables becomes
complicated. For simplicity, let's fall back to generic handling of
tied registers when we detect such case.
TODO: This fixes functional (assertion) failure. Ideally we should
try to recompute new live range/liveness in place.

Reviewed By: skatkov

Differential Revision: https://reviews.llvm.org/D132255

Added: 
    

Modified: 
    llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
    llvm/test/CodeGen/X86/statepoint-cmp-sunk-past-statepoint.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
index 17fe819fa900a..3805221e06d33 100644
--- a/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
+++ b/llvm/lib/CodeGen/TwoAddressInstructionPass.cpp
@@ -1657,13 +1657,43 @@ bool TwoAddressInstructionPass::processStatepoint(
     if (RegA == RegB)
       continue;
 
+    // CodeGenPrepare can sink pointer compare past statepoint, which
+    // breaks assumption that statepoint kills tied-use register when
+    // in SSA form (see note in IR/SafepointIRVerifier.cpp). Fall back
+    // to generic tied register handling to avoid assertion failures.
+    // TODO: Recompute LIS/LV information for new range here.
+    if (LIS) {
+      const auto &UseLI = LIS->getInterval(RegB);
+      const auto &DefLI = LIS->getInterval(RegA);
+      if (DefLI.overlaps(UseLI)) {
+        LLVM_DEBUG(dbgs() << "LIS: " << printReg(RegB, TRI, 0)
+                          << " UseLI overlaps with DefLI\n");
+        NeedCopy = true;
+        continue;
+      }
+    } else if (LV && LV->getVarInfo(RegB).findKill(MI->getParent()) != MI) {
+      // Note that MachineOperand::isKill does not work here, because it
+      // is set only on first register use in instruction and for statepoint
+      // tied-use register will usually be found in preceeding deopt bundle.
+      LLVM_DEBUG(dbgs() << "LV: " << printReg(RegB, TRI, 0)
+                        << " not killed by statepoint\n");
+      NeedCopy = true;
+      continue;
+    }
+
     MRI->replaceRegWith(RegA, RegB);
 
     if (LIS) {
       VNInfo::Allocator &A = LIS->getVNInfoAllocator();
       LiveInterval &LI = LIS->getInterval(RegB);
-      for (auto &S : LIS->getInterval(RegA)) {
-        VNInfo *VNI = LI.getNextValue(S.start, A);
+      LiveInterval &Other = LIS->getInterval(RegA);
+      SmallVector<VNInfo *> NewVNIs;
+      for (const VNInfo *VNI : Other.valnos) {
+        assert(VNI->id == NewVNIs.size() && "assumed");
+        NewVNIs.push_back(LI.createValueCopy(VNI, A));
+      }
+      for (auto &S : Other) {
+        VNInfo *VNI = NewVNIs[S.valno->id];
         LiveRange::Segment NewSeg(S.start, S.end, VNI);
         LI.addSegment(NewSeg);
       }

diff  --git a/llvm/test/CodeGen/X86/statepoint-cmp-sunk-past-statepoint.ll b/llvm/test/CodeGen/X86/statepoint-cmp-sunk-past-statepoint.ll
index 9df386f095a9f..9c881dd816994 100644
--- a/llvm/test/CodeGen/X86/statepoint-cmp-sunk-past-statepoint.ll
+++ b/llvm/test/CodeGen/X86/statepoint-cmp-sunk-past-statepoint.ll
@@ -1,12 +1,5 @@
-; RUN: not --crash llc -max-registers-for-gc-values=256 -verify-machineinstrs -stop-after twoaddressinstruction < %s 2>&1 | FileCheck --check-prefixes CHECK-ERROR-LV %s
-; RUN: not --crash llc -max-registers-for-gc-values=256 -verify-machineinstrs -stop-after twoaddressinstruction -early-live-intervals < %s 2>&1  | FileCheck --check-prefixes CHECK-ERROR-LIS %s
-; REQUIRES: asserts
-
-; CHECK-ERROR-LV:  Bad machine code: Virtual register killed in block, but needed live out.
-; CHECK-ERROR-LV:  function:    test
-; CHECK-ERROR-LV:  basic block: %bb.0
-
-; CHECK-ERROR-LIS: Found multiple kills of a register in a basic block
+; RUN: llc -max-registers-for-gc-values=256 -verify-machineinstrs -stop-after twoaddressinstruction < %s | FileCheck --check-prefixes CHECK,CHECK-LV %s
+; RUN: llc -max-registers-for-gc-values=256 -verify-machineinstrs -stop-after twoaddressinstruction -early-live-intervals < %s | FileCheck --check-prefixes CHECK,CHECK-LIS %s
 
 target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128-ni:1-p2:32:8:8:32-ni:2"
 target triple = "x86_64-unknown-linux-gnu"
@@ -22,15 +15,16 @@ declare i32* @fake_personality_function()
 ; CHECK:  bb.0
 ; CHECK-LV:     %0:gr64 = COPY killed $rdi
 ; CHECK-LIS:    %0:gr64 = COPY $rdi
-; CHECK:        %0:gr64 = STATEPOINT 2, 5, 0, undef %2:gr64, 2, 0, 2, 0, 2, 0, 2, 1, %0(tied-def 0), 2, 0, 2, 1, 0, 0
+; CHECK:        %1:gr64 = COPY %0
+; CHECK:        %1:gr64 = STATEPOINT 2, 5, 0, undef %2:gr64, 2, 0, 2, 0, 2, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0
 ; CHECK-LV:     TEST64rr killed %0, %0, implicit-def $eflags
 ; CHECK-LIS:    TEST64rr %0, %0, implicit-def $eflags
 ; CHECK:        JCC_1 %bb.2, 4, implicit killed $eflags
 ; CHECK:        JMP_1 %bb.1
 ; CHECK:      bb.1
-; CHECK-LV:     $rdi = COPY killed %0
-; CHECK-LV:     STATEPOINT 2, 5, 1, undef %3:gr64, $rdi, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0
-; CHECK-LIS:    $rdi = COPY killed %0
+; CHECK-LV:     $rdi = COPY killed %1
+; CHECK-LV:     STATEPOINT 2, 5, 1, undef %3:gr64, killed $rdi, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0
+; CHECK-LIS:    $rdi = COPY %1
 ; CHECK-LIS:    STATEPOINT 2, 5, 1, undef %3:gr64, $rdi, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, 0
 ; CHECK:        RET 0
 ; CHECK:      bb.2
@@ -55,7 +49,8 @@ zero:
 ; CHECK-LABEL: name: test2
 ; CHECK:  bb.2
 ; CHECK:        %1:gr64 = STATEPOINT 2882400000, 0, 0, undef %11:gr64, 2, 0, 2, 0, 2, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64
-; CHECK:        %1:gr64 = STATEPOINT 2882400000, 0, 0, undef %13:gr64, 2, 0, 2, 0, 2, 0, 2, 1, %1(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64
+; CHECK:        %10:gr64 = COPY %1
+; CHECK:        %10:gr64 = STATEPOINT 2882400000, 0, 0, undef %13:gr64, 2, 0, 2, 0, 2, 0, 2, 1, %10(tied-def 0), 2, 0, 2, 1, 0, 0, csr_64
 ; CHECK:        JMP_1 %bb.3
 ; CHECK:      bb.3
 ; CHECK:        %18:gr8 = COPY %17.sub_8bit
@@ -65,9 +60,9 @@ zero:
 ; CHECK:        JMP_1 %bb.4
 ; CHECK:      bb.4
 ; CHECK:      bb.5
-; CHECK:        %4:gr64 = LEA64r %1, 1, $noreg, 8, $noreg
-; CHECK-LV:     %3:gr64 = COPY killed %1
-; CHECK-LIS:    %3:gr64 = COPY killed %1
+; CHECK:        %4:gr64 = LEA64r %10, 1, $noreg, 8, $noreg
+; CHECK-LV:     %3:gr64 = COPY killed %10
+; CHECK-LIS:    %3:gr64 = COPY %10
 ; CHECK-LV:     TEST64rr killed %1, %1, implicit-def $eflags
 ; CHECK:        JCC_1 %bb.1, 5, implicit killed $eflags
 ; CHECK:        JMP_1 %bb.6


        


More information about the llvm-commits mailing list