|  | 
| 12 | 12 | 
 | 
| 13 | 13 | #include "Thumb1InstrInfo.h" | 
| 14 | 14 | #include "ARMSubtarget.h" | 
|  | 15 | +#include "llvm/ADT/BitVector.h" | 
|  | 16 | +#include "llvm/CodeGen/LiveRegUnits.h" | 
| 15 | 17 | #include "llvm/CodeGen/MachineFrameInfo.h" | 
| 16 | 18 | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
| 17 | 19 | #include "llvm/CodeGen/MachineMemOperand.h" | 
| @@ -47,24 +49,57 @@ void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock &MBB, | 
| 47 | 49 |   assert(ARM::GPRRegClass.contains(DestReg, SrcReg) && | 
| 48 | 50 |          "Thumb1 can only copy GPR registers"); | 
| 49 | 51 | 
 | 
| 50 |  | -  if (st.hasV6Ops() || ARM::hGPRRegClass.contains(SrcReg) | 
| 51 |  | -      || !ARM::tGPRRegClass.contains(DestReg)) | 
|  | 52 | +  if (st.hasV6Ops() || ARM::hGPRRegClass.contains(SrcReg) || | 
|  | 53 | +      !ARM::tGPRRegClass.contains(DestReg)) | 
| 52 | 54 |     BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) | 
| 53 | 55 |         .addReg(SrcReg, getKillRegState(KillSrc)) | 
| 54 | 56 |         .add(predOps(ARMCC::AL)); | 
| 55 | 57 |   else { | 
| 56 |  | -    // FIXME: Can also use 'mov hi, $src; mov $dst, hi', | 
| 57 |  | -    // with hi as either r10 or r11. | 
| 58 |  | - | 
| 59 | 58 |     const TargetRegisterInfo *RegInfo = st.getRegisterInfo(); | 
| 60 |  | -    if (MBB.computeRegisterLiveness(RegInfo, ARM::CPSR, I) | 
| 61 |  | -        == MachineBasicBlock::LQR_Dead) { | 
|  | 59 | +    LiveRegUnits UsedRegs(*RegInfo); | 
|  | 60 | +    UsedRegs.addLiveOuts(MBB); | 
|  | 61 | + | 
|  | 62 | +    auto InstUpToI = MBB.end(); | 
|  | 63 | +    while (InstUpToI != I) | 
|  | 64 | +      // The pre-decrement is on purpose here. | 
|  | 65 | +      // We want to have the liveness right before I. | 
|  | 66 | +      UsedRegs.stepBackward(*--InstUpToI); | 
|  | 67 | + | 
|  | 68 | +    if (UsedRegs.available(ARM::CPSR)) { | 
| 62 | 69 |       BuildMI(MBB, I, DL, get(ARM::tMOVSr), DestReg) | 
| 63 | 70 |           .addReg(SrcReg, getKillRegState(KillSrc)) | 
| 64 | 71 |           ->addRegisterDead(ARM::CPSR, RegInfo); | 
| 65 | 72 |       return; | 
| 66 | 73 |     } | 
| 67 | 74 | 
 | 
|  | 75 | +    // Use high register to move source to destination | 
|  | 76 | +    // if movs is not an option. | 
|  | 77 | +    BitVector Allocatable = RegInfo->getAllocatableSet( | 
|  | 78 | +        MF, RegInfo->getRegClass(ARM::hGPRRegClassID)); | 
|  | 79 | + | 
|  | 80 | +    Register TmpReg = ARM::NoRegister; | 
|  | 81 | +    // Prefer R12 as it is known to not be preserved anyway | 
|  | 82 | +    if (UsedRegs.available(ARM::R12) && Allocatable.test(ARM::R12)) { | 
|  | 83 | +      TmpReg = ARM::R12; | 
|  | 84 | +    } else { | 
|  | 85 | +      for (Register Reg : Allocatable.set_bits()) { | 
|  | 86 | +        if (UsedRegs.available(Reg)) { | 
|  | 87 | +          TmpReg = Reg; | 
|  | 88 | +          break; | 
|  | 89 | +        } | 
|  | 90 | +      } | 
|  | 91 | +    } | 
|  | 92 | + | 
|  | 93 | +    if (TmpReg) { | 
|  | 94 | +      BuildMI(MBB, I, DL, get(ARM::tMOVr), TmpReg) | 
|  | 95 | +          .addReg(SrcReg, getKillRegState(KillSrc)) | 
|  | 96 | +          .add(predOps(ARMCC::AL)); | 
|  | 97 | +      BuildMI(MBB, I, DL, get(ARM::tMOVr), DestReg) | 
|  | 98 | +          .addReg(TmpReg, getKillRegState(true)) | 
|  | 99 | +          .add(predOps(ARMCC::AL)); | 
|  | 100 | +      return; | 
|  | 101 | +    } | 
|  | 102 | + | 
| 68 | 103 |     // 'MOV lo, lo' is unpredictable on < v6, so use the stack to do it | 
| 69 | 104 |     BuildMI(MBB, I, DL, get(ARM::tPUSH)) | 
| 70 | 105 |         .add(predOps(ARMCC::AL)) | 
|  | 
0 commit comments