1 //===-- CSKYInstrInfo.h - CSKY Instruction Information --------*- C++ -*---===//
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 CSKY implementation of the TargetInstrInfo class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "CSKYInstrInfo.h"
14 #include "CSKYMachineFunctionInfo.h"
15 #include "CSKYTargetMachine.h"
16 #include "llvm/MC/MCContext.h"
17 
18 #define DEBUG_TYPE "csky-instr-info"
19 
20 using namespace llvm;
21 
22 #define GET_INSTRINFO_CTOR_DTOR
23 #include "CSKYGenInstrInfo.inc"
24 
25 CSKYInstrInfo::CSKYInstrInfo(CSKYSubtarget &STI)
26     : CSKYGenInstrInfo(CSKY::ADJCALLSTACKDOWN, CSKY::ADJCALLSTACKUP), STI(STI) {
27 }
28 
29 static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
30                             SmallVectorImpl<MachineOperand> &Cond) {
31   // Block ends with fall-through condbranch.
32   assert(LastInst.getDesc().isConditionalBranch() &&
33          "Unknown conditional branch");
34   Target = LastInst.getOperand(1).getMBB();
35   Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
36   Cond.push_back(LastInst.getOperand(0));
37 }
38 
39 bool CSKYInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
40                                   MachineBasicBlock *&TBB,
41                                   MachineBasicBlock *&FBB,
42                                   SmallVectorImpl<MachineOperand> &Cond,
43                                   bool AllowModify) const {
44   TBB = FBB = nullptr;
45   Cond.clear();
46 
47   // If the block has no terminators, it just falls into the block after it.
48   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
49   if (I == MBB.end() || !isUnpredicatedTerminator(*I))
50     return false;
51 
52   // Count the number of terminators and find the first unconditional or
53   // indirect branch.
54   MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
55   int NumTerminators = 0;
56   for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
57        J++) {
58     NumTerminators++;
59     if (J->getDesc().isUnconditionalBranch() ||
60         J->getDesc().isIndirectBranch()) {
61       FirstUncondOrIndirectBr = J.getReverse();
62     }
63   }
64 
65   // If AllowModify is true, we can erase any terminators after
66   // FirstUncondOrIndirectBR.
67   if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
68     while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
69       std::next(FirstUncondOrIndirectBr)->eraseFromParent();
70       NumTerminators--;
71     }
72     I = FirstUncondOrIndirectBr;
73   }
74 
75   // We can't handle blocks that end in an indirect branch.
76   if (I->getDesc().isIndirectBranch())
77     return true;
78 
79   // We can't handle blocks with more than 2 terminators.
80   if (NumTerminators > 2)
81     return true;
82 
83   // Handle a single unconditional branch.
84   if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
85     TBB = getBranchDestBlock(*I);
86     return false;
87   }
88 
89   // Handle a single conditional branch.
90   if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
91     parseCondBranch(*I, TBB, Cond);
92     return false;
93   }
94 
95   // Handle a conditional branch followed by an unconditional branch.
96   if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
97       I->getDesc().isUnconditionalBranch()) {
98     parseCondBranch(*std::prev(I), TBB, Cond);
99     FBB = getBranchDestBlock(*I);
100     return false;
101   }
102 
103   // Otherwise, we can't handle this.
104   return true;
105 }
106 
107 unsigned CSKYInstrInfo::removeBranch(MachineBasicBlock &MBB,
108                                      int *BytesRemoved) const {
109   if (BytesRemoved)
110     *BytesRemoved = 0;
111   MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
112   if (I == MBB.end())
113     return 0;
114 
115   if (!I->getDesc().isUnconditionalBranch() &&
116       !I->getDesc().isConditionalBranch())
117     return 0;
118 
119   // Remove the branch.
120   if (BytesRemoved)
121     *BytesRemoved += getInstSizeInBytes(*I);
122   I->eraseFromParent();
123 
124   I = MBB.end();
125 
126   if (I == MBB.begin())
127     return 1;
128   --I;
129   if (!I->getDesc().isConditionalBranch())
130     return 1;
131 
132   // Remove the branch.
133   if (BytesRemoved)
134     *BytesRemoved += getInstSizeInBytes(*I);
135   I->eraseFromParent();
136   return 2;
137 }
138 
139 MachineBasicBlock *
140 CSKYInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
141   assert(MI.getDesc().isBranch() && "Unexpected opcode!");
142   // The branch target is always the last operand.
143   int NumOp = MI.getNumExplicitOperands();
144   assert(MI.getOperand(NumOp - 1).isMBB() && "Expected MBB!");
145   return MI.getOperand(NumOp - 1).getMBB();
146 }
147 
148 unsigned CSKYInstrInfo::insertBranch(
149     MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
150     ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
151   if (BytesAdded)
152     *BytesAdded = 0;
153 
154   // Shouldn't be a fall through.
155   assert(TBB && "insertBranch must not be told to insert a fallthrough");
156   assert((Cond.size() == 2 || Cond.size() == 0) &&
157          "CSKY branch conditions have two components!");
158 
159   // Unconditional branch.
160   if (Cond.empty()) {
161     MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(TBB);
162     if (BytesAdded)
163       *BytesAdded += getInstSizeInBytes(MI);
164     return 1;
165   }
166 
167   // Either a one or two-way conditional branch.
168   unsigned Opc = Cond[0].getImm();
169   MachineInstr &CondMI = *BuildMI(&MBB, DL, get(Opc)).add(Cond[1]).addMBB(TBB);
170   if (BytesAdded)
171     *BytesAdded += getInstSizeInBytes(CondMI);
172 
173   // One-way conditional branch.
174   if (!FBB)
175     return 1;
176 
177   // Two-way conditional branch.
178   MachineInstr &MI = *BuildMI(&MBB, DL, get(CSKY::BR32)).addMBB(FBB);
179   if (BytesAdded)
180     *BytesAdded += getInstSizeInBytes(MI);
181   return 2;
182 }
183 
184 static unsigned getOppositeBranchOpc(unsigned Opcode) {
185   switch (Opcode) {
186   default:
187     llvm_unreachable("Unknown conditional branch!");
188   case CSKY::BT32:
189     return CSKY::BF32;
190   case CSKY::BT16:
191     return CSKY::BF16;
192   case CSKY::BF32:
193     return CSKY::BT32;
194   case CSKY::BF16:
195     return CSKY::BT16;
196   case CSKY::BHZ32:
197     return CSKY::BLSZ32;
198   case CSKY::BHSZ32:
199     return CSKY::BLZ32;
200   case CSKY::BLZ32:
201     return CSKY::BHSZ32;
202   case CSKY::BLSZ32:
203     return CSKY::BHZ32;
204   case CSKY::BNEZ32:
205     return CSKY::BEZ32;
206   case CSKY::BEZ32:
207     return CSKY::BNEZ32;
208   }
209 }
210 
211 bool CSKYInstrInfo::reverseBranchCondition(
212     SmallVectorImpl<MachineOperand> &Cond) const {
213   assert((Cond.size() == 2) && "Invalid branch condition!");
214   Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
215   return false;
216 }
217 
218 Register CSKYInstrInfo::movImm(MachineBasicBlock &MBB,
219                                MachineBasicBlock::iterator MBBI,
220                                const DebugLoc &DL, int64_t Val,
221                                MachineInstr::MIFlag Flag) const {
222   assert(isUInt<32>(Val) && "should be uint32");
223 
224   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
225 
226   Register DstReg;
227   if (STI.hasE2()) {
228     DstReg = MRI.createVirtualRegister(&CSKY::GPRRegClass);
229 
230     if (isUInt<16>(Val)) {
231       BuildMI(MBB, MBBI, DL, get(CSKY::MOVI32), DstReg)
232           .addImm(Val & 0xFFFF)
233           .setMIFlags(Flag);
234     } else if (isShiftedUInt<16, 16>(Val)) {
235       BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
236           .addImm((Val >> 16) & 0xFFFF)
237           .setMIFlags(Flag);
238     } else {
239       BuildMI(MBB, MBBI, DL, get(CSKY::MOVIH32), DstReg)
240           .addImm((Val >> 16) & 0xFFFF)
241           .setMIFlags(Flag);
242       BuildMI(MBB, MBBI, DL, get(CSKY::ORI32), DstReg)
243           .addReg(DstReg)
244           .addImm(Val & 0xFFFF)
245           .setMIFlags(Flag);
246     }
247 
248   } else {
249     DstReg = MRI.createVirtualRegister(&CSKY::mGPRRegClass);
250     if (isUInt<8>(Val)) {
251       BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
252           .addImm(Val & 0xFF)
253           .setMIFlags(Flag);
254     } else if (isUInt<16>(Val)) {
255       BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
256           .addImm((Val >> 8) & 0xFF)
257           .setMIFlags(Flag);
258       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
259           .addReg(DstReg)
260           .addImm(8)
261           .setMIFlags(Flag);
262       if ((Val & 0xFF) != 0)
263         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
264             .addReg(DstReg)
265             .addImm(Val & 0xFF)
266             .setMIFlags(Flag);
267     } else if (isUInt<24>(Val)) {
268       BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
269           .addImm((Val >> 16) & 0xFF)
270           .setMIFlags(Flag);
271       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
272           .addReg(DstReg)
273           .addImm(8)
274           .setMIFlags(Flag);
275       if (((Val >> 8) & 0xFF) != 0)
276         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
277             .addReg(DstReg)
278             .addImm((Val >> 8) & 0xFF)
279             .setMIFlags(Flag);
280       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
281           .addReg(DstReg)
282           .addImm(8)
283           .setMIFlags(Flag);
284       if ((Val & 0xFF) != 0)
285         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
286             .addReg(DstReg)
287             .addImm(Val & 0xFF)
288             .setMIFlags(Flag);
289     } else {
290       BuildMI(MBB, MBBI, DL, get(CSKY::MOVI16), DstReg)
291           .addImm((Val >> 24) & 0xFF)
292           .setMIFlags(Flag);
293       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
294           .addReg(DstReg)
295           .addImm(8)
296           .setMIFlags(Flag);
297       if (((Val >> 16) & 0xFF) != 0)
298         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
299             .addReg(DstReg)
300             .addImm((Val >> 16) & 0xFF)
301             .setMIFlags(Flag);
302       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
303           .addReg(DstReg)
304           .addImm(8)
305           .setMIFlags(Flag);
306       if (((Val >> 8) & 0xFF) != 0)
307         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
308             .addReg(DstReg)
309             .addImm((Val >> 8) & 0xFF)
310             .setMIFlags(Flag);
311       BuildMI(MBB, MBBI, DL, get(CSKY::LSLI16), DstReg)
312           .addReg(DstReg)
313           .addImm(8)
314           .setMIFlags(Flag);
315       if ((Val & 0xFF) != 0)
316         BuildMI(MBB, MBBI, DL, get(CSKY::ADDI16), DstReg)
317             .addReg(DstReg)
318             .addImm(Val & 0xFF)
319             .setMIFlags(Flag);
320     }
321   }
322 
323   return DstReg;
324 }
325 
326 unsigned CSKYInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
327                                             int &FrameIndex) const {
328   switch (MI.getOpcode()) {
329   default:
330     return 0;
331   case CSKY::LD16B:
332   case CSKY::LD16H:
333   case CSKY::LD16W:
334   case CSKY::LD32B:
335   case CSKY::LD32BS:
336   case CSKY::LD32H:
337   case CSKY::LD32HS:
338   case CSKY::LD32W:
339   case CSKY::RESTORE_CARRY:
340     break;
341   }
342 
343   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
344       MI.getOperand(2).getImm() == 0) {
345     FrameIndex = MI.getOperand(1).getIndex();
346     return MI.getOperand(0).getReg();
347   }
348 
349   return 0;
350 }
351 
352 unsigned CSKYInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
353                                            int &FrameIndex) const {
354   switch (MI.getOpcode()) {
355   default:
356     return 0;
357   case CSKY::ST16B:
358   case CSKY::ST16H:
359   case CSKY::ST16W:
360   case CSKY::ST32B:
361   case CSKY::ST32H:
362   case CSKY::ST32W:
363   case CSKY::SPILL_CARRY:
364     break;
365   }
366 
367   if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() &&
368       MI.getOperand(2).getImm() == 0) {
369     FrameIndex = MI.getOperand(1).getIndex();
370     return MI.getOperand(0).getReg();
371   }
372 
373   return 0;
374 }
375 
376 void CSKYInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
377                                         MachineBasicBlock::iterator I,
378                                         Register SrcReg, bool IsKill, int FI,
379                                         const TargetRegisterClass *RC,
380                                         const TargetRegisterInfo *TRI) const {
381   DebugLoc DL;
382   if (I != MBB.end())
383     DL = I->getDebugLoc();
384 
385   MachineFunction &MF = *MBB.getParent();
386   CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
387   MachineFrameInfo &MFI = MF.getFrameInfo();
388 
389   unsigned Opcode = 0;
390 
391   if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
392     Opcode = CSKY::ST32W; // Optimize for 16bit
393   } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
394     Opcode = CSKY::SPILL_CARRY;
395     CFI->setSpillsCR();
396   } else {
397     llvm_unreachable("Unknown RegisterClass");
398   }
399 
400   MachineMemOperand *MMO = MF.getMachineMemOperand(
401       MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
402       MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
403 
404   BuildMI(MBB, I, DL, get(Opcode))
405       .addReg(SrcReg, getKillRegState(IsKill))
406       .addFrameIndex(FI)
407       .addImm(0)
408       .addMemOperand(MMO);
409 }
410 
411 void CSKYInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
412                                          MachineBasicBlock::iterator I,
413                                          Register DestReg, int FI,
414                                          const TargetRegisterClass *RC,
415                                          const TargetRegisterInfo *TRI) const {
416   DebugLoc DL;
417   if (I != MBB.end())
418     DL = I->getDebugLoc();
419 
420   MachineFunction &MF = *MBB.getParent();
421   CSKYMachineFunctionInfo *CFI = MF.getInfo<CSKYMachineFunctionInfo>();
422   MachineFrameInfo &MFI = MF.getFrameInfo();
423 
424   unsigned Opcode = 0;
425 
426   if (CSKY::GPRRegClass.hasSubClassEq(RC)) {
427     Opcode = CSKY::LD32W;
428   } else if (CSKY::CARRYRegClass.hasSubClassEq(RC)) {
429     Opcode = CSKY::RESTORE_CARRY;
430     CFI->setSpillsCR();
431   } else {
432     llvm_unreachable("Unknown RegisterClass");
433   }
434 
435   MachineMemOperand *MMO = MF.getMachineMemOperand(
436       MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
437       MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
438 
439   BuildMI(MBB, I, DL, get(Opcode), DestReg)
440       .addFrameIndex(FI)
441       .addImm(0)
442       .addMemOperand(MMO);
443 }
444 
445 void CSKYInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
446                                 MachineBasicBlock::iterator I,
447                                 const DebugLoc &DL, MCRegister DestReg,
448                                 MCRegister SrcReg, bool KillSrc) const {
449 
450   MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();
451 
452   if (CSKY::GPRRegClass.contains(SrcReg) &&
453       CSKY::CARRYRegClass.contains(DestReg)) {
454     if (STI.hasE2()) {
455       BuildMI(MBB, I, DL, get(CSKY::BTSTI32), DestReg)
456           .addReg(SrcReg, getKillRegState(KillSrc))
457           .addImm(0);
458     } else {
459       assert(SrcReg < CSKY::R8);
460       BuildMI(MBB, I, DL, get(CSKY::BTSTI16), DestReg)
461           .addReg(SrcReg, getKillRegState(KillSrc))
462           .addImm(0);
463     }
464     return;
465   }
466 
467   if (CSKY::CARRYRegClass.contains(SrcReg) &&
468       CSKY::GPRRegClass.contains(DestReg)) {
469 
470     if (STI.hasE2()) {
471       BuildMI(MBB, I, DL, get(CSKY::MVC32), DestReg)
472           .addReg(SrcReg, getKillRegState(KillSrc));
473     } else {
474       assert(DestReg < CSKY::R16);
475       assert(DestReg < CSKY::R8);
476       BuildMI(MBB, I, DL, get(CSKY::MOVI16), DestReg).addImm(0);
477       BuildMI(MBB, I, DL, get(CSKY::ADDC16))
478           .addReg(DestReg, RegState::Define)
479           .addReg(SrcReg, RegState::Define)
480           .addReg(DestReg, getKillRegState(true))
481           .addReg(DestReg, getKillRegState(true))
482           .addReg(SrcReg, getKillRegState(true));
483       BuildMI(MBB, I, DL, get(CSKY::BTSTI16))
484           .addReg(SrcReg, RegState::Define | getDeadRegState(KillSrc))
485           .addReg(DestReg)
486           .addImm(0);
487     }
488     return;
489   }
490 
491   unsigned Opcode = 0;
492   if (CSKY::GPRRegClass.contains(DestReg, SrcReg))
493     Opcode = CSKY::MOV32;
494   else {
495     LLVM_DEBUG(dbgs() << "src = " << SrcReg << ", dst = " << DestReg);
496     LLVM_DEBUG(I->dump());
497     llvm_unreachable("Unknown RegisterClass");
498   }
499 
500   BuildMI(MBB, I, DL, get(Opcode), DestReg)
501       .addReg(SrcReg, getKillRegState(KillSrc));
502 }
503