|
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