1 //===- SPUInstrInfo.cpp - Cell SPU Instruction Information ----------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains the Cell SPU implementation of the TargetInstrInfo class.
12 //===----------------------------------------------------------------------===//
14 #include "SPURegisterNames.h"
15 #include "SPUInstrInfo.h"
16 #include "SPUInstrBuilder.h"
17 #include "SPUTargetMachine.h"
18 #include "SPUGenInstrInfo.inc"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "llvm/Support/Streams.h"
21 #include "llvm/Support/Debug.h"
26 //! Predicate for an unconditional branch instruction
27 inline bool isUncondBranch(const MachineInstr
*I
) {
28 unsigned opc
= I
->getOpcode();
30 return (opc
== SPU::BR
35 //! Predicate for a conditional branch instruction
36 inline bool isCondBranch(const MachineInstr
*I
) {
37 unsigned opc
= I
->getOpcode();
39 return (opc
== SPU::BRNZr32
40 || opc
== SPU::BRNZv4i32
42 || opc
== SPU::BRZv4i32
43 || opc
== SPU::BRHNZr16
44 || opc
== SPU::BRHNZv8i16
45 || opc
== SPU::BRHZr16
46 || opc
== SPU::BRHZv8i16
);
50 SPUInstrInfo::SPUInstrInfo(SPUTargetMachine
&tm
)
51 : TargetInstrInfoImpl(SPUInsts
, sizeof(SPUInsts
)/sizeof(SPUInsts
[0])),
53 RI(*TM
.getSubtargetImpl(), *this)
57 SPUInstrInfo::isMoveInstr(const MachineInstr
& MI
,
60 unsigned& SrcSR
, unsigned& DstSR
) const {
61 SrcSR
= DstSR
= 0; // No sub-registers.
63 switch (MI
.getOpcode()) {
78 assert(MI
.getNumOperands() == 3 &&
79 MI
.getOperand(0).isReg() &&
80 MI
.getOperand(1).isReg() &&
81 MI
.getOperand(2).isImm() &&
82 "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!");
83 if (MI
.getOperand(2).getImm() == 0) {
84 sourceReg
= MI
.getOperand(1).getReg();
85 destReg
= MI
.getOperand(0).getReg();
90 assert(MI
.getNumOperands() == 3 &&
91 "wrong number of operands to AIr32");
92 if (MI
.getOperand(0).isReg() &&
93 MI
.getOperand(1).isReg() &&
94 (MI
.getOperand(2).isImm() &&
95 MI
.getOperand(2).getImm() == 0)) {
96 sourceReg
= MI
.getOperand(1).getReg();
97 destReg
= MI
.getOperand(0).getReg();
114 case SPU::ORv16i8_i8
:
115 case SPU::ORv8i16_i16
:
116 case SPU::ORv4i32_i32
:
117 case SPU::ORv2i64_i64
:
118 case SPU::ORv4f32_f32
:
119 case SPU::ORv2f64_f64
:
120 case SPU::ORi8_v16i8
:
121 case SPU::ORi16_v8i16
:
122 case SPU::ORi32_v4i32
:
123 case SPU::ORi64_v2i64
:
124 case SPU::ORf32_v4f32
:
125 case SPU::ORf64_v2f64
:
127 case SPU::ORi128_r64:
128 case SPU::ORi128_f64:
129 case SPU::ORi128_r32:
130 case SPU::ORi128_f32:
131 case SPU::ORi128_r16:
134 case SPU::ORi128_vec
:
136 case SPU::ORr64_i128:
137 case SPU::ORf64_i128:
138 case SPU::ORr32_i128:
139 case SPU::ORf32_i128:
140 case SPU::ORr16_i128:
143 case SPU::ORvec_i128
:
161 case SPU::ORr64_f64
: {
162 assert(MI
.getNumOperands() == 2 &&
163 MI
.getOperand(0).isReg() &&
164 MI
.getOperand(1).isReg() &&
165 "invalid SPU OR<type>_<vec> or LR instruction!");
166 if (MI
.getOperand(0).getReg() == MI
.getOperand(1).getReg()) {
167 sourceReg
= MI
.getOperand(1).getReg();
168 destReg
= MI
.getOperand(0).getReg();
184 assert(MI
.getNumOperands() == 3 &&
185 MI
.getOperand(0).isReg() &&
186 MI
.getOperand(1).isReg() &&
187 MI
.getOperand(2).isReg() &&
188 "invalid SPU OR(vec|r32|r64|gprc) instruction!");
189 if (MI
.getOperand(1).getReg() == MI
.getOperand(2).getReg()) {
190 sourceReg
= MI
.getOperand(1).getReg();
191 destReg
= MI
.getOperand(0).getReg();
201 SPUInstrInfo::isLoadFromStackSlot(const MachineInstr
*MI
,
202 int &FrameIndex
) const {
203 switch (MI
->getOpcode()) {
214 const MachineOperand MOp1
= MI
->getOperand(1);
215 const MachineOperand MOp2
= MI
->getOperand(2);
216 if (MOp1
.isImm() && MOp2
.isFI()) {
217 FrameIndex
= MOp2
.getIndex();
218 return MI
->getOperand(0).getReg();
227 SPUInstrInfo::isStoreToStackSlot(const MachineInstr
*MI
,
228 int &FrameIndex
) const {
229 switch (MI
->getOpcode()) {
241 const MachineOperand MOp1
= MI
->getOperand(1);
242 const MachineOperand MOp2
= MI
->getOperand(2);
243 if (MOp1
.isImm() && MOp2
.isFI()) {
244 FrameIndex
= MOp2
.getIndex();
245 return MI
->getOperand(0).getReg();
253 bool SPUInstrInfo::copyRegToReg(MachineBasicBlock
&MBB
,
254 MachineBasicBlock::iterator MI
,
255 unsigned DestReg
, unsigned SrcReg
,
256 const TargetRegisterClass
*DestRC
,
257 const TargetRegisterClass
*SrcRC
) const
259 // We support cross register class moves for our aliases, such as R3 in any
260 // reg class to any other reg class containing R3. This is required because
261 // we instruction select bitconvert i64 -> f64 as a noop for example, so our
262 // types have no specific meaning.
264 DebugLoc DL
= DebugLoc::getUnknownLoc();
265 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
267 if (DestRC
== SPU::R8CRegisterClass
) {
268 BuildMI(MBB
, MI
, DL
, get(SPU::LRr8
), DestReg
).addReg(SrcReg
);
269 } else if (DestRC
== SPU::R16CRegisterClass
) {
270 BuildMI(MBB
, MI
, DL
, get(SPU::LRr16
), DestReg
).addReg(SrcReg
);
271 } else if (DestRC
== SPU::R32CRegisterClass
) {
272 BuildMI(MBB
, MI
, DL
, get(SPU::LRr32
), DestReg
).addReg(SrcReg
);
273 } else if (DestRC
== SPU::R32FPRegisterClass
) {
274 BuildMI(MBB
, MI
, DL
, get(SPU::LRf32
), DestReg
).addReg(SrcReg
);
275 } else if (DestRC
== SPU::R64CRegisterClass
) {
276 BuildMI(MBB
, MI
, DL
, get(SPU::LRr64
), DestReg
).addReg(SrcReg
);
277 } else if (DestRC
== SPU::R64FPRegisterClass
) {
278 BuildMI(MBB
, MI
, DL
, get(SPU::LRf64
), DestReg
).addReg(SrcReg
);
279 } else if (DestRC
== SPU::GPRCRegisterClass
) {
280 BuildMI(MBB
, MI
, DL
, get(SPU::LRr128
), DestReg
).addReg(SrcReg
);
281 } else if (DestRC
== SPU::VECREGRegisterClass
) {
282 BuildMI(MBB
, MI
, DL
, get(SPU::LRv16i8
), DestReg
).addReg(SrcReg
);
284 // Attempt to copy unknown/unsupported register class!
292 SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock
&MBB
,
293 MachineBasicBlock::iterator MI
,
294 unsigned SrcReg
, bool isKill
, int FrameIdx
,
295 const TargetRegisterClass
*RC
) const
298 bool isValidFrameIdx
= (FrameIdx
< SPUFrameInfo::maxFrameOffset());
299 if (RC
== SPU::GPRCRegisterClass
) {
300 opc
= (isValidFrameIdx
? SPU::STQDr128
: SPU::STQXr128
);
301 } else if (RC
== SPU::R64CRegisterClass
) {
302 opc
= (isValidFrameIdx
? SPU::STQDr64
: SPU::STQXr64
);
303 } else if (RC
== SPU::R64FPRegisterClass
) {
304 opc
= (isValidFrameIdx
? SPU::STQDr64
: SPU::STQXr64
);
305 } else if (RC
== SPU::R32CRegisterClass
) {
306 opc
= (isValidFrameIdx
? SPU::STQDr32
: SPU::STQXr32
);
307 } else if (RC
== SPU::R32FPRegisterClass
) {
308 opc
= (isValidFrameIdx
? SPU::STQDr32
: SPU::STQXr32
);
309 } else if (RC
== SPU::R16CRegisterClass
) {
310 opc
= (isValidFrameIdx
? SPU::STQDr16
: SPU::STQXr16
);
311 } else if (RC
== SPU::R8CRegisterClass
) {
312 opc
= (isValidFrameIdx
? SPU::STQDr8
: SPU::STQXr8
);
313 } else if (RC
== SPU::VECREGRegisterClass
) {
314 opc
= (isValidFrameIdx
) ? SPU::STQDv16i8
: SPU::STQXv16i8
;
316 assert(0 && "Unknown regclass!");
320 DebugLoc DL
= DebugLoc::getUnknownLoc();
321 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
322 addFrameReference(BuildMI(MBB
, MI
, DL
, get(opc
))
323 .addReg(SrcReg
, false, false, isKill
), FrameIdx
);
326 void SPUInstrInfo::storeRegToAddr(MachineFunction
&MF
, unsigned SrcReg
,
328 SmallVectorImpl
<MachineOperand
> &Addr
,
329 const TargetRegisterClass
*RC
,
330 SmallVectorImpl
<MachineInstr
*> &NewMIs
) const {
331 cerr
<< "storeRegToAddr() invoked!\n";
334 if (Addr
[0].isFI()) {
335 /* do what storeRegToStackSlot does here */
338 if (RC
== SPU::GPRCRegisterClass
) {
339 /* Opc = PPC::STW; */
340 } else if (RC
== SPU::R16CRegisterClass
) {
341 /* Opc = PPC::STD; */
342 } else if (RC
== SPU::R32CRegisterClass
) {
343 /* Opc = PPC::STFD; */
344 } else if (RC
== SPU::R32FPRegisterClass
) {
345 /* Opc = PPC::STFD; */
346 } else if (RC
== SPU::R64FPRegisterClass
) {
347 /* Opc = PPC::STFS; */
348 } else if (RC
== SPU::VECREGRegisterClass
) {
349 /* Opc = PPC::STVX; */
351 assert(0 && "Unknown regclass!");
354 DebugLoc DL
= DebugLoc::getUnknownLoc();
355 MachineInstrBuilder MIB
= BuildMI(MF
, DL
, get(Opc
))
356 .addReg(SrcReg
, false, false, isKill
);
357 for (unsigned i
= 0, e
= Addr
.size(); i
!= e
; ++i
)
358 MIB
.addOperand(Addr
[i
]);
359 NewMIs
.push_back(MIB
);
364 SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock
&MBB
,
365 MachineBasicBlock::iterator MI
,
366 unsigned DestReg
, int FrameIdx
,
367 const TargetRegisterClass
*RC
) const
370 bool isValidFrameIdx
= (FrameIdx
< SPUFrameInfo::maxFrameOffset());
371 if (RC
== SPU::GPRCRegisterClass
) {
372 opc
= (isValidFrameIdx
? SPU::LQDr128
: SPU::LQXr128
);
373 } else if (RC
== SPU::R64CRegisterClass
) {
374 opc
= (isValidFrameIdx
? SPU::LQDr64
: SPU::LQXr64
);
375 } else if (RC
== SPU::R64FPRegisterClass
) {
376 opc
= (isValidFrameIdx
? SPU::LQDr64
: SPU::LQXr64
);
377 } else if (RC
== SPU::R32CRegisterClass
) {
378 opc
= (isValidFrameIdx
? SPU::LQDr32
: SPU::LQXr32
);
379 } else if (RC
== SPU::R32FPRegisterClass
) {
380 opc
= (isValidFrameIdx
? SPU::LQDr32
: SPU::LQXr32
);
381 } else if (RC
== SPU::R16CRegisterClass
) {
382 opc
= (isValidFrameIdx
? SPU::LQDr16
: SPU::LQXr16
);
383 } else if (RC
== SPU::R8CRegisterClass
) {
384 opc
= (isValidFrameIdx
? SPU::LQDr8
: SPU::LQXr8
);
385 } else if (RC
== SPU::VECREGRegisterClass
) {
386 opc
= (isValidFrameIdx
) ? SPU::LQDv16i8
: SPU::LQXv16i8
;
388 assert(0 && "Unknown regclass in loadRegFromStackSlot!");
392 DebugLoc DL
= DebugLoc::getUnknownLoc();
393 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
394 addFrameReference(BuildMI(MBB
, MI
, DL
, get(opc
)).addReg(DestReg
), FrameIdx
);
398 \note We are really pessimistic here about what kind of a load we're doing.
400 void SPUInstrInfo::loadRegFromAddr(MachineFunction
&MF
, unsigned DestReg
,
401 SmallVectorImpl
<MachineOperand
> &Addr
,
402 const TargetRegisterClass
*RC
,
403 SmallVectorImpl
<MachineInstr
*> &NewMIs
)
405 cerr
<< "loadRegToAddr() invoked!\n";
408 if (Addr
[0].isFI()) {
409 /* do what loadRegFromStackSlot does here... */
412 if (RC
== SPU::R8CRegisterClass
) {
413 /* do brilliance here */
414 } else if (RC
== SPU::R16CRegisterClass
) {
415 /* Opc = PPC::LWZ; */
416 } else if (RC
== SPU::R32CRegisterClass
) {
418 } else if (RC
== SPU::R32FPRegisterClass
) {
419 /* Opc = PPC::LFD; */
420 } else if (RC
== SPU::R64FPRegisterClass
) {
421 /* Opc = PPC::LFS; */
422 } else if (RC
== SPU::VECREGRegisterClass
) {
423 /* Opc = PPC::LVX; */
424 } else if (RC
== SPU::GPRCRegisterClass
) {
425 /* Opc = something else! */
427 assert(0 && "Unknown regclass!");
430 DebugLoc DL
= DebugLoc::getUnknownLoc();
431 MachineInstrBuilder MIB
= BuildMI(MF
, DL
, get(Opc
), DestReg
);
432 for (unsigned i
= 0, e
= Addr
.size(); i
!= e
; ++i
)
433 MIB
.addOperand(Addr
[i
]);
434 NewMIs
.push_back(MIB
);
438 //! Return true if the specified load or store can be folded
440 SPUInstrInfo::canFoldMemoryOperand(const MachineInstr
*MI
,
441 const SmallVectorImpl
<unsigned> &Ops
) const {
442 if (Ops
.size() != 1) return false;
444 // Make sure this is a reg-reg copy.
445 unsigned Opc
= MI
->getOpcode();
458 if (MI
->getOperand(1).getReg() == MI
->getOperand(2).getReg())
466 /// foldMemoryOperand - SPU, like PPC, can only fold spills into
467 /// copy instructions, turning them into load/store instructions.
469 SPUInstrInfo::foldMemoryOperandImpl(MachineFunction
&MF
,
471 const SmallVectorImpl
<unsigned> &Ops
,
472 int FrameIndex
) const
474 if (Ops
.size() != 1) return 0;
476 unsigned OpNum
= Ops
[0];
477 unsigned Opc
= MI
->getOpcode();
478 MachineInstr
*NewMI
= 0;
491 if (OpNum
== 0) { // move -> store
492 unsigned InReg
= MI
->getOperand(1).getReg();
493 bool isKill
= MI
->getOperand(1).isKill();
494 if (FrameIndex
< SPUFrameInfo::maxFrameOffset()) {
495 MachineInstrBuilder MIB
= BuildMI(MF
, MI
->getDebugLoc(),
498 MIB
.addReg(InReg
, false, false, isKill
);
499 NewMI
= addFrameReference(MIB
, FrameIndex
);
501 } else { // move -> load
502 unsigned OutReg
= MI
->getOperand(0).getReg();
503 bool isDead
= MI
->getOperand(0).isDead();
504 MachineInstrBuilder MIB
= BuildMI(MF
, MI
->getDebugLoc(), get(Opc
));
506 MIB
.addReg(OutReg
, true, false, false, isDead
);
507 Opc
= (FrameIndex
< SPUFrameInfo::maxFrameOffset())
508 ? SPU::STQDr32
: SPU::STQXr32
;
509 NewMI
= addFrameReference(MIB
, FrameIndex
);
519 \note This code was kiped from PPC. There may be more branch analysis for
520 CellSPU than what's currently done here.
523 SPUInstrInfo::AnalyzeBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*&TBB
,
524 MachineBasicBlock
*&FBB
,
525 SmallVectorImpl
<MachineOperand
> &Cond
,
526 bool AllowModify
) const {
527 // If the block has no terminators, it just falls into the block after it.
528 MachineBasicBlock::iterator I
= MBB
.end();
529 if (I
== MBB
.begin() || !isUnpredicatedTerminator(--I
))
532 // Get the last instruction in the block.
533 MachineInstr
*LastInst
= I
;
535 // If there is only one terminator instruction, process it.
536 if (I
== MBB
.begin() || !isUnpredicatedTerminator(--I
)) {
537 if (isUncondBranch(LastInst
)) {
538 TBB
= LastInst
->getOperand(0).getMBB();
540 } else if (isCondBranch(LastInst
)) {
541 // Block ends with fall-through condbranch.
542 TBB
= LastInst
->getOperand(1).getMBB();
543 DEBUG(cerr
<< "Pushing LastInst: ");
544 DEBUG(LastInst
->dump());
545 Cond
.push_back(MachineOperand::CreateImm(LastInst
->getOpcode()));
546 Cond
.push_back(LastInst
->getOperand(0));
549 // Otherwise, don't know what this is.
553 // Get the instruction before it if it's a terminator.
554 MachineInstr
*SecondLastInst
= I
;
556 // If there are three terminators, we don't know what sort of block this is.
557 if (SecondLastInst
&& I
!= MBB
.begin() &&
558 isUnpredicatedTerminator(--I
))
561 // If the block ends with a conditional and unconditional branch, handle it.
562 if (isCondBranch(SecondLastInst
) && isUncondBranch(LastInst
)) {
563 TBB
= SecondLastInst
->getOperand(1).getMBB();
564 DEBUG(cerr
<< "Pushing SecondLastInst: ");
565 DEBUG(SecondLastInst
->dump());
566 Cond
.push_back(MachineOperand::CreateImm(SecondLastInst
->getOpcode()));
567 Cond
.push_back(SecondLastInst
->getOperand(0));
568 FBB
= LastInst
->getOperand(0).getMBB();
572 // If the block ends with two unconditional branches, handle it. The second
573 // one is not executed, so remove it.
574 if (isUncondBranch(SecondLastInst
) && isUncondBranch(LastInst
)) {
575 TBB
= SecondLastInst
->getOperand(0).getMBB();
578 I
->eraseFromParent();
582 // Otherwise, can't handle this.
587 SPUInstrInfo::RemoveBranch(MachineBasicBlock
&MBB
) const {
588 MachineBasicBlock::iterator I
= MBB
.end();
589 if (I
== MBB
.begin())
592 if (!isCondBranch(I
) && !isUncondBranch(I
))
595 // Remove the first branch.
596 DEBUG(cerr
<< "Removing branch: ");
598 I
->eraseFromParent();
600 if (I
== MBB
.begin())
604 if (!(isCondBranch(I
) || isUncondBranch(I
)))
607 // Remove the second branch.
608 DEBUG(cerr
<< "Removing second branch: ");
610 I
->eraseFromParent();
615 SPUInstrInfo::InsertBranch(MachineBasicBlock
&MBB
, MachineBasicBlock
*TBB
,
616 MachineBasicBlock
*FBB
,
617 const SmallVectorImpl
<MachineOperand
> &Cond
) const {
618 // FIXME this should probably have a DebugLoc argument
619 DebugLoc dl
= DebugLoc::getUnknownLoc();
620 // Shouldn't be a fall through.
621 assert(TBB
&& "InsertBranch must not be told to insert a fallthrough");
622 assert((Cond
.size() == 2 || Cond
.size() == 0) &&
623 "SPU branch conditions have two components!");
628 // Unconditional branch
629 MachineInstrBuilder MIB
= BuildMI(&MBB
, dl
, get(SPU::BR
));
632 DEBUG(cerr
<< "Inserted one-way uncond branch: ");
633 DEBUG((*MIB
).dump());
635 // Conditional branch
636 MachineInstrBuilder MIB
= BuildMI(&MBB
, dl
, get(Cond
[0].getImm()));
637 MIB
.addReg(Cond
[1].getReg()).addMBB(TBB
);
639 DEBUG(cerr
<< "Inserted one-way cond branch: ");
640 DEBUG((*MIB
).dump());
644 MachineInstrBuilder MIB
= BuildMI(&MBB
, dl
, get(Cond
[0].getImm()));
645 MachineInstrBuilder MIB2
= BuildMI(&MBB
, dl
, get(SPU::BR
));
647 // Two-way Conditional Branch.
648 MIB
.addReg(Cond
[1].getReg()).addMBB(TBB
);
651 DEBUG(cerr
<< "Inserted conditional branch: ");
652 DEBUG((*MIB
).dump());
653 DEBUG(cerr
<< "part 2: ");
654 DEBUG((*MIB2
).dump());
660 SPUInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock
&MBB
) const {
661 return (!MBB
.empty() && isUncondBranch(&MBB
.back()));
663 //! Reverses a branch's condition, returning false on success.
665 SPUInstrInfo::ReverseBranchCondition(SmallVectorImpl
<MachineOperand
> &Cond
)
667 // Pretty brainless way of inverting the condition, but it works, considering
668 // there are only two conditions...
670 unsigned Opc
; //! The incoming opcode
671 unsigned RevCondOpc
; //! The reversed condition opcode
673 { SPU::BRNZr32
, SPU::BRZr32
},
674 { SPU::BRNZv4i32
, SPU::BRZv4i32
},
675 { SPU::BRZr32
, SPU::BRNZr32
},
676 { SPU::BRZv4i32
, SPU::BRNZv4i32
},
677 { SPU::BRHNZr16
, SPU::BRHZr16
},
678 { SPU::BRHNZv8i16
, SPU::BRHZv8i16
},
679 { SPU::BRHZr16
, SPU::BRHNZr16
},
680 { SPU::BRHZv8i16
, SPU::BRHNZv8i16
}
683 unsigned Opc
= unsigned(Cond
[0].getImm());
684 // Pretty dull mapping between the two conditions that SPU can generate:
685 for (int i
= sizeof(revconds
)/sizeof(revconds
[0]) - 1; i
>= 0; --i
) {
686 if (revconds
[i
].Opc
== Opc
) {
687 Cond
[0].setImm(revconds
[i
].RevCondOpc
);