xref: /freebsd/contrib/llvm-project/llvm/lib/Target/MSP430/MSP430InstrInfo.cpp (revision cfd6422a5217410fbd66f7a7a8a64d9d85e61229)
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/Support/ErrorHandling.h"
22 #include "llvm/Support/TargetRegistry.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::Br &&
120         I->getOpcode() != MSP430::Bm)
121       break;
122     // Remove the branch.
123     I->eraseFromParent();
124     I = MBB.end();
125     ++Count;
126   }
127 
128   return Count;
129 }
130 
131 bool MSP430InstrInfo::
132 reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {
133   assert(Cond.size() == 1 && "Invalid Xbranch condition!");
134 
135   MSP430CC::CondCodes CC = static_cast<MSP430CC::CondCodes>(Cond[0].getImm());
136 
137   switch (CC) {
138   default: llvm_unreachable("Invalid branch condition!");
139   case MSP430CC::COND_E:
140     CC = MSP430CC::COND_NE;
141     break;
142   case MSP430CC::COND_NE:
143     CC = MSP430CC::COND_E;
144     break;
145   case MSP430CC::COND_L:
146     CC = MSP430CC::COND_GE;
147     break;
148   case MSP430CC::COND_GE:
149     CC = MSP430CC::COND_L;
150     break;
151   case MSP430CC::COND_HS:
152     CC = MSP430CC::COND_LO;
153     break;
154   case MSP430CC::COND_LO:
155     CC = MSP430CC::COND_HS;
156     break;
157   }
158 
159   Cond[0].setImm(CC);
160   return false;
161 }
162 
163 bool MSP430InstrInfo::analyzeBranch(MachineBasicBlock &MBB,
164                                     MachineBasicBlock *&TBB,
165                                     MachineBasicBlock *&FBB,
166                                     SmallVectorImpl<MachineOperand> &Cond,
167                                     bool AllowModify) const {
168   // Start from the bottom of the block and work up, examining the
169   // terminator instructions.
170   MachineBasicBlock::iterator I = MBB.end();
171   while (I != MBB.begin()) {
172     --I;
173     if (I->isDebugInstr())
174       continue;
175 
176     // Working from the bottom, when we see a non-terminator
177     // instruction, we're done.
178     if (!isUnpredicatedTerminator(*I))
179       break;
180 
181     // A terminator that isn't a branch can't easily be handled
182     // by this analysis.
183     if (!I->isBranch())
184       return true;
185 
186     // Cannot handle indirect branches.
187     if (I->getOpcode() == MSP430::Br ||
188         I->getOpcode() == MSP430::Bm)
189       return true;
190 
191     // Handle unconditional branches.
192     if (I->getOpcode() == MSP430::JMP) {
193       if (!AllowModify) {
194         TBB = I->getOperand(0).getMBB();
195         continue;
196       }
197 
198       // If the block has any instructions after a JMP, delete them.
199       while (std::next(I) != MBB.end())
200         std::next(I)->eraseFromParent();
201       Cond.clear();
202       FBB = nullptr;
203 
204       // Delete the JMP if it's equivalent to a fall-through.
205       if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
206         TBB = nullptr;
207         I->eraseFromParent();
208         I = MBB.end();
209         continue;
210       }
211 
212       // TBB is used to indicate the unconditinal destination.
213       TBB = I->getOperand(0).getMBB();
214       continue;
215     }
216 
217     // Handle conditional branches.
218     assert(I->getOpcode() == MSP430::JCC && "Invalid conditional branch");
219     MSP430CC::CondCodes BranchCode =
220       static_cast<MSP430CC::CondCodes>(I->getOperand(1).getImm());
221     if (BranchCode == MSP430CC::COND_INVALID)
222       return true;  // Can't handle weird stuff.
223 
224     // Working from the bottom, handle the first conditional branch.
225     if (Cond.empty()) {
226       FBB = TBB;
227       TBB = I->getOperand(0).getMBB();
228       Cond.push_back(MachineOperand::CreateImm(BranchCode));
229       continue;
230     }
231 
232     // Handle subsequent conditional branches. Only handle the case where all
233     // conditional branches branch to the same destination.
234     assert(Cond.size() == 1);
235     assert(TBB);
236 
237     // Only handle the case where all conditional branches branch to
238     // the same destination.
239     if (TBB != I->getOperand(0).getMBB())
240       return true;
241 
242     MSP430CC::CondCodes OldBranchCode = (MSP430CC::CondCodes)Cond[0].getImm();
243     // If the conditions are the same, we can leave them alone.
244     if (OldBranchCode == BranchCode)
245       continue;
246 
247     return true;
248   }
249 
250   return false;
251 }
252 
253 unsigned MSP430InstrInfo::insertBranch(MachineBasicBlock &MBB,
254                                        MachineBasicBlock *TBB,
255                                        MachineBasicBlock *FBB,
256                                        ArrayRef<MachineOperand> Cond,
257                                        const DebugLoc &DL,
258                                        int *BytesAdded) const {
259   // Shouldn't be a fall through.
260   assert(TBB && "insertBranch must not be told to insert a fallthrough");
261   assert((Cond.size() == 1 || Cond.size() == 0) &&
262          "MSP430 branch conditions have one component!");
263   assert(!BytesAdded && "code size not handled");
264 
265   if (Cond.empty()) {
266     // Unconditional branch?
267     assert(!FBB && "Unconditional branch with multiple successors!");
268     BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(TBB);
269     return 1;
270   }
271 
272   // Conditional branch.
273   unsigned Count = 0;
274   BuildMI(&MBB, DL, get(MSP430::JCC)).addMBB(TBB).addImm(Cond[0].getImm());
275   ++Count;
276 
277   if (FBB) {
278     // Two-way Conditional branch. Insert the second branch.
279     BuildMI(&MBB, DL, get(MSP430::JMP)).addMBB(FBB);
280     ++Count;
281   }
282   return Count;
283 }
284 
285 /// GetInstSize - Return the number of bytes of code the specified
286 /// instruction may be.  This returns the maximum number of bytes.
287 ///
288 unsigned MSP430InstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
289   const MCInstrDesc &Desc = MI.getDesc();
290 
291   switch (Desc.getOpcode()) {
292   case TargetOpcode::CFI_INSTRUCTION:
293   case TargetOpcode::EH_LABEL:
294   case TargetOpcode::IMPLICIT_DEF:
295   case TargetOpcode::KILL:
296   case TargetOpcode::DBG_VALUE:
297     return 0;
298   case TargetOpcode::INLINEASM:
299   case TargetOpcode::INLINEASM_BR: {
300     const MachineFunction *MF = MI.getParent()->getParent();
301     const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo();
302     return TII.getInlineAsmLength(MI.getOperand(0).getSymbolName(),
303                                   *MF->getTarget().getMCAsmInfo());
304   }
305   }
306 
307   return Desc.getSize();
308 }
309