Skip to content

Commit

Permalink
[LivePhysRegs] Preserve pristine regs in blocks with no successors.
Browse files Browse the repository at this point in the history
One common source of blocks with no successors is calls to noreturn
functions; we want to preserve pristine registers in case they throw an
exception.

The whole pristine register thing is messy (we should really prefer to
explicitly model registers), but this fills a hole in the model for now.

Fixes https://bugs.llvm.org/show_bug.cgi?id=36073.

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

llvm-svn: 323559
  • Loading branch information
Eli Friedman committed Jan 26, 2018
1 parent d15b289 commit 2910884
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 2 deletions.
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/LivePhysRegs.cpp
Expand Up @@ -225,10 +225,10 @@ void LivePhysRegs::addLiveOutsNoPristines(const MachineBasicBlock &MBB) {

void LivePhysRegs::addLiveOuts(const MachineBasicBlock &MBB) {
const MachineFunction &MF = *MBB.getParent();
if (!MBB.succ_empty()) {
if (!MBB.isReturnBlock()) {
addPristines(MF);
addLiveOutsNoPristines(MBB);
} else if (MBB.isReturnBlock()) {
} else {
// For the return block: Add all callee saved registers.
const MachineFrameInfo &MFI = MF.getFrameInfo();
if (MFI.isCalleeSavedInfoValid())
Expand Down
47 changes: 47 additions & 0 deletions llvm/test/CodeGen/Thumb/stm-scavenging.ll
@@ -0,0 +1,47 @@
; RUN: llc < %s | FileCheck %s
target triple = "thumbv6---gnueabi"

; Use STM to save the three registers
; CHECK-LABEL: use_stm:
; CHECK: .save {r7, lr}
; CHECK: .setfp r7, sp
; CHECK: stm r3!, {r0, r1, r2}
; CHECK: bl throws_1
define void @use_stm(i32 %a, i32 %b, i32 %c, i32* %d) local_unnamed_addr noreturn "no-frame-pointer-elim"="true" {
entry:
%arrayidx = getelementptr inbounds i32, i32* %d, i32 2
store i32 %a, i32* %arrayidx, align 4
%arrayidx1 = getelementptr inbounds i32, i32* %d, i32 3
store i32 %b, i32* %arrayidx1, align 4
%arrayidx2 = getelementptr inbounds i32, i32* %d, i32 4
store i32 %c, i32* %arrayidx2, align 4
tail call void @throws_1(i32 %a, i32 %b, i32 %c) noreturn
unreachable
}

; Don't use STM: there is no available register to store
; the address. We could transform this with some extra math, but
; that currently isn't implemented.
; CHECK-LABEL: no_stm:
; CHECK: .save {r7, lr}
; CHECK: .setfp r7, sp
; CHECK: str r0,
; CHECK: str r1,
; CHECK: str r2,
; CHECK: bl throws_2
define void @no_stm(i32 %a, i32 %b, i32 %c, i32* %d) local_unnamed_addr noreturn "no-frame-pointer-elim"="true" {
entry:
%arrayidx = getelementptr inbounds i32, i32* %d, i32 2
store i32 %a, i32* %arrayidx, align 4
%arrayidx1 = getelementptr inbounds i32, i32* %d, i32 3
store i32 %b, i32* %arrayidx1, align 4
%arrayidx2 = getelementptr inbounds i32, i32* %d, i32 4
store i32 %c, i32* %arrayidx2, align 4
tail call void @throws_2(i32 %a, i32 %b, i32 %c, i32* %d) noreturn
unreachable
}


declare void @throws_1(i32, i32, i32) noreturn
declare void @throws_2(i32, i32, i32, i32*) noreturn

0 comments on commit 2910884

Please sign in to comment.