From 95651321e4e455777bb6a06050931967fb851d21 Mon Sep 17 00:00:00 2001 From: MuellerMP Date: Tue, 29 Oct 2024 16:47:59 +0100 Subject: [PATCH] [CodeGen] Use first EHLabel as a stop gate for live range shrinking This fixes issue #114194 The issue happens during the LiveRangeShrink pass, which runs early, before phi elimination. LandingPads, which are lowered to EHLabels, need to be the first non phi instruction in an EHPad. In case of a phi node being in front of the EHLabel and a use being after the EHLabel, we hoist the use in front of the label. This results in a portion of the landingpad missing due to being hoisted in front of the label. --- llvm/lib/CodeGen/LiveRangeShrink.cpp | 9 +- llvm/test/CodeGen/X86/lrshrink-ehpad-phis.ll | 112 +++++++++++++++++++ 2 files changed, 119 insertions(+), 2 deletions(-) create mode 100755 llvm/test/CodeGen/X86/lrshrink-ehpad-phis.ll diff --git a/llvm/lib/CodeGen/LiveRangeShrink.cpp b/llvm/lib/CodeGen/LiveRangeShrink.cpp index 3e3e3e51bfe9c6..8509a9e21aae42 100644 --- a/llvm/lib/CodeGen/LiveRangeShrink.cpp +++ b/llvm/lib/CodeGen/LiveRangeShrink.cpp @@ -125,10 +125,15 @@ bool LiveRangeShrink::runOnMachineFunction(MachineFunction &MF) { if (MBB.empty()) continue; bool SawStore = false; - BuildInstOrderMap(MBB.begin(), IOM); + MachineBasicBlock::iterator Next = MBB.begin(); + if (MBB.isEHPad()) + Next = MBB.SkipPHIsLabelsAndDebug(Next); + if (Next == MBB.end()) + continue; + BuildInstOrderMap(Next, IOM); UseMap.clear(); - for (MachineBasicBlock::iterator Next = MBB.begin(); Next != MBB.end();) { + while (Next != MBB.end()) { MachineInstr &MI = *Next; ++Next; if (MI.isPHI() || MI.isDebugOrPseudoInstr()) diff --git a/llvm/test/CodeGen/X86/lrshrink-ehpad-phis.ll b/llvm/test/CodeGen/X86/lrshrink-ehpad-phis.ll new file mode 100755 index 00000000000000..b9afb996973548 --- /dev/null +++ b/llvm/test/CodeGen/X86/lrshrink-ehpad-phis.ll @@ -0,0 +1,112 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -mtriple x86_64-unknown-linux-gnu %s -o - | FileCheck %s + +declare i32 @__gxx_personality_v0(...) +declare void @maythrow() +declare void @cleanup(i32) + +@external_bool = external global i1 +@externalA = external global i32 +@externalB = external global i32 +@externalC = external global i32 +@externalD = external global i32 + +define void @test() personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: test: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: pushq %r15 +; CHECK-NEXT: .cfi_def_cfa_offset 24 +; CHECK-NEXT: pushq %r14 +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: pushq %r13 +; CHECK-NEXT: .cfi_def_cfa_offset 40 +; CHECK-NEXT: pushq %r12 +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: pushq %rbx +; CHECK-NEXT: .cfi_def_cfa_offset 56 +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 64 +; CHECK-NEXT: .cfi_offset %rbx, -56 +; CHECK-NEXT: .cfi_offset %r12, -48 +; CHECK-NEXT: .cfi_offset %r13, -40 +; CHECK-NEXT: .cfi_offset %r14, -32 +; CHECK-NEXT: .cfi_offset %r15, -24 +; CHECK-NEXT: .cfi_offset %rbp, -16 +; CHECK-NEXT: movq external_bool@GOTPCREL(%rip), %rax +; CHECK-NEXT: cmpb $1, (%rax) +; CHECK-NEXT: jne .LBB0_3 +; CHECK-NEXT: # %bb.1: # %branchA +; CHECK-NEXT: movq externalA@GOTPCREL(%rip), %rax +; CHECK-NEXT: movl (%rax), %eax +; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill +; CHECK-NEXT: movq externalC@GOTPCREL(%rip), %rax +; CHECK-NEXT: movl (%rax), %eax +; CHECK-NEXT: movl %eax, (%rsp) # 4-byte Spill +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: .Ltmp2: +; CHECK-NEXT: callq maythrow@PLT +; CHECK-NEXT: .Ltmp3: +; CHECK-NEXT: jmp .LBB0_4 +; CHECK-NEXT: .LBB0_3: # %branchB +; CHECK-NEXT: movq externalB@GOTPCREL(%rip), %rax +; CHECK-NEXT: movl (%rax), %eax +; CHECK-NEXT: movl %eax, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill +; CHECK-NEXT: movq externalD@GOTPCREL(%rip), %rax +; CHECK-NEXT: movl (%rax), %eax +; CHECK-NEXT: movl %eax, (%rsp) # 4-byte Spill +; CHECK-NEXT: #APP +; CHECK-NEXT: #NO_APP +; CHECK-NEXT: .Ltmp0: +; CHECK-NEXT: callq maythrow@PLT +; CHECK-NEXT: .Ltmp1: +; CHECK-NEXT: .LBB0_4: # %end +; CHECK-NEXT: addq $8, %rsp +; CHECK-NEXT: .cfi_def_cfa_offset 56 +; CHECK-NEXT: popq %rbx +; CHECK-NEXT: .cfi_def_cfa_offset 48 +; CHECK-NEXT: popq %r12 +; CHECK-NEXT: .cfi_def_cfa_offset 40 +; CHECK-NEXT: popq %r13 +; CHECK-NEXT: .cfi_def_cfa_offset 32 +; CHECK-NEXT: popq %r14 +; CHECK-NEXT: .cfi_def_cfa_offset 24 +; CHECK-NEXT: popq %r15 +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: popq %rbp +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB0_2: # %lpad +; CHECK-NEXT: .cfi_def_cfa_offset 64 +; CHECK-NEXT: .Ltmp4: +; CHECK-NEXT: movq %rax, %rbx +; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %edi # 4-byte Reload +; CHECK-NEXT: addl (%rsp), %edi # 4-byte Folded Reload +; CHECK-NEXT: callq cleanup@PLT +; CHECK-NEXT: movq %rbx, %rdi +; CHECK-NEXT: callq _Unwind_Resume@PLT + %1 = load i1, ptr @external_bool + br i1 %1, label %branchA, label %branchB +branchA: + %valueA = load i32, ptr @externalA + %valueC = load i32, ptr @externalC + call void asm sideeffect "", "~{rbp},~{rsi},~{rdi},~{rcx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{flags}"() + invoke void @maythrow() to label %end unwind label %lpad +branchB: + %valueB = load i32, ptr @externalB + %valueD = load i32, ptr @externalD + call void asm sideeffect "", "~{rbp},~{rsi},~{rdi},~{rcx},~{rbx},~{r12},~{r13},~{r14},~{r15},~{flags}"() + invoke void @maythrow() to label %end unwind label %lpad +lpad: + %phiValue = phi i32 [%valueA, %branchA], [%valueB, %branchB] + %phiValue2 = phi i32 [%valueC, %branchA], [%valueD, %branchB] + %lp = landingpad { ptr, i32 } + cleanup + %3 = add i32 %phiValue2, %phiValue + call void @cleanup(i32 %3) + resume { ptr, i32 } %lp +end: + ret void +}