[llvm] 3815ae2 - [machinesink] fix debug invariance issue

Markus Lavin via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 20 23:13:29 PDT 2022


Author: Markus Lavin
Date: 2022-06-21T08:13:09+02:00
New Revision: 3815ae29b5cb43333adde04df9d9a7a644b77d68

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

LOG: [machinesink] fix debug invariance issue

Do not include debug instructions when comparing block sizes with
thresholds.

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

Added: 
    llvm/test/CodeGen/X86/machinesink-debug-inv-0.mir

Modified: 
    llvm/include/llvm/CodeGen/MachineBasicBlock.h
    llvm/lib/CodeGen/MachineBasicBlock.cpp
    llvm/lib/CodeGen/MachineSink.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/CodeGen/MachineBasicBlock.h b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
index 56952ef73e0dc..d2bd2c87f7d71 100644
--- a/llvm/include/llvm/CodeGen/MachineBasicBlock.h
+++ b/llvm/include/llvm/CodeGen/MachineBasicBlock.h
@@ -246,6 +246,7 @@ class MachineBasicBlock
       MachineInstrBundleIterator<const MachineInstr, true>;
 
   unsigned size() const { return (unsigned)Insts.size(); }
+  bool sizeWithoutDebugLargerThan(unsigned Limit) const;
   bool empty() const { return Insts.empty(); }
 
   MachineInstr       &instr_front()       { return Insts.front(); }

diff  --git a/llvm/lib/CodeGen/MachineBasicBlock.cpp b/llvm/lib/CodeGen/MachineBasicBlock.cpp
index 9f6be9aba632c..26e84101dbd1d 100644
--- a/llvm/lib/CodeGen/MachineBasicBlock.cpp
+++ b/llvm/lib/CodeGen/MachineBasicBlock.cpp
@@ -1617,6 +1617,16 @@ MachineBasicBlock::liveout_iterator MachineBasicBlock::liveout_begin() const {
   return liveout_iterator(*this, ExceptionPointer, ExceptionSelector, false);
 }
 
+bool MachineBasicBlock::sizeWithoutDebugLargerThan(unsigned Limit) const {
+  unsigned Cntr = 0;
+  auto R = instructionsWithoutDebug(begin(), end());
+  for (auto I = R.begin(), E = R.end(); I != E; ++I) {
+    if (++Cntr > Limit)
+      return true;
+  }
+  return false;
+}
+
 const MBBSectionID MBBSectionID::ColdSectionID(MBBSectionID::SectionType::Cold);
 const MBBSectionID
     MBBSectionID::ExceptionSectionID(MBBSectionID::SectionType::Exception);

