1 //===-- MSP430InstrInfo.cpp - MSP430 Instruction Information --------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains the MSP430 implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12
13 #include "MSP430InstrInfo.h"
14 #include "MSP430.h"
15 #include "llvm/CodeGen/MachineFrameInfo.h"
16 #include "llvm/CodeGen/MachineInstrBuilder.h"
17 #include "llvm/Support/ErrorHandling.h"
18
19 using namespace llvm;
20
21 #define GET_INSTRINFO_CTOR_DTOR
22 #include "MSP430GenInstrInfo.inc"
23
24 // Pin the vtable to this file.
anchor()25 void MSP430InstrInfo::anchor() {}
26
MSP430InstrInfo(MSP430Subtarget & STI)27 MSP430InstrInfo::MSP430InstrInfo(MSP430Subtarget &STI)
28 : MSP430GenInstrInfo(MSP430::ADJCALLSTACKDOWN, MSP430::ADJCALLSTACKUP),
29 RI() {}
30
storeRegToStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register SrcReg,bool isKill,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg,MachineInstr::MIFlag Flags) const31 void MSP430InstrInfo::storeRegToStackSlot(
32 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register SrcReg,
33 bool isKill, int FrameIdx, const TargetRegisterClass *RC,
34 const TargetRegisterInfo *TRI, Register VReg,
35 MachineInstr::MIFlag Flags) const {
36 DebugLoc DL;
37 if (MI != MBB.end()) DL = MI->getDebugLoc();
38 MachineFunction &MF = *MBB.getParent();
39 MachineFrameInfo &MFI = MF.getFrameInfo();
40
41 MachineMemOperand *MMO = MF.getMachineMemOperand(
42 MachinePointerInfo::getFixedStack(MF, FrameIdx),
43 MachineMemOperand::MOStore, MFI.getObjectSize(FrameIdx),
44 MFI.getObjectAlign(FrameIdx));
45
46 if (RC == &MSP430::GR16RegClass)
47 BuildMI(MBB, MI, DL, get(MSP430::MOV16mr))
48 .addFrameIndex(FrameIdx).addImm(0)
49 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
50 else if (RC == &MSP430::GR8RegClass)
51 BuildMI(MBB, MI, DL, get(MSP430::MOV8mr))
52 .addFrameIndex(FrameIdx).addImm(0)
53 .addReg(SrcReg, getKillRegState(isKill)).addMemOperand(MMO);
54 else
55 llvm_unreachable("Cannot store this register to stack slot!");
56 }
57
loadRegFromStackSlot(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,Register DestReg,int FrameIdx,const TargetRegisterClass * RC,const TargetRegisterInfo * TRI,Register VReg,MachineInstr::MIFlag Flags) const58 void MSP430InstrInfo::loadRegFromStackSlot(
59 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, Register DestReg,
60 int FrameIdx, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
61 Register VReg, MachineInstr::MIFlag Flags) const {
62 DebugLoc DL;
63 if (MI != MBB.end()) DL = MI->getDebugLoc();
64 MachineFunction &MF = *MBB.getParent();
65 MachineFrameInfo &MFI = MF.getFrameInfo();
66
67 MachineMemOperand *MMO = MF.getMachineMemOperand(
68 MachinePointerInfo::getFixedStack(MF, FrameIdx),
69 MachineMemOperand::MOLoad, MFI.getObjectSize(FrameIdx),
70 MFI.getObjectAlign(FrameIdx));
71
72 if (RC == &MSP430::GR16RegClass)
73 BuildMI(MBB, MI, DL, get(MSP430::MOV16rm))
74 .addReg(DestReg, getDefRegState(true)).addFrameIndex(FrameIdx)
75 .addImm(0).addMemOperand(MMO);
76 else if (RC == &MSP430::GR8RegClass)
77 BuildMI(MBB, MI, DL, get(MSP430::MOV8rm))
78 .addReg(DestReg, getDefRegState(true)).addFrameIndex(FrameIdx)
79 .addImm(0).addMemOperand(MMO);
80 else
81 llvm_unreachable("Cannot store this register to stack slot!");
82 }
83
copyPhysReg(MachineBasicBlock & MBB,MachineBasicBlock::iterator I,const DebugLoc & DL,Register DestReg,Register SrcReg,bool KillSrc,bool RenamableDest,bool RenamableSrc) const84 void MSP430InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
85 MachineBasicBlock::iterator I,
86 const DebugLoc &DL, Register DestReg,
87 Register SrcReg, bool KillSrc,
88 bool RenamableDest, bool RenamableSrc) const {
89 unsigned Opc;
90 if (MSP430::GR16RegClass.contains(DestReg, SrcReg))
91 Opc = MSP430::MOV16rr;
92 else if (MSP430::GR8RegClass.contains(DestReg, SrcReg))
93 Opc = MSP430::MOV8rr;
94 else
95 llvm_unreachable("Impossible reg-to-reg copy");
96
97 BuildMI(MBB, I, DL, get(Opc), DestReg)
98 .addReg(SrcReg, getKillRegState(KillSrc));
99 }
100
removeBranch(MachineBasicBlock & MBB,int * BytesRemoved) const101 unsigned MSP430InstrInfo::removeBranch(MachineBasicBlock &MBB,
102 int *BytesRemoved) const {
103 assert(!BytesRemoved && "code size not handled");
104
105 MachineBasicBlock::iterator I = MBB.end();
106 unsigned Count = 0;
107
108 while (I != MBB.begin()) {
109 --I;
110 if (I->isDebugInstr())
111 continue;
112 if (I->getOpcode() != MSP430::JMP &&
113 I->getOpcode() != MSP430::JCC &&
114 I->getOpcode() != MSP430::Bi &&
115 I->getOpcode() != MSP430::Br &&
116 I->getOpcode() != MSP430::Bm)
117 break;
118 // Remove the branch.
119 I->eraseFromParent();
120 I = MBB.end();
121 ++Count;
122 }
123
124 return Count;
125 }
126
127 bool MSP430InstrInfo::
reverseBranchCondition(SmallVectorImpl<MachineOperand> & Cond) const128 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
129 assert(Cond.size() == 1 && "Invalid Xbranch condition!");
130
131 MSP430CC::CondCodes CC = static_cast<MSP430CC::CondCodes>(Cond[0].getImm());
132
133 switch (CC) {
134 default: llvm_unreachable("Invalid branch condition!");
135 case MSP430CC::COND_E:
136 CC = MSP430CC::COND_NE;
137 break;
138 case MSP430CC::COND_NE:
139 CC = MSP430CC::COND_E;
140 break;
141 case MSP430CC::COND_L:
142 CC = MSP430CC::COND_GE;
143 break;
144 case MSP430CC::COND_GE:
145 CC = MSP430CC::COND_L;
146 break;
147 case MSP430CC::COND_HS:
148 CC = MSP430CC::COND_LO;
149 break;
150 case MSP430CC::COND_LO:
151 CC = MSP430CC::COND_HS;
152 break;
153 }
154
155 Cond[0].setImm(CC);
156 return false;
157 }
158
analyzeBranch(MachineBasicBlock & MBB,MachineBasicBlock * & TBB,MachineBasicBlock * & FBB,SmallVectorImpl<MachineOperand> & Cond,bool AllowModify) const159 bool MSP430InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
160 MachineBasicBlock *&TBB,
161 MachineBasicBlock *&FBB,
162 SmallVectorImpl<MachineOperand> &Cond,
163 bool AllowModify) const {
164 // Start from the bottom of the block and work up, examining the
165 // terminator instructions.
166 MachineBasicBlock::iterator I = MBB.end();
167 while (I != MBB.begin()) {
168 --I;
169 if (I->isDebugInstr())
170 continue;
171
172 // Working from the bottom, when we see a non-terminator
173 // instruction, we're done.
174 if (!isUnpredicatedTerminator(*I))
175 break;
176
177 // A terminator that isn't a branch can't easily be handled
178 // by this analysis.
179 if (!I->isBranch())
180 return true;
181
182 // Cannot handle indirect branches.
183 if (I->getOpcode() == MSP430::Br ||
184 I->getOpcode() == MSP430::Bm)
185 return true;
186
187 // Handle unconditional branches.
188 if (I->getOpcode() == MSP430::JMP || I->getOpcode() == MSP430::Bi) {
189 if (!AllowModify) {
190 TBB = I->getOperand(0).getMBB();
191 continue;
192 }
193
194 // If the block has any instructions after a JMP, delete them.
195 MBB.erase(std::next(I), MBB.end());
196 Cond.clear();
197 FBB = nullptr;
198
199 // Delete the JMP if it's equivalent to a fall-through.
200 if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
201 TBB = nullptr;
202 I->eraseFromParent();
203 I = MBB.end();
204 continue;
205 }
206
207 // TBB is used to indicate the unconditinal destination.
208 TBB = I->getOperand(0).getMBB();
209 continue;
210 }
211
212 // Handle conditional branches.
213 assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch");
214 MSP430CC::CondCodes BranchCode =
215 static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm());
216 if (BranchCode == MSP430CC::COND_INVALID)
217 return true; // Can't handle weird stuff.
218
219 // Working from the bottom, handle the first conditional branch.
220 if (Cond.empty()) {
221 FBB = TBB;
222 TBB = I->getOperand(0).getMBB();
223 Cond.push_back(MachineOperand::CreateImm(BranchCode));
224 continue;
225 }
226
227 // Handle subsequent conditional branches. Only handle the case where all
228 // conditional branches branch to the same destination.
229 assert(Cond.size() == 1);
230 assert(TBB);
231
232 // Only handle the case where all conditional branches branch to
233 // the same destination.
234 if (TBB != I->getOperand(0).getMBB())
235 return true;
236
237 MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm();
238 // If the conditions are the same, we can leave them alone.
239 if (OldBranchCode == BranchCode)
240 continue;
241
242 return true;
243 }
244
245 return false;
246 }
247
insertBranch(MachineBasicBlock & MBB,MachineBasicBlock * TBB,MachineBasicBlock * FBB,ArrayRef<MachineOperand> Cond,const DebugLoc & DL,int * BytesAdded) const248 unsigned MSP430InstrInfo::insertBranch(MachineBasicBlock &MBB,
249 MachineBasicBlock *TBB,
250 MachineBasicBlock *FBB,
251 ArrayRef<MachineOperand> Cond,
252 const DebugLoc &DL,
253 int *BytesAdded) const {
254 // Shouldn't be a fall through.
255 assert(TBB && "insertBranch must not be told to insert a fallthrough");
256 assert((Cond.size() == 1 || Cond.size() == 0) &&
257 "MSP430 branch conditions have one component!");
258 assert(!BytesAdded && "code size not handled");
259
260 if (Cond.empty()) {
261 // Unconditional branch?
262 assert(!FBB && "Unconditional branch with multiple successors!");
263 BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(TBB);
264 return 1;
265 }
266
267 // Conditional branch.
268 unsigned Count = 0;
269 BuildMI(&MBB, DL, get(MSP430::JCC)).addMBB(TBB).addImm(Cond[0].getImm());
270 ++Count;
271
272 if (FBB) {
273 // Two-way Conditional branch. Insert the second branch.
274 BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(FBB);
275 ++Count;
276 }
277 return Count;
278 }
279
280 /// GetInstSize - Return the number of bytes of code the specified
281 /// instruction may be. This returns the maximum number of bytes.
282 ///
getInstSizeInBytes(const MachineInstr & MI) const283 unsigned MSP430InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
284 const MCInstrDesc &Desc = MI.getDesc();
285
286 switch (Desc.getOpcode()) {
287 case TargetOpcode::CFI_INSTRUCTION:
288 case TargetOpcode::EH_LABEL:
289 case TargetOpcode::IMPLICIT_DEF:
290 case TargetOpcode::KILL:
291 case TargetOpcode::DBG_VALUE:
292 return 0;
293 case TargetOpcode::INLINEASM:
294 case TargetOpcode::INLINEASM_BR: {
295 const MachineFunction *MF = MI.getParent()->getParent();
296 const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
297 return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
298 *MF->getTarget().getMCAsmInfo());
299 }
300 }
301
302 return Desc.getSize();
303 }
304