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