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