Index: include/llvm/CodeGen/LivePhysRegs.h =================================================================== --- include/llvm/CodeGen/LivePhysRegs.h +++ include/llvm/CodeGen/LivePhysRegs.h @@ -186,6 +186,9 @@ void computeAndAddLiveIns(LivePhysRegs &LiveRegs, MachineBasicBlock &MBB); +/// Convenience function combining computeLiveIns() and addLiveIns() for \p MBB. +void computeAndAddLiveIns(MachineBasicBlock &MBB); + /// Convenience function for recomputing live-in's for \p MBB. static inline void recomputeLiveIns(MachineBasicBlock &MBB) { LivePhysRegs LPR; Index: lib/CodeGen/LivePhysRegs.cpp =================================================================== --- lib/CodeGen/LivePhysRegs.cpp +++ lib/CodeGen/LivePhysRegs.cpp @@ -329,3 +329,8 @@ computeLiveIns(LiveRegs, MBB); addLiveIns(MBB, LiveRegs); } + +void llvm::computeAndAddLiveIns(MachineBasicBlock &MBB) { + LivePhysRegs LPR; + computeAndAddLiveIns(LPR, MBB); +} Index: lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- lib/Target/ARM/ARMISelLowering.cpp +++ lib/Target/ARM/ARMISelLowering.cpp @@ -9096,6 +9096,7 @@ } MI.eraseFromParent(); // The instruction is gone now. + computeAndAddLiveIns(*exitMBB); return BB; } @@ -9203,45 +9204,10 @@ .addReg(ARM::CPSR); MI.eraseFromParent(); + computeAndAddLiveIns(*ContBB); return ContBB; } -// The CPSR operand of SelectItr might be missing a kill marker -// because there were multiple uses of CPSR, and ISel didn't know -// which to mark. Figure out whether SelectItr should have had a -// kill marker, and set it if it should. Returns the correct kill -// marker value. -static bool checkAndUpdateCPSRKill(MachineBasicBlock::iterator SelectItr, - MachineBasicBlock* BB, - const TargetRegisterInfo* TRI) { - // Scan forward through BB for a use/def of CPSR. - MachineBasicBlock::iterator miI(std::next(SelectItr)); - for (MachineBasicBlock::iterator miE = BB->end(); miI != miE; ++miI) { - const MachineInstr& mi = *miI; - if (mi.readsRegister(ARM::CPSR)) - return false; - if (mi.definesRegister(ARM::CPSR)) - break; // Should have kill-flag - update below. - } - - // If we hit the end of the block, check whether CPSR is live into a - // successor. - if (miI == BB->end()) { - for (MachineBasicBlock::succ_iterator sItr = BB->succ_begin(), - sEnd = BB->succ_end(); - sItr != sEnd; ++sItr) { - MachineBasicBlock* succ = *sItr; - if (succ->isLiveIn(ARM::CPSR)) - return false; - } - } - - // We found a def, or hit the end of the basic block and CPSR wasn't live - // out. SelectMI should have a kill flag on CPSR. - SelectItr->addRegisterKilled(ARM::CPSR, TRI); - return true; -} - MachineBasicBlock * ARMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { @@ -9341,14 +9307,6 @@ F->insert(It, copy0MBB); F->insert(It, sinkMBB); - // Check whether CPSR is live past the tMOVCCr_pseudo. - const TargetRegisterInfo *TRI = Subtarget->getRegisterInfo(); - if (!MI.killsRegister(ARM::CPSR) && - !checkAndUpdateCPSRKill(MI, thisMBB, TRI)) { - copy0MBB->addLiveIn(ARM::CPSR); - sinkMBB->addLiveIn(ARM::CPSR); - } - // Transfer the remainder of BB and its successor edges to sinkMBB. sinkMBB->splice(sinkMBB->begin(), BB, std::next(MachineBasicBlock::iterator(MI)), BB->end()); @@ -9381,6 +9339,8 @@ .addMBB(thisMBB); MI.eraseFromParent(); // The pseudo instruction is gone now. + computeAndAddLiveIns(*sinkMBB); + computeAndAddLiveIns(*copy0MBB); return BB; } Index: test/CodeGen/ARM/expand-isel-pseudos-liveins-windows.mir =================================================================== --- /dev/null +++ test/CodeGen/ARM/expand-isel-pseudos-liveins-windows.mir @@ -0,0 +1,105 @@ +# RUN: llc -mtriple=thumbv7-unknown-windows-itanium -run-pass=expand-isel-pseudos %s -o - | FileCheck %s +--- | + target triple = "thumbv7-unknown-windows-itanium" + + @r = common global i32 0, align 4 + @c = common global i32 0, align 4 + + define arm_aapcs_vfpcc i32 @test1(i32 %n, i32 %d) { + entry: + %retval = alloca i32, align 4 + %n.addr = alloca i32, align 4 + %d.addr = alloca i32, align 4 + store i32 %n, i32* %n.addr, align 4 + store i32 %d, i32* %d.addr, align 4 + %0 = load i32, i32* %n.addr, align 4 + %1 = load i32, i32* %d.addr, align 4 + %div = sdiv i32 %0, %1 + %tobool = icmp ne i32 %div, 0 + br i1 %tobool, label %if.then, label %if.end + + if.then: ; preds = %entry + store i32 1, i32* %retval, align 4 + br label %return + + if.end: ; preds = %entry + store i32 0, i32* %retval, align 4 + br label %return + + return: ; preds = %if.end, %if.then + %2 = load i32, i32* %retval, align 4 + ret i32 %2 + } + +... +--- +name: test1 +alignment: 1 +tracksRegLiveness: true +hasWinCFI: false +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: tgpr, preferred-register: '' } + - { id: 2, class: gprnopc, preferred-register: '' } + - { id: 3, class: rgpr, preferred-register: '' } + - { id: 4, class: rgpr, preferred-register: '' } + - { id: 5, class: gpr, preferred-register: '' } +liveins: + - { reg: '$r0', virtual-reg: '%0' } + - { reg: '$r1', virtual-reg: '%1' } +frameInfo: + adjustsStack: true + hasCalls: true +fixedStack: [] +stack: + - { id: 0, name: retval, type: default, offset: 0, size: 4, alignment: 4, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, name: n.addr, type: default, offset: 0, size: 4, alignment: 4, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 2, name: d.addr, type: default, offset: 0, size: 4, alignment: 4, + stack-id: 0, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +constants: [] +body: | + bb.0.entry: + successors: %bb.1(0x50000000), %bb.2(0x30000000) + liveins: $r0, $r1 + + %1:tgpr = COPY $r1 + %0:gpr = COPY $r0 + t2STRi12 %1, %stack.2.d.addr, 0, 14, $noreg :: (store 4 into %ir.d.addr) + WIN__DBZCHK %1, implicit-def dead $cpsr + t2STRi12 %0, %stack.1.n.addr, 0, 14, $noreg :: (store 4 into %ir.n.addr) + ADJCALLSTACKDOWN 0, 0, 14, $noreg, implicit-def dead $sp, implicit $sp + tBL 14, $noreg, &__rt_sdiv, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit $r0, implicit $r1, implicit-def $sp, implicit-def $r0 + ADJCALLSTACKUP 0, 0, 14, $noreg, implicit-def dead $sp, implicit $sp + %2:gprnopc = COPY $r0 + t2CMPri %2, 0, 14, $noreg, implicit-def $cpsr + t2Bcc %bb.2, 0, $cpsr + t2B %bb.1, 14, $noreg + + bb.1.if.then: + successors: %bb.3(0x80000000) + + %4:rgpr = t2MOVi 1, 14, $noreg, $noreg + t2STRi12 killed %4, %stack.0.retval, 0, 14, $noreg :: (store 4 into %ir.retval) + t2B %bb.3, 14, $noreg + + bb.2.if.end: + successors: %bb.3(0x80000000) + + %3:rgpr = t2MOVi 0, 14, $noreg, $noreg + t2STRi12 killed %3, %stack.0.retval, 0, 14, $noreg :: (store 4 into %ir.retval) + + bb.3.return: + %5:gpr = t2LDRi12 %stack.0.retval, 0, 14, $noreg :: (dereferenceable load 4 from %ir.retval) + $r0 = COPY %5 + tBX_RET 14, $noreg, implicit $r0 + +... +# CHECK-LABEL: name: test1 +# CHECK-LABEL: bb.4: +# CHECK-NEXT: successors: +# CHECK-NEXT: liveins: $r1, $r0 Index: test/CodeGen/ARM/expand-isel-pseudos-liveins.mir =================================================================== --- /dev/null +++ test/CodeGen/ARM/expand-isel-pseudos-liveins.mir @@ -0,0 +1,106 @@ +# Check liveins are properly setwhen new MBBs are created in +# expand-isel-pseudos. + +# RUN: llc -run-pass=expand-isel-pseudos %s -o - | FileCheck %s +--- | + target triple = "thumb-unknown-unknown-eabi" + + define i32 @test_copy_struct_byval(i32 %x) { + entry: + unreachable + } + + define { i32, i32 } @test_slt_not(i32 %c, i32 %d, i64 %a, i64 %b) { + entry: + %cmp = icmp slt i64 %a, %b + %not = xor i1 %cmp, true + %r1 = zext i1 %cmp to i32 + %r2 = zext i1 %not to i32 + %z = insertvalue { i32, i32 } undef, i32 %r1, 0 + %z2 = insertvalue { i32, i32 } %z, i32 %r2, 1 + ret { i32, i32 } %z2 + } +... +--- +# CHECK-LABEL: name: test_copy_struct_byval +# CHECK-LABEL: bb.2.entry: +# CHECK-NEXT: liveins: $r1 +name: test_copy_struct_byval +alignment: 2 +tracksRegLiveness: true +registers: + - { id: 0, class: gpr, preferred-register: '' } + - { id: 1, class: gpr, preferred-register: '' } + - { id: 2, class: gpr, preferred-register: '' } + - { id: 3, class: gpr, preferred-register: '' } +liveins: + - { reg: '$r0', virtual-reg: '%0' } + - { reg: '$r1', virtual-reg: '%1' } +body: | + bb.0.entry: + liveins: $r0, $r1 + %0:gpr = COPY $r1 + ADJCALLSTACKDOWN 136, 0, 14, $noreg, implicit-def dead $sp, implicit $sp + %1:gpr = COPY $sp + %2:gpr = COPY $r0 + COPY_STRUCT_BYVAL_I32 %2, %0, 72, 8 + COPY_STRUCT_BYVAL_I32 %2, %0, 72, 8 + %3:gpr = COPY $r1 + STRi12 killed %3, %1, 132, 14, $noreg :: (store 4 into stack + 132) + ADJCALLSTACKUP 136, 0, 14, $noreg, implicit-def dead $sp, implicit $sp + BX_RET 14, $noreg +... +--- +# CHECK-LABEL: name: test_slt_not +# CHECK-LABEL: bb.1.entry: +# CHECK-NEXT: successors: +# CHECK-NEXT: liveins: $cpsr +# CHECK-LABEL: bb.2.entry: +# CHECK-NEXT: successors: +# CHECK-NEXT: liveins: $cpsr +name: test_slt_not +alignment: 1 +tracksRegLiveness: true +registers: + - { id: 0, class: tgpr, preferred-register: '' } + - { id: 1, class: tgpr, preferred-register: '' } + - { id: 2, class: tgpr, preferred-register: '' } + - { id: 3, class: tgpr, preferred-register: '' } + - { id: 4, class: tgpr, preferred-register: '' } + - { id: 5, class: tgpr, preferred-register: '' } + - { id: 6, class: tgpr, preferred-register: '' } + - { id: 7, class: tgpr, preferred-register: '' } + - { id: 8, class: tgpr, preferred-register: '' } + - { id: 9, class: tgpr, preferred-register: '' } + - { id: 10, class: tgpr, preferred-register: '' } + - { id: 11, class: tgpr, preferred-register: '' } +liveins: + - { reg: '$r2', virtual-reg: '%2' } + - { reg: '$r3', virtual-reg: '%3' } +frameInfo: +fixedStack: + - { id: 0, type: default, offset: 4, size: 4, alignment: 4, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } + - { id: 1, type: default, offset: 0, size: 4, alignment: 8, stack-id: 0, + isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true, + debug-info-variable: '', debug-info-expression: '', debug-info-location: '' } +body: | + bb.0.entry: + liveins: $r2, $r3 + + %3:tgpr = COPY $r3 + %2:tgpr = COPY $r2 + %4:tgpr, dead $cpsr = tMOVi8 1, 14, $noreg + %5:tgpr, dead $cpsr = tMOVi8 0, 14, $noreg + %6:tgpr = tLDRspi %fixed-stack.0, 0, 14, $noreg :: (load 4 from %fixed-stack.0) + %7:tgpr = tLDRspi %fixed-stack.1, 0, 14, $noreg :: (load 4 from %fixed-stack.1, align 8) + %8:tgpr, $cpsr = tSUBrr %2, killed %7, 14, $noreg + %9:tgpr, $cpsr = tSBC %3, killed %6, 14, $noreg, implicit $cpsr + %10:tgpr = tMOVCCr_pseudo %5, %4, 11, $cpsr + %11:tgpr = tMOVCCr_pseudo %5, %4, 10, $cpsr + $r0 = COPY %10 + $r1 = COPY %11 + tBX_RET 14, $noreg, implicit $r0, implicit $r1 + +...