1 //===-- R600InstrInfo.cpp - R600 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 // R600 Implementation of TargetInstrInfo.
12 //===----------------------------------------------------------------------===//
14 #include "R600InstrInfo.h"
15 #include "AMDGPUTargetMachine.h"
16 #include "AMDGPUSubtarget.h"
17 #include "R600Defines.h"
18 #include "R600RegisterInfo.h"
19 #include "llvm/CodeGen/MachineInstrBuilder.h"
20 #include "AMDILUtilityFunctions.h"
22 #define GET_INSTRINFO_CTOR
23 #include "AMDGPUGenDFAPacketizer.inc"
27 R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine
&tm
)
28 : AMDGPUInstrInfo(tm
),
33 const R600RegisterInfo
&R600InstrInfo::getRegisterInfo() const
38 bool R600InstrInfo::isTrig(const MachineInstr
&MI
) const
40 return get(MI
.getOpcode()).TSFlags
& R600_InstFlag::TRIG
;
43 bool R600InstrInfo::isVector(const MachineInstr
&MI
) const
45 return get(MI
.getOpcode()).TSFlags
& R600_InstFlag::VECTOR
;
49 R600InstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
50 MachineBasicBlock::iterator MI
, DebugLoc DL
,
51 unsigned DestReg
, unsigned SrcReg
,
54 if (AMDGPU::R600_Reg128RegClass
.contains(DestReg
)
55 && AMDGPU::R600_Reg128RegClass
.contains(SrcReg
)) {
56 for (unsigned I
= 0; I
< 4; I
++) {
57 unsigned SubRegIndex
= RI
.getSubRegFromChannel(I
);
58 BuildMI(MBB
, MI
, DL
, get(AMDGPU::MOV
))
59 .addReg(RI
.getSubReg(DestReg
, SubRegIndex
), RegState::Define
)
60 .addReg(RI
.getSubReg(SrcReg
, SubRegIndex
))
62 .addReg(0) // PREDICATE_BIT
63 .addReg(DestReg
, RegState::Define
| RegState::Implicit
);
67 /* We can't copy vec4 registers */
68 assert(!AMDGPU::R600_Reg128RegClass
.contains(DestReg
)
69 && !AMDGPU::R600_Reg128RegClass
.contains(SrcReg
));
71 BuildMI(MBB
, MI
, DL
, get(AMDGPU::MOV
), DestReg
)
72 .addReg(SrcReg
, getKillRegState(KillSrc
))
74 .addReg(0); // PREDICATE_BIT
78 MachineInstr
* R600InstrInfo::getMovImmInstr(MachineFunction
*MF
,
79 unsigned DstReg
, int64_t Imm
) const
81 MachineInstr
* MI
= MF
->CreateMachineInstr(get(AMDGPU::MOV
), DebugLoc());
82 MachineInstrBuilder(MI
).addReg(DstReg
, RegState::Define
);
83 MachineInstrBuilder(MI
).addReg(AMDGPU::ALU_LITERAL_X
);
84 MachineInstrBuilder(MI
).addImm(Imm
);
85 MachineInstrBuilder(MI
).addReg(0); // PREDICATE_BIT
90 unsigned R600InstrInfo::getIEQOpcode() const
92 return AMDGPU::SETE_INT
;
95 bool R600InstrInfo::isMov(unsigned Opcode
) const
100 default: return false;
102 case AMDGPU::MOV_IMM_F32
:
103 case AMDGPU::MOV_IMM_I32
:
108 // Some instructions act as place holders to emulate operations that the GPU
109 // hardware does automatically. This function can be used to check if
110 // an opcode falls into this category.
111 bool R600InstrInfo::isPlaceHolderOpcode(unsigned Opcode
) const
114 default: return false;
116 case AMDGPU::MASK_WRITE
:
117 case AMDGPU::RESERVE_REG
:
122 bool R600InstrInfo::isReductionOp(unsigned Opcode
) const
125 default: return false;
126 case AMDGPU::DOT4_r600
:
127 case AMDGPU::DOT4_eg
:
132 bool R600InstrInfo::isCubeOp(unsigned Opcode
) const
135 default: return false;
136 case AMDGPU::CUBE_r600_pseudo
:
137 case AMDGPU::CUBE_r600_real
:
138 case AMDGPU::CUBE_eg_pseudo
:
139 case AMDGPU::CUBE_eg_real
:
144 DFAPacketizer
*R600InstrInfo::CreateTargetScheduleState(const TargetMachine
*TM
,
145 const ScheduleDAG
*DAG
) const
147 const InstrItineraryData
*II
= TM
->getInstrItineraryData();
148 return TM
->getSubtarget
<AMDGPUSubtarget
>().createDFAPacketizer(II
);
152 isPredicateSetter(unsigned Opcode
)
162 static MachineInstr
*
163 findFirstPredicateSetterFrom(MachineBasicBlock
&MBB
,
164 MachineBasicBlock::iterator I
)
166 while (I
!= MBB
.begin()) {
168 MachineInstr
*MI
= I
;
169 if (isPredicateSetter(MI
->getOpcode()))
177 R600InstrInfo::AnalyzeBranch(MachineBasicBlock
&MBB
,
178 MachineBasicBlock
*&TBB
,
179 MachineBasicBlock
*&FBB
,
180 SmallVectorImpl
<MachineOperand
> &Cond
,
181 bool AllowModify
) const
183 // Most of the following comes from the ARM implementation of AnalyzeBranch
185 // If the block has no terminators, it just falls into the block after it.
186 MachineBasicBlock::iterator I
= MBB
.end();
187 if (I
== MBB
.begin())
190 while (I
->isDebugValue()) {
191 if (I
== MBB
.begin())
195 if (static_cast<MachineInstr
*>(I
)->getOpcode() != AMDGPU::JUMP
) {
199 // Get the last instruction in the block.
200 MachineInstr
*LastInst
= I
;
202 // If there is only one terminator instruction, process it.
203 unsigned LastOpc
= LastInst
->getOpcode();
204 if (I
== MBB
.begin() ||
205 static_cast<MachineInstr
*>(--I
)->getOpcode() != AMDGPU::JUMP
) {
206 if (LastOpc
== AMDGPU::JUMP
) {
207 if(!isPredicated(LastInst
)) {
208 TBB
= LastInst
->getOperand(0).getMBB();
211 MachineInstr
*predSet
= I
;
212 while (!isPredicateSetter(predSet
->getOpcode())) {
215 TBB
= LastInst
->getOperand(0).getMBB();
216 Cond
.push_back(predSet
->getOperand(1));
217 Cond
.push_back(predSet
->getOperand(2));
218 Cond
.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE
, false));
222 return true; // Can't handle indirect branch.
225 // Get the instruction before it if it is a terminator.
226 MachineInstr
*SecondLastInst
= I
;
227 unsigned SecondLastOpc
= SecondLastInst
->getOpcode();
229 // If the block ends with a B and a Bcc, handle it.
230 if (SecondLastOpc
== AMDGPU::JUMP
&&
231 isPredicated(SecondLastInst
) &&
232 LastOpc
== AMDGPU::JUMP
&&
233 !isPredicated(LastInst
)) {
234 MachineInstr
*predSet
= --I
;
235 while (!isPredicateSetter(predSet
->getOpcode())) {
238 TBB
= SecondLastInst
->getOperand(0).getMBB();
239 FBB
= LastInst
->getOperand(0).getMBB();
240 Cond
.push_back(predSet
->getOperand(1));
241 Cond
.push_back(predSet
->getOperand(2));
242 Cond
.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE
, false));
246 // Otherwise, can't handle this.
250 int R600InstrInfo::getBranchInstr(const MachineOperand
&op
) const {
251 const MachineInstr
*MI
= op
.getParent();
253 switch (MI
->getDesc().OpInfo
->RegClass
) {
254 default: // FIXME: fallthrough??
255 case AMDGPU::GPRI32RegClassID
: return AMDGPU::BRANCH_COND_i32
;
256 case AMDGPU::GPRF32RegClassID
: return AMDGPU::BRANCH_COND_f32
;
261 R600InstrInfo::InsertBranch(MachineBasicBlock
&MBB
,
262 MachineBasicBlock
*TBB
,
263 MachineBasicBlock
*FBB
,
264 const SmallVectorImpl
<MachineOperand
> &Cond
,
267 assert(TBB
&& "InsertBranch must not be told to insert a fallthrough");
271 BuildMI(&MBB
, DL
, get(AMDGPU::JUMP
)).addMBB(TBB
).addReg(0);
274 MachineInstr
*PredSet
= findFirstPredicateSetterFrom(MBB
, MBB
.end());
275 assert(PredSet
&& "No previous predicate !");
276 addFlag(PredSet
, 1, MO_FLAG_PUSH
);
277 PredSet
->getOperand(2).setImm(Cond
[1].getImm());
279 BuildMI(&MBB
, DL
, get(AMDGPU::JUMP
))
281 .addReg(AMDGPU::PREDICATE_BIT
, RegState::Kill
);
285 MachineInstr
*PredSet
= findFirstPredicateSetterFrom(MBB
, MBB
.end());
286 assert(PredSet
&& "No previous predicate !");
287 addFlag(PredSet
, 1, MO_FLAG_PUSH
);
288 PredSet
->getOperand(2).setImm(Cond
[1].getImm());
289 BuildMI(&MBB
, DL
, get(AMDGPU::JUMP
))
291 .addReg(AMDGPU::PREDICATE_BIT
, RegState::Kill
);
292 BuildMI(&MBB
, DL
, get(AMDGPU::JUMP
)).addMBB(FBB
).addReg(0);
298 R600InstrInfo::RemoveBranch(MachineBasicBlock
&MBB
) const
301 // Note : we leave PRED* instructions there.
302 // They may be needed when predicating instructions.
304 MachineBasicBlock::iterator I
= MBB
.end();
306 if (I
== MBB
.begin()) {
310 switch (I
->getOpcode()) {
314 if (isPredicated(I
)) {
315 MachineInstr
*predSet
= findFirstPredicateSetterFrom(MBB
, I
);
316 clearFlag(predSet
, 1, MO_FLAG_PUSH
);
318 I
->eraseFromParent();
323 if (I
== MBB
.begin()) {
327 switch (I
->getOpcode()) {
328 // FIXME: only one case??
332 if (isPredicated(I
)) {
333 MachineInstr
*predSet
= findFirstPredicateSetterFrom(MBB
, I
);
334 clearFlag(predSet
, 1, MO_FLAG_PUSH
);
336 I
->eraseFromParent();
343 R600InstrInfo::isPredicated(const MachineInstr
*MI
) const
345 int idx
= MI
->findFirstPredOperandIdx();
349 unsigned Reg
= MI
->getOperand(idx
).getReg();
351 default: return false;
352 case AMDGPU::PRED_SEL_ONE
:
353 case AMDGPU::PRED_SEL_ZERO
:
354 case AMDGPU::PREDICATE_BIT
:
360 R600InstrInfo::isPredicable(MachineInstr
*MI
) const
362 return AMDGPUInstrInfo::isPredicable(MI
);
367 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock
&MBB
,
369 unsigned ExtraPredCycles
,
370 const BranchProbability
&Probability
) const{
375 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock
&TMBB
,
377 unsigned ExtraTCycles
,
378 MachineBasicBlock
&FMBB
,
380 unsigned ExtraFCycles
,
381 const BranchProbability
&Probability
) const
387 R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock
&MBB
,
389 const BranchProbability
&Probability
)
396 R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock
&TMBB
,
397 MachineBasicBlock
&FMBB
) const
404 R600InstrInfo::ReverseBranchCondition(SmallVectorImpl
<MachineOperand
> &Cond
) const
406 MachineOperand
&MO
= Cond
[1];
407 switch (MO
.getImm()) {
408 case OPCODE_IS_ZERO_INT
:
409 MO
.setImm(OPCODE_IS_NOT_ZERO_INT
);
411 case OPCODE_IS_NOT_ZERO_INT
:
412 MO
.setImm(OPCODE_IS_ZERO_INT
);
415 MO
.setImm(OPCODE_IS_NOT_ZERO
);
417 case OPCODE_IS_NOT_ZERO
:
418 MO
.setImm(OPCODE_IS_ZERO
);
424 MachineOperand
&MO2
= Cond
[2];
425 switch (MO2
.getReg()) {
426 case AMDGPU::PRED_SEL_ZERO
:
427 MO2
.setReg(AMDGPU::PRED_SEL_ONE
);
429 case AMDGPU::PRED_SEL_ONE
:
430 MO2
.setReg(AMDGPU::PRED_SEL_ZERO
);
439 R600InstrInfo::DefinesPredicate(MachineInstr
*MI
,
440 std::vector
<MachineOperand
> &Pred
) const
442 return isPredicateSetter(MI
->getOpcode());
447 R600InstrInfo::SubsumesPredicate(const SmallVectorImpl
<MachineOperand
> &Pred1
,
448 const SmallVectorImpl
<MachineOperand
> &Pred2
) const
455 R600InstrInfo::PredicateInstruction(MachineInstr
*MI
,
456 const SmallVectorImpl
<MachineOperand
> &Pred
) const
458 int PIdx
= MI
->findFirstPredOperandIdx();
461 MachineOperand
&PMO
= MI
->getOperand(PIdx
);
462 PMO
.setReg(Pred
[2].getReg());
463 MachineInstrBuilder(MI
).addReg(AMDGPU::PREDICATE_BIT
, RegState::Implicit
);
470 int R600InstrInfo::getInstrLatency(const InstrItineraryData
*ItinData
,
471 const MachineInstr
*MI
,
472 unsigned *PredCost
) const
479 //===----------------------------------------------------------------------===//
480 // Instruction flag getters/setters
481 //===----------------------------------------------------------------------===//
483 bool R600InstrInfo::hasFlagOperand(const MachineInstr
&MI
) const
485 return GET_FLAG_OPERAND_IDX(get(MI
.getOpcode()).TSFlags
) != 0;
488 MachineOperand
&R600InstrInfo::getFlagOp(MachineInstr
*MI
) const
490 unsigned FlagIndex
= GET_FLAG_OPERAND_IDX(get(MI
->getOpcode()).TSFlags
);
491 assert(FlagIndex
!= 0 &&
492 "Instruction flags not supported for this instruction");
493 MachineOperand
&FlagOp
= MI
->getOperand(FlagIndex
);
494 assert(FlagOp
.isImm());
498 void R600InstrInfo::addFlag(MachineInstr
*MI
, unsigned Operand
,
501 MachineOperand
&FlagOp
= getFlagOp(MI
);
502 FlagOp
.setImm(FlagOp
.getImm() | (Flag
<< (NUM_MO_FLAGS
* Operand
)));
505 void R600InstrInfo::clearFlag(MachineInstr
*MI
, unsigned Operand
,
508 MachineOperand
&FlagOp
= getFlagOp(MI
);
509 unsigned InstFlags
= FlagOp
.getImm();
510 InstFlags
&= ~(Flag
<< (NUM_MO_FLAGS
* Operand
));
511 FlagOp
.setImm(InstFlags
);