Keep the link register for uwtable.

The function with uwtable attribute might be visited by the
stack unwinder, thus the link register should be considered
as clobbered after the execution of the branch and link
instruction (i.e. the definition of the machine instruction
can't be ignored) even when the callee function are marked
with noreturn.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@202165 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Logan Chien 2014-02-25 16:57:28 +00:00
parent 6dc9f732ce
commit 28713bdebc
2 changed files with 29 additions and 3 deletions

View File

@ -278,6 +278,11 @@ void VirtRegRewriter::rewrite() {
PhysRegs.clear(); PhysRegs.clear();
PhysRegs.setUniverse(TRI->getNumRegs()); PhysRegs.setUniverse(TRI->getNumRegs());
// The function with uwtable should guarantee that the stack unwinder
// can unwind the stack to the previous frame. Thus, we can't apply the
// noreturn optimization if the caller function has uwtable attribute.
bool HasUWTable = MF->getFunction()->hasFnAttribute(Attribute::UWTable);
for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end(); for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end();
MBBI != MBBE; ++MBBI) { MBBI != MBBE; ++MBBI) {
DEBUG(MBBI->print(dbgs(), Indexes)); DEBUG(MBBI->print(dbgs(), Indexes));
@ -287,9 +292,12 @@ void VirtRegRewriter::rewrite() {
MachineInstr *MI = MII; MachineInstr *MI = MII;
++MII; ++MII;
// Check if this instruction is a call to a noreturn function. // Check if this instruction is a call to a noreturn function. If this
// If so, all the definitions set by this instruction can be ignored. // is a call to noreturn function and we don't need the stack unwinding
if (IsExitBB && MI->isCall()) // functionality (i.e. this function does not have uwtable attribute and
// the callee function has the nounwind attribute), then we can ignore
// the definitions set by this instruction.
if (!HasUWTable && IsExitBB && MI->isCall()) {
for (MachineInstr::mop_iterator MOI = MI->operands_begin(), for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
MOE = MI->operands_end(); MOI != MOE; ++MOI) { MOE = MI->operands_end(); MOI != MOE; ++MOI) {
MachineOperand &MO = *MOI; MachineOperand &MO = *MOI;
@ -305,6 +313,7 @@ void VirtRegRewriter::rewrite() {
NoReturnInsts.insert(MI); NoReturnInsts.insert(MI);
break; break;
} }
}
for (MachineInstr::mop_iterator MOI = MI->operands_begin(), for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
MOE = MI->operands_end(); MOI != MOE; ++MOI) { MOE = MI->operands_end(); MOI != MOE; ++MOI) {

View File

@ -43,6 +43,23 @@ entry:
unreachable unreachable
} }
; Test case for uwtable
define i32 @test4() uwtable {
; CHECK-LABEL: @test4
; CHECK: push
entry:
tail call void @overflow() #0
unreachable
}
define i32 @test5() uwtable {
; CHECK-LABEL: @test5
; CHECK: push
entry:
tail call void @overflow_with_unwind() #1
unreachable
}
; Function Attrs: noreturn ; Function Attrs: noreturn
declare void @overflow_with_unwind() #1 declare void @overflow_with_unwind() #1