diff --git a/llvm/lib/CodeGen/MachineSink.cpp b/llvm/lib/CodeGen/MachineSink.cpp --- a/llvm/lib/CodeGen/MachineSink.cpp +++ b/llvm/lib/CodeGen/MachineSink.cpp @@ -596,6 +596,54 @@ FindSuccToSinkTo(MI, SuccToSinkTo, BreakPHIEdge, AllSuccessors)) return isProfitableToSinkTo(Reg, MI, SuccToSinkTo, MBB2, AllSuccessors); + // If this instruction is inside a loop and sinking this instruction can make + // more registers live range shorten, it is still prifitable. + MachineLoop *ML = LI->getLoopFor(MBB); + if (!ML) + return false; + int RegClassWeightCount = 0; + for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI.getOperand(i); + // Ignore non-register operands. + if (!MO.isReg()) + continue; + Register Reg = MO.getReg(); + if (Reg == 0) + continue; + + // Don't handle physical register. + if (Register::isPhysicalRegister(Reg)) + return false; + + const TargetRegisterClass *RC = MRI->getRegClass(Reg); + RegClassWeight W = TRI->getRegClassWeight(RC); + // Users for the defs are all dominated by SuccToSinkTo. + if (MO.isDef()) { + // This def register's live range is shortened after sinking. + bool LocalUse = false; + if (!AllUsesDominatedByBlock(Reg, SuccToSinkTo, MBB, BreakPHIEdge, + LocalUse)) + return false; + RegClassWeightCount += W.RegWeight; + } else { + MachineInstr *DefMI = MRI->getVRegDef(Reg); + // DefMI is defined outside of loop. There should be no live range + // impact for this operand. Defination outside of loop means: + // 1: defination is outside of loop. + // 2: defination is in this loop, but it is a PHI in the loop header. + if (LI->getLoopFor(DefMI->getParent()) != ML || + (DefMI->isPHI() && LI->isLoopHeader(DefMI->getParent()))) + continue; + // DefMI is inside the loop. + RegClassWeightCount -= W.RegWeight; + } + } + // If there is no register class weight degradation, we treat it as + // profitable. Because after sinking all users of one defination inside the + // loop, we can also sink the defination later. + if (RegClassWeightCount >= 0) + return true; + // If SuccToSinkTo is final destination and it is a post dominator of current // block then it is not profitable to sink MI into SuccToSinkTo block. return false; diff --git a/llvm/test/CodeGen/PowerPC/sink-down-more-instructions.ll b/llvm/test/CodeGen/PowerPC/sink-down-more-instructions.ll --- a/llvm/test/CodeGen/PowerPC/sink-down-more-instructions.ll +++ b/llvm/test/CodeGen/PowerPC/sink-down-more-instructions.ll @@ -9,32 +9,31 @@ ; CHECK-NEXT: blt cr0, .LBB0_8 ; CHECK-NEXT: # %bb.1: ; CHECK-NEXT: addi r4, r5, -4 -; CHECK-NEXT: addi r8, r6, -4 -; CHECK-NEXT: clrldi r7, r7, 32 +; CHECK-NEXT: clrldi r8, r7, 32 +; CHECK-NEXT: addi r7, r6, -4 ; CHECK-NEXT: li r5, 0 -; CHECK-NEXT: mtctr r7 -; CHECK-NEXT: lis r7, -30584 +; CHECK-NEXT: mtctr r8 +; CHECK-NEXT: lis r8, -30584 ; CHECK-NEXT: li r6, 0 ; CHECK-NEXT: cmplwi r3, 3 ; CHECK-NEXT: cmplwi cr1, r3, 1 -; CHECK-NEXT: ori r7, r7, 34953 +; CHECK-NEXT: ori r8, r8, 34953 ; CHECK-NEXT: b .LBB0_4 ; CHECK-NEXT: .p2align 4 ; CHECK-NEXT: .LBB0_2: -; CHECK-NEXT: mulhwu r9, r6, r7 +; CHECK-NEXT: mulhwu r9, r6, r8 ; CHECK-NEXT: srwi r9, r9, 4 ; CHECK-NEXT: mulli r9, r9, 30 ; CHECK-NEXT: sub r9, r6, r9 ; CHECK-NEXT: .LBB0_3: ; CHECK-NEXT: addi r6, r6, 1 -; CHECK-NEXT: add r9, r9, r5 -; CHECK-NEXT: stw r9, 4(r8) -; CHECK-NEXT: mr r8, r3 +; CHECK-NEXT: add r5, r3, r5 +; CHECK-NEXT: add r3, r9, r5 +; CHECK-NEXT: stw r3, 4(r7) +; CHECK-NEXT: addi r7, r7, 4 ; CHECK-NEXT: bdz .LBB0_8 ; CHECK-NEXT: .LBB0_4: -; CHECK-NEXT: lwzu r9, 4(r4) -; CHECK-NEXT: addi r3, r8, 4 -; CHECK-NEXT: add r5, r9, r5 +; CHECK-NEXT: lwzu r3, 4(r4) ; CHECK-NEXT: beq cr0, .LBB0_7 ; CHECK-NEXT: # %bb.5: ; CHECK-NEXT: bne cr1, .LBB0_2