#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/Function.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
SmallVector<unsigned, 8> SuperDeads;
SmallVector<unsigned, 8> SuperDefs;
SmallVector<unsigned, 8> SuperKills;
+ SmallPtrSet<const MachineInstr *, 4> NoReturnInsts;
for (MachineFunction::iterator MBBI = MF->begin(), MBBE = MF->end();
MBBI != MBBE; ++MBBI) {
DEBUG(MBBI->print(dbgs(), Indexes));
+ bool IsExitBB = MBBI->succ_empty();
for (MachineBasicBlock::instr_iterator
MII = MBBI->instr_begin(), MIE = MBBI->instr_end(); MII != MIE;) {
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())
+ for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
+ MOE = MI->operands_end(); MOI != MOE; ++MOI) {
+ MachineOperand &MO = *MOI;
+ if (!MO.isGlobal())
+ continue;
+ const Function *Func = dyn_cast<Function>(MO.getGlobal());
+ if (!Func || !Func->hasFnAttribute(Attribute::NoReturn))
+ continue;
+ NoReturnInsts.insert(MI);
+ break;
+ }
+
for (MachineInstr::mop_iterator MOI = MI->operands_begin(),
MOE = MI->operands_end(); MOI != MOE; ++MOI) {
MachineOperand &MO = *MOI;
}
// Tell MRI about physical registers in use.
- for (unsigned Reg = 1, RegE = TRI->getNumRegs(); Reg != RegE; ++Reg)
- if (!MRI->reg_nodbg_empty(Reg))
- MRI->setPhysRegUsed(Reg);
+ if (NoReturnInsts.empty()) {
+ for (unsigned Reg = 1, RegE = TRI->getNumRegs(); Reg != RegE; ++Reg)
+ if (!MRI->reg_nodbg_empty(Reg))
+ MRI->setPhysRegUsed(Reg);
+ } else {
+ for (unsigned Reg = 1, RegE = TRI->getNumRegs(); Reg != RegE; ++Reg) {
+ if (MRI->reg_nodbg_empty(Reg))
+ continue;
+ // Check if this register has a use that will impact the rest of the
+ // code. Uses in debug and noreturn instructions do not impact the
+ // generated code.
+ for (MachineRegisterInfo::reg_nodbg_iterator It =
+ MRI->reg_nodbg_begin(Reg),
+ EndIt = MRI->reg_nodbg_end(); It != EndIt; ++It) {
+ if (!NoReturnInsts.count(&(*It))) {
+ MRI->setPhysRegUsed(Reg);
+ break;
+ }
+ }
+ }
+ }
}
--- /dev/null
+; RUN: llc -O3 -o - %s | FileCheck %s
+; Test case from PR16882.
+target triple = "thumbv7s-apple-ios"
+
+; Function Attrs: noreturn
+define i32 @test1() #0 {
+; CHECK-LABEL: @test1
+; CHECK-NOT: push
+entry:
+ tail call void @overflow() #0
+ unreachable
+}
+
+; Function Attrs: noreturn
+declare void @overflow() #0
+
+define i32 @test2(i32 %x, i32 %y) {
+; CHECK-LABEL: @test2
+; CHECK-NOT: push
+; CHECK-NOT: pop
+entry:
+ %conv = sext i32 %x to i64
+ %conv1 = sext i32 %y to i64
+ %mul = mul nsw i64 %conv1, %conv
+ %conv2 = trunc i64 %mul to i32
+ %conv3 = sext i32 %conv2 to i64
+ %cmp = icmp eq i64 %mul, %conv3
+ br i1 %cmp, label %if.end, label %if.then
+
+if.then: ; preds = %entry
+ tail call void @overflow() #0
+ unreachable
+
+if.end: ; preds = %entry
+ ret i32 %conv2
+}
+
+attributes #0 = { noreturn }