diff --git a/lib/CodeGen/VirtRegMap.cpp b/lib/CodeGen/VirtRegMap.cpp index 47772e7c02f..29ed30cb51a 100644 --- a/lib/CodeGen/VirtRegMap.cpp +++ b/lib/CodeGen/VirtRegMap.cpp @@ -278,6 +278,11 @@ void VirtRegRewriter::rewrite() { PhysRegs.clear(); 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(); MBBI != MBBE; ++MBBI) { DEBUG(MBBI->print(dbgs(), Indexes)); @@ -287,9 +292,12 @@ void VirtRegRewriter::rewrite() { MachineInstr *MI = MII; ++MII; - // Check if this instruction is a call to a noreturn function. - // If so, all the definitions set by this instruction can be ignored. - if (IsExitBB && MI->isCall()) + // Check if this instruction is a call to a noreturn function. If this + // is a call to noreturn function and we don't need the stack unwinding + // 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(), MOE = MI->operands_end(); MOI != MOE; ++MOI) { MachineOperand &MO = *MOI; @@ -305,6 +313,7 @@ void VirtRegRewriter::rewrite() { NoReturnInsts.insert(MI); break; } + } for (MachineInstr::mop_iterator MOI = MI->operands_begin(), MOE = MI->operands_end(); MOI != MOE; ++MOI) { diff --git a/test/CodeGen/ARM/noreturn.ll b/test/CodeGen/ARM/noreturn.ll index 4c876cec9c1..edc3333455d 100644 --- a/test/CodeGen/ARM/noreturn.ll +++ b/test/CodeGen/ARM/noreturn.ll @@ -43,6 +43,23 @@ entry: 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 declare void @overflow_with_unwind() #1