diff  --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp
index 96d575ffb3fc5..3f2330b925774 100644
--- a/llvm/lib/CodeGen/MachineSink.cpp
+++ b/llvm/lib/CodeGen/MachineSink.cpp
@@ -1177,7 +1177,7 @@ bool MachineSinking::hasStoreBetween(MachineBasicBlock *From,
 
       // If this BB is too big or the block number in straight line between From
       // and To is too big, stop searching to save compiling time.
-      if (BB->size() > SinkLoadInstsPerBlockThreshold ||
+      if (BB->sizeWithoutDebugLargerThan(SinkLoadInstsPerBlockThreshold) ||
           HandledDomBlocks.size() > SinkLoadBlocksThreshold) {
         for (auto *DomBB : HandledDomBlocks) {
           if (DomBB != BB && DT->dominates(DomBB, BB))
@@ -1279,7 +1279,7 @@ bool MachineSinking::SinkIntoCycle(MachineCycle *Cycle, MachineInstr &I) {
         dbgs() << "CycleSink: Not sinking, sink block is the preheader\n");
     return false;
   }
-  if (SinkBlock->size() > SinkLoadInstsPerBlockThreshold) {
+  if (SinkBlock->sizeWithoutDebugLargerThan(SinkLoadInstsPerBlockThreshold)) {
     LLVM_DEBUG(
         dbgs() << "CycleSink: Not Sinking, block too large to analyse.\n");
     return false;

diff  --git a/llvm/test/CodeGen/X86/machinesink-debug-inv-0.mir b/llvm/test/CodeGen/X86/machinesink-debug-inv-0.mir
new file mode 100644
index 0000000000000..ca8764618b856
--- /dev/null
+++ b/llvm/test/CodeGen/X86/machinesink-debug-inv-0.mir
@@ -0,0 +1,137 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=x86_64 -machine-sink-load-instrs-threshold=2 -run-pass=machine-sink %s -o - | FileCheck %s
+# RUN: llc -mtriple=x86_64 -machine-sink-load-instrs-threshold=2 -run-pass=mir-debugify,machine-sink,mir-strip-debug %s -o - | FileCheck %s
+
+# Verify that machine-sink pass is debug invariant wrt to given input. Since
+# the pass examines MemOperands the IR is required for the original bug to
+# trigger.
+
+--- |
+  @e = global i32 0, align 1
+  @d = global i32 0, align 1
+  @f = global i32 0, align 1
+  @g = global i32 0, align 1
+
+  define i32 @l() {
+  entry:
+    br label %for.body
+
+  for.body:                                         ; preds = %h.exit, %entry
+    %cmp = phi i1 [ true, %entry ], [ false, %h.exit ]
+    %0 = load i32, ptr @d, align 1
+    %tobool61.not.i = icmp eq i32 %0, 0
+    %e.promoted44.i = load i32, ptr @e, align 1
+    br i1 %tobool61.not.i, label %h.exit, label %for.cond13.preheader.preheader.i
+
+  for.cond13.preheader.preheader.i:                 ; preds = %for.body
+    %1 = load i32, ptr @f, align 1
+    store i32 %1, ptr @g, align 1
+    br label %h.exit
+
+  h.exit:                                           ; preds = %for.cond13.preheader.preheader.i, %for.body
+    %.us-phi50.i = or i32 %e.promoted44.i, 4
+    store i32 %.us-phi50.i, ptr @e, align 1
+    br i1 %cmp, label %for.body, label %for.end
+
+  for.end:                                          ; preds = %h.exit
+    ret i32 undef
+  }
+...
+---
+name:            l
+alignment:       16
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr8 }
+  - { id: 1, class: gr32 }
+  - { id: 2, class: gr8 }
+  - { id: 3, class: gr64 }
+  - { id: 4, class: gr64 }
+  - { id: 5, class: gr64 }
+  - { id: 6, class: gr32 }
+  - { id: 7, class: gr64 }
+  - { id: 8, class: gr8 }
+  - { id: 9, class: gr32 }
+  - { id: 10, class: gr64 }
+  - { id: 11, class: gr32 }
+  - { id: 12, class: gr32 }
+frameInfo:
+  maxAlignment:    1
+machineFunctionInfo: {}
+body:             |
+  ; CHECK-LABEL: name: l
+  ; CHECK: bb.0.entry:
+  ; CHECK-NEXT:   successors: %bb.1(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV8ri:%[0-9]+]]:gr8 = MOV8ri 1
+  ; CHECK-NEXT:   [[MOV64rm:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @d, $noreg :: (load (s64) from got)
+  ; CHECK-NEXT:   [[MOV64rm1:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @e, $noreg :: (load (s64) from got)
+  ; CHECK-NEXT:   [[MOV64rm2:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @f, $noreg :: (load (s64) from got)
+  ; CHECK-NEXT:   [[MOV64rm3:%[0-9]+]]:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @g, $noreg :: (load (s64) from got)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.1.for.body:
+  ; CHECK-NEXT:   successors: %bb.3(0x30000000), %bb.2(0x50000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[PHI:%[0-9]+]]:gr8 = PHI [[MOV8ri]], %bb.0, %8, %bb.3
+  ; CHECK-NEXT:   CMP32mi8 [[MOV64rm]], 1, $noreg, 0, $noreg, 0, implicit-def $eflags :: (dereferenceable load (s32) from @d, align 1)
+  ; CHECK-NEXT:   JCC_1 %bb.3, 4, implicit $eflags
+  ; CHECK-NEXT:   JMP_1 %bb.2
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.2.for.cond13.preheader.preheader.i:
+  ; CHECK-NEXT:   successors: %bb.3(0x80000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32rm:%[0-9]+]]:gr32 = MOV32rm [[MOV64rm2]], 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @f, align 1)
+  ; CHECK-NEXT:   MOV32mr [[MOV64rm3]], 1, $noreg, 0, $noreg, killed [[MOV32rm]] :: (store (s32) into @g, align 1)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.3.h.exit:
+  ; CHECK-NEXT:   successors: %bb.1(0x7c000000), %bb.4(0x04000000)
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT:   [[MOV32rm1:%[0-9]+]]:gr32 = MOV32rm [[MOV64rm1]], 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @e, align 1)
+  ; CHECK-NEXT:   [[OR32ri8_:%[0-9]+]]:gr32 = OR32ri8 [[MOV32rm1]], 4, implicit-def dead $eflags
+  ; CHECK-NEXT:   MOV32mr [[MOV64rm1]], 1, $noreg, 0, $noreg, killed [[OR32ri8_]] :: (store (s32) into @e, align 1)
+  ; CHECK-NEXT:   [[MOV32r0_:%[0-9]+]]:gr32 = MOV32r0 implicit-def dead $eflags
+  ; CHECK-NEXT:   [[COPY:%[0-9]+]]:gr8 = COPY [[MOV32r0_]].sub_8bit
+  ; CHECK-NEXT:   TEST8ri [[PHI]], 1, implicit-def $eflags
+  ; CHECK-NEXT:   JCC_1 %bb.1, 5, implicit $eflags
+  ; CHECK-NEXT:   JMP_1 %bb.4
+  ; CHECK-NEXT: {{  $}}
+  ; CHECK-NEXT: bb.4.for.end:
+  ; CHECK-NEXT:   [[DEF:%[0-9]+]]:gr32 = IMPLICIT_DEF
+  ; CHECK-NEXT:   $eax = COPY [[DEF]]
+  ; CHECK-NEXT:   RET 0, $eax
+  bb.0.entry:
+    %2:gr8 = MOV8ri 1
+    %3:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @d, $noreg :: (load (s64) from got)
+    %4:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @e, $noreg :: (load (s64) from got)
+    %5:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @f, $noreg :: (load (s64) from got)
+    %7:gr64 = MOV64rm $rip, 1, $noreg, target-flags(x86-gotpcrel) @g, $noreg :: (load (s64) from got)
+
+  bb.1.for.body:
+    successors: %bb.3(0x30000000), %bb.2(0x50000000)
+
+    %0:gr8 = PHI %2, %bb.0, %8, %bb.3
+    CMP32mi8 %3, 1, $noreg, 0, $noreg, 0, implicit-def $eflags :: (dereferenceable load (s32) from @d, align 1)
+    %1:gr32 = MOV32rm %4, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @e, align 1)
+    JCC_1 %bb.3, 4, implicit $eflags
+    JMP_1 %bb.2
+
+  bb.2.for.cond13.preheader.preheader.i:
+    %6:gr32 = MOV32rm %5, 1, $noreg, 0, $noreg :: (dereferenceable load (s32) from @f, align 1)
+    MOV32mr %7, 1, $noreg, 0, $noreg, killed %6 :: (store (s32) into @g, align 1)
+
+  bb.3.h.exit:
+    successors: %bb.1(0x7c000000), %bb.4(0x04000000)
+
+    %9:gr32 = OR32ri8 %1, 4, implicit-def dead $eflags
+    MOV32mr %4, 1, $noreg, 0, $noreg, killed %9 :: (store (s32) into @e, align 1)
+    %11:gr32 = MOV32r0 implicit-def dead $eflags
+    %8:gr8 = COPY %11.sub_8bit
+    TEST8ri %0, 1, implicit-def $eflags
+    JCC_1 %bb.1, 5, implicit $eflags
+    JMP_1 %bb.4
+
+  bb.4.for.end:
+    %12:gr32 = IMPLICIT_DEF
+    $eax = COPY %12
+    RET 0, $eax
+...


        


More information about the llvm-commits mailing list