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