[PATCH] D101525: RegAlloc: do not consider liveins to EH-pad successors as liveout.

Tim Northover via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 29 05:36:02 PDT 2021


t.p.northover created this revision.
Herald added subscribers: pengfei, hiraditya, mcrosier, qcolombet, MatzeB.
t.p.northover requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

RegAllocFast is looking at  the successors' liveins to determine the initial liveouts of the block being allocated. Unfortunately if the block ends with an invoke, one of these is the landingpad which really gets its liveins from the runtime, not us.

This leads to registers being reserved in the block until they're fully clobbered by an instruction in reverse-order. In particularly tight situations on x86 (base pointer, lots of arg registers, and `al` used for varargs purposes, a `_NOREX` regclass being allocated) we can end up with nothing spillable and fail to allocate.

Also, it turns out that RegUnit 0 is valid, which threw me for a while when I was relying on `dumpState` and `AH` was nowhere to be found. So this fixes the dumper too.


https://reviews.llvm.org/D101525

Files:
  llvm/lib/CodeGen/RegAllocFast.cpp
  llvm/test/CodeGen/X86/fast-isel-cmp-branch.ll
  llvm/test/CodeGen/X86/regalloc-tight-invoke.ll


Index: llvm/test/CodeGen/X86/regalloc-tight-invoke.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/X86/regalloc-tight-invoke.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -mtriple=x86_64-apple-darwin %s -o - | FileCheck %s
+declare void @foo(i32, ...)
+
+declare i32 @__gxx_personality_v0(...)
+
+; We were running out of registers for this invoke, because:
+
+;     1. The lshr/and pattern gets matched to a no-REX MOV so that ah/bh/... can
+;        be used instead, cutting available registers for %b.arg down to eax, ebx,
+;        ecx, edx, esi, edi.
+;     2. We have a base pointer taking ebx out of contention.
+;     3. The landingpad block convinced us we should be defining rax here.
+;     3. The al fiddling for the varargs call only noted down that al was spillable,
+;        not ah or hax.
+;
+; So by the time we need to allocate a register for the call all registers are
+; tied up and unspillable.
+
+; CHECK-LABEL: bar:
+; CHECK: xorl %edi, %edi
+; CHECK: movb %dil, {{[0-9]+}}(%rbx)
+; CHECK: movb {{[0-9]+}}(%rbx), %al
+define i32 @bar(i32 %a, i32 %b, i32 %c, i32 %d, ...) personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
+  %mem = alloca i32, i32 %a, align 32   ; Force rbx to be used as a base pointer
+  %b.tmp = lshr i32 %b, 8
+  %b.arg = and i32 %b.tmp, 255
+  invoke void(i32, ...) @foo(i32 42, i32* %mem, i32 %c, i32 %d, i32 %b.arg) to label %success unwind label %fail
+
+success:
+  ret i32 0
+fail:
+  %exc = landingpad { i8*, i32 } cleanup
+  %res = extractvalue { i8*, i32 } %exc, 1
+  ret i32 %res
+}
Index: llvm/test/CodeGen/X86/fast-isel-cmp-branch.ll
===================================================================
--- llvm/test/CodeGen/X86/fast-isel-cmp-branch.ll
+++ llvm/test/CodeGen/X86/fast-isel-cmp-branch.ll
@@ -19,7 +19,7 @@
 ; different basic block, so its operands aren't necessarily exported
 ; for cross-block usage.
 
-; CHECK: movb    %cl, [[OFS:[0-9]*]](%rsp)
+; CHECK: movb    %al, [[OFS:[0-9]*]](%rsp)
 ; CHECK: callq   {{_?}}bar
 ; CHECK: movb    [[OFS]](%rsp), %al
 
Index: llvm/lib/CodeGen/RegAllocFast.cpp
===================================================================
--- llvm/lib/CodeGen/RegAllocFast.cpp
+++ llvm/lib/CodeGen/RegAllocFast.cpp
@@ -1002,7 +1002,7 @@
 #ifndef NDEBUG
 
 void RegAllocFast::dumpState() const {
-  for (unsigned Unit = 1, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
+  for (unsigned Unit = 0, UnitE = TRI->getNumRegUnits(); Unit != UnitE;
        ++Unit) {
     switch (unsigned VirtReg = RegUnitStates[Unit]) {
     case regFree:
@@ -1440,6 +1440,11 @@
   assert(LiveVirtRegs.empty() && "Mapping not cleared from last block?");
 
   for (MachineBasicBlock *Succ : MBB.successors()) {
+    // EH-pads get their liveins from the runtime, not whatever happens in this
+    // block.
+    if (Succ->isEHPad())
+      continue;
+
     for (const MachineBasicBlock::RegisterMaskPair &LI : Succ->liveins())
       setPhysRegState(LI.PhysReg, regPreAssigned);
   }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D101525.341484.patch
Type: text/x-patch
Size: 3026 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20210429/2ed4afa1/attachment.bin>


More information about the llvm-commits mailing list