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