1 //===-- Thumb1InstrInfo.cpp - Thumb-1 Instruction Information -------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file contains the Thumb-1 implementation of the TargetInstrInfo class.
11 //===----------------------------------------------------------------------===//
13 #include "Thumb1InstrInfo.h"
14 #include "ARMSubtarget.h"
15 #include "llvm/CodeGen/MachineFrameInfo.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/CodeGen/MachineMemOperand.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstBuilder.h"
23 Thumb1InstrInfo::Thumb1InstrInfo(const ARMSubtarget
&STI
)
24 : ARMBaseInstrInfo(STI
), RI() {}
26 /// Return the noop instruction to use for a noop.
27 MCInst
Thumb1InstrInfo::getNop() const {
28 return MCInstBuilder(ARM::tMOVr
)
35 unsigned Thumb1InstrInfo::getUnindexedOpcode(unsigned Opc
) const {
39 void Thumb1InstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
40 MachineBasicBlock::iterator I
,
41 const DebugLoc
&DL
, MCRegister DestReg
,
42 MCRegister SrcReg
, bool KillSrc
) const {
43 // Need to check the arch.
44 MachineFunction
&MF
= *MBB
.getParent();
45 const ARMSubtarget
&st
= MF
.getSubtarget
<ARMSubtarget
>();
47 assert(ARM::GPRRegClass
.contains(DestReg
, SrcReg
) &&
48 "Thumb1 can only copy GPR registers");
50 if (st
.hasV6Ops() || ARM::hGPRRegClass
.contains(SrcReg
)
51 || !ARM::tGPRRegClass
.contains(DestReg
))
52 BuildMI(MBB
, I
, DL
, get(ARM::tMOVr
), DestReg
)
53 .addReg(SrcReg
, getKillRegState(KillSrc
))
54 .add(predOps(ARMCC::AL
));
56 // FIXME: Can also use 'mov hi, $src; mov $dst, hi',
57 // with hi as either r10 or r11.
59 const TargetRegisterInfo
*RegInfo
= st
.getRegisterInfo();
60 if (MBB
.computeRegisterLiveness(RegInfo
, ARM::CPSR
, I
)
61 == MachineBasicBlock::LQR_Dead
) {
62 BuildMI(MBB
, I
, DL
, get(ARM::tMOVSr
), DestReg
)
63 .addReg(SrcReg
, getKillRegState(KillSrc
))
64 ->addRegisterDead(ARM::CPSR
, RegInfo
);
68 // 'MOV lo, lo' is unpredictable on < v6, so use the stack to do it
69 BuildMI(MBB
, I
, DL
, get(ARM::tPUSH
))
70 .add(predOps(ARMCC::AL
))
71 .addReg(SrcReg
, getKillRegState(KillSrc
));
72 BuildMI(MBB
, I
, DL
, get(ARM::tPOP
))
73 .add(predOps(ARMCC::AL
))
74 .addReg(DestReg
, getDefRegState(true));
78 void Thumb1InstrInfo::
79 storeRegToStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
80 Register SrcReg
, bool isKill
, int FI
,
81 const TargetRegisterClass
*RC
,
82 const TargetRegisterInfo
*TRI
) const {
83 assert((RC
== &ARM::tGPRRegClass
||
84 (Register::isPhysicalRegister(SrcReg
) && isARMLowRegister(SrcReg
))) &&
87 if (RC
== &ARM::tGPRRegClass
||
88 (Register::isPhysicalRegister(SrcReg
) && isARMLowRegister(SrcReg
))) {
90 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
92 MachineFunction
&MF
= *MBB
.getParent();
93 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
94 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
95 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOStore
,
96 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
97 BuildMI(MBB
, I
, DL
, get(ARM::tSTRspi
))
98 .addReg(SrcReg
, getKillRegState(isKill
))
102 .add(predOps(ARMCC::AL
));
106 void Thumb1InstrInfo::
107 loadRegFromStackSlot(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator I
,
108 Register DestReg
, int FI
,
109 const TargetRegisterClass
*RC
,
110 const TargetRegisterInfo
*TRI
) const {
112 (RC
->hasSuperClassEq(&ARM::tGPRRegClass
) ||
113 (Register::isPhysicalRegister(DestReg
) && isARMLowRegister(DestReg
))) &&
114 "Unknown regclass!");
116 if (RC
->hasSuperClassEq(&ARM::tGPRRegClass
) ||
117 (Register::isPhysicalRegister(DestReg
) && isARMLowRegister(DestReg
))) {
119 if (I
!= MBB
.end()) DL
= I
->getDebugLoc();
121 MachineFunction
&MF
= *MBB
.getParent();
122 MachineFrameInfo
&MFI
= MF
.getFrameInfo();
123 MachineMemOperand
*MMO
= MF
.getMachineMemOperand(
124 MachinePointerInfo::getFixedStack(MF
, FI
), MachineMemOperand::MOLoad
,
125 MFI
.getObjectSize(FI
), MFI
.getObjectAlign(FI
));
126 BuildMI(MBB
, I
, DL
, get(ARM::tLDRspi
), DestReg
)
130 .add(predOps(ARMCC::AL
));
134 void Thumb1InstrInfo::expandLoadStackGuard(
135 MachineBasicBlock::iterator MI
) const {
136 MachineFunction
&MF
= *MI
->getParent()->getParent();
137 const TargetMachine
&TM
= MF
.getTarget();
138 if (TM
.isPositionIndependent())
139 expandLoadStackGuardBase(MI
, ARM::tLDRLIT_ga_pcrel
, ARM::tLDRi
);
141 expandLoadStackGuardBase(MI
, ARM::tLDRLIT_ga_abs
, ARM::tLDRi
);
144 bool Thumb1InstrInfo::canCopyGluedNodeDuringSchedule(SDNode
*N
) const {
145 // In Thumb1 the scheduler may need to schedule a cross-copy between GPRS and CPSR
146 // but this is not always possible there, so allow the Scheduler to clone tADCS and tSBCS
147 // even if they have glue.
148 // FIXME. Actually implement the cross-copy where it is possible (post v6)
149 // because these copies entail more spilling.
150 unsigned Opcode
= N
->getMachineOpcode();
151 if (Opcode
== ARM::tADCS
|| Opcode
== ARM::tSBCS
)