1 //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// R600 Implementation of TargetInstrInfo.
12 //===----------------------------------------------------------------------===//
14 #include "R600InstrInfo.h"
16 #include "MCTargetDesc/R600MCTargetDesc.h"
18 #include "R600Defines.h"
19 #include "R600Subtarget.h"
20 #include "llvm/ADT/SmallSet.h"
21 #include "llvm/CodeGen/MachineFrameInfo.h"
25 #define GET_INSTRINFO_CTOR_DTOR
26 #include "R600GenDFAPacketizer.inc"
28 #define GET_INSTRINFO_CTOR_DTOR
29 #define GET_INSTRMAP_INFO
30 #define GET_INSTRINFO_NAMED_OPS
31 #include "R600GenInstrInfo.inc"
33 R600InstrInfo::R600InstrInfo(const R600Subtarget
&ST
)
34 : R600GenInstrInfo(-1, -1), RI(), ST(ST
) {}
36 bool R600InstrInfo::isVector(const MachineInstr
&MI
) const {
37 return get(MI
.getOpcode()).TSFlags
& R600_InstFlag::VECTOR
;
40 void R600InstrInfo::copyPhysReg(MachineBasicBlock
&MBB
,
41 MachineBasicBlock::iterator MI
,
42 const DebugLoc
&DL
, MCRegister DestReg
,
43 MCRegister SrcReg
, bool KillSrc
) const {
44 unsigned VectorComponents
= 0;
45 if ((R600::R600_Reg128RegClass
.contains(DestReg
) ||
46 R600::R600_Reg128VerticalRegClass
.contains(DestReg
)) &&
47 (R600::R600_Reg128RegClass
.contains(SrcReg
) ||
48 R600::R600_Reg128VerticalRegClass
.contains(SrcReg
))) {
50 } else if((R600::R600_Reg64RegClass
.contains(DestReg
) ||
51 R600::R600_Reg64VerticalRegClass
.contains(DestReg
)) &&
52 (R600::R600_Reg64RegClass
.contains(SrcReg
) ||
53 R600::R600_Reg64VerticalRegClass
.contains(SrcReg
))) {
57 if (VectorComponents
> 0) {
58 for (unsigned I
= 0; I
< VectorComponents
; I
++) {
59 unsigned SubRegIndex
= R600RegisterInfo::getSubRegFromChannel(I
);
60 buildDefaultInstruction(MBB
, MI
, R600::MOV
,
61 RI
.getSubReg(DestReg
, SubRegIndex
),
62 RI
.getSubReg(SrcReg
, SubRegIndex
))
64 RegState::Define
| RegState::Implicit
);
67 MachineInstr
*NewMI
= buildDefaultInstruction(MBB
, MI
, R600::MOV
,
69 NewMI
->getOperand(getOperandIdx(*NewMI
, R600::OpName::src0
))
74 /// \returns true if \p MBBI can be moved into a new basic.
75 bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock
&MBB
,
76 MachineBasicBlock::iterator MBBI
) const {
77 for (MachineInstr::const_mop_iterator I
= MBBI
->operands_begin(),
78 E
= MBBI
->operands_end(); I
!= E
; ++I
) {
79 if (I
->isReg() && !I
->getReg().isVirtual() && I
->isUse() &&
80 RI
.isPhysRegLiveAcrossClauses(I
->getReg()))
86 bool R600InstrInfo::isMov(unsigned Opcode
) const {
91 case R600::MOV_IMM_F32
:
92 case R600::MOV_IMM_I32
:
97 bool R600InstrInfo::isReductionOp(unsigned Opcode
) const {
101 bool R600InstrInfo::isCubeOp(unsigned Opcode
) const {
103 default: return false;
104 case R600::CUBE_r600_pseudo
:
105 case R600::CUBE_r600_real
:
106 case R600::CUBE_eg_pseudo
:
107 case R600::CUBE_eg_real
:
112 bool R600InstrInfo::isALUInstr(unsigned Opcode
) const {
113 unsigned TargetFlags
= get(Opcode
).TSFlags
;
115 return (TargetFlags
& R600_InstFlag::ALU_INST
);
118 bool R600InstrInfo::hasInstrModifiers(unsigned Opcode
) const {
119 unsigned TargetFlags
= get(Opcode
).TSFlags
;
121 return ((TargetFlags
& R600_InstFlag::OP1
) |
122 (TargetFlags
& R600_InstFlag::OP2
) |
123 (TargetFlags
& R600_InstFlag::OP3
));
126 bool R600InstrInfo::isLDSInstr(unsigned Opcode
) const {
127 unsigned TargetFlags
= get(Opcode
).TSFlags
;
129 return ((TargetFlags
& R600_InstFlag::LDS_1A
) |
130 (TargetFlags
& R600_InstFlag::LDS_1A1D
) |
131 (TargetFlags
& R600_InstFlag::LDS_1A2D
));
134 bool R600InstrInfo::isLDSRetInstr(unsigned Opcode
) const {
135 return isLDSInstr(Opcode
) && getOperandIdx(Opcode
, R600::OpName::dst
) != -1;
138 bool R600InstrInfo::canBeConsideredALU(const MachineInstr
&MI
) const {
139 if (isALUInstr(MI
.getOpcode()))
141 if (isVector(MI
) || isCubeOp(MI
.getOpcode()))
143 switch (MI
.getOpcode()) {
145 case R600::INTERP_PAIR_XY
:
146 case R600::INTERP_PAIR_ZW
:
147 case R600::INTERP_VEC_LOAD
:
156 bool R600InstrInfo::isTransOnly(unsigned Opcode
) const {
157 if (ST
.hasCaymanISA())
159 return (get(Opcode
).getSchedClass() == R600::Sched::TransALU
);
162 bool R600InstrInfo::isTransOnly(const MachineInstr
&MI
) const {
163 return isTransOnly(MI
.getOpcode());
166 bool R600InstrInfo::isVectorOnly(unsigned Opcode
) const {
167 return (get(Opcode
).getSchedClass() == R600::Sched::VecALU
);
170 bool R600InstrInfo::isVectorOnly(const MachineInstr
&MI
) const {
171 return isVectorOnly(MI
.getOpcode());
174 bool R600InstrInfo::isExport(unsigned Opcode
) const {
175 return (get(Opcode
).TSFlags
& R600_InstFlag::IS_EXPORT
);
178 bool R600InstrInfo::usesVertexCache(unsigned Opcode
) const {
179 return ST
.hasVertexCache() && IS_VTX(get(Opcode
));
182 bool R600InstrInfo::usesVertexCache(const MachineInstr
&MI
) const {
183 const MachineFunction
*MF
= MI
.getParent()->getParent();
184 return !AMDGPU::isCompute(MF
->getFunction().getCallingConv()) &&
185 usesVertexCache(MI
.getOpcode());
188 bool R600InstrInfo::usesTextureCache(unsigned Opcode
) const {
189 return (!ST
.hasVertexCache() && IS_VTX(get(Opcode
))) || IS_TEX(get(Opcode
));
192 bool R600InstrInfo::usesTextureCache(const MachineInstr
&MI
) const {
193 const MachineFunction
*MF
= MI
.getParent()->getParent();
194 return (AMDGPU::isCompute(MF
->getFunction().getCallingConv()) &&
195 usesVertexCache(MI
.getOpcode())) ||
196 usesTextureCache(MI
.getOpcode());
199 bool R600InstrInfo::mustBeLastInClause(unsigned Opcode
) const {
202 case R600::GROUP_BARRIER
:
209 bool R600InstrInfo::usesAddressRegister(MachineInstr
&MI
) const {
210 return MI
.findRegisterUseOperandIdx(R600::AR_X
, &RI
, false) != -1;
213 bool R600InstrInfo::definesAddressRegister(MachineInstr
&MI
) const {
214 return MI
.findRegisterDefOperandIdx(R600::AR_X
, &RI
, false, false) != -1;
217 bool R600InstrInfo::readsLDSSrcReg(const MachineInstr
&MI
) const {
218 if (!isALUInstr(MI
.getOpcode())) {
221 for (MachineInstr::const_mop_iterator I
= MI
.operands_begin(),
222 E
= MI
.operands_end();
224 if (!I
->isReg() || !I
->isUse() || I
->getReg().isVirtual())
227 if (R600::R600_LDS_SRC_REGRegClass
.contains(I
->getReg()))
233 int R600InstrInfo::getSelIdx(unsigned Opcode
, unsigned SrcIdx
) const {
234 static const unsigned SrcSelTable
[][2] = {
235 {R600::OpName::src0
, R600::OpName::src0_sel
},
236 {R600::OpName::src1
, R600::OpName::src1_sel
},
237 {R600::OpName::src2
, R600::OpName::src2_sel
},
238 {R600::OpName::src0_X
, R600::OpName::src0_sel_X
},
239 {R600::OpName::src0_Y
, R600::OpName::src0_sel_Y
},
240 {R600::OpName::src0_Z
, R600::OpName::src0_sel_Z
},
241 {R600::OpName::src0_W
, R600::OpName::src0_sel_W
},
242 {R600::OpName::src1_X
, R600::OpName::src1_sel_X
},
243 {R600::OpName::src1_Y
, R600::OpName::src1_sel_Y
},
244 {R600::OpName::src1_Z
, R600::OpName::src1_sel_Z
},
245 {R600::OpName::src1_W
, R600::OpName::src1_sel_W
}
248 for (const auto &Row
: SrcSelTable
) {
249 if (getOperandIdx(Opcode
, Row
[0]) == (int)SrcIdx
) {
250 return getOperandIdx(Opcode
, Row
[1]);
256 SmallVector
<std::pair
<MachineOperand
*, int64_t>, 3>
257 R600InstrInfo::getSrcs(MachineInstr
&MI
) const {
258 SmallVector
<std::pair
<MachineOperand
*, int64_t>, 3> Result
;
260 if (MI
.getOpcode() == R600::DOT_4
) {
261 static const unsigned OpTable
[8][2] = {
262 {R600::OpName::src0_X
, R600::OpName::src0_sel_X
},
263 {R600::OpName::src0_Y
, R600::OpName::src0_sel_Y
},
264 {R600::OpName::src0_Z
, R600::OpName::src0_sel_Z
},
265 {R600::OpName::src0_W
, R600::OpName::src0_sel_W
},
266 {R600::OpName::src1_X
, R600::OpName::src1_sel_X
},
267 {R600::OpName::src1_Y
, R600::OpName::src1_sel_Y
},
268 {R600::OpName::src1_Z
, R600::OpName::src1_sel_Z
},
269 {R600::OpName::src1_W
, R600::OpName::src1_sel_W
},
272 for (const auto &Op
: OpTable
) {
273 MachineOperand
&MO
= MI
.getOperand(getOperandIdx(MI
.getOpcode(), Op
[0]));
274 Register Reg
= MO
.getReg();
275 if (Reg
== R600::ALU_CONST
) {
276 MachineOperand
&Sel
=
277 MI
.getOperand(getOperandIdx(MI
.getOpcode(), Op
[1]));
278 Result
.push_back(std::pair(&MO
, Sel
.getImm()));
285 static const unsigned OpTable
[3][2] = {
286 {R600::OpName::src0
, R600::OpName::src0_sel
},
287 {R600::OpName::src1
, R600::OpName::src1_sel
},
288 {R600::OpName::src2
, R600::OpName::src2_sel
},
291 for (const auto &Op
: OpTable
) {
292 int SrcIdx
= getOperandIdx(MI
.getOpcode(), Op
[0]);
295 MachineOperand
&MO
= MI
.getOperand(SrcIdx
);
296 Register Reg
= MO
.getReg();
297 if (Reg
== R600::ALU_CONST
) {
298 MachineOperand
&Sel
= MI
.getOperand(getOperandIdx(MI
.getOpcode(), Op
[1]));
299 Result
.push_back(std::pair(&MO
, Sel
.getImm()));
302 if (Reg
== R600::ALU_LITERAL_X
) {
303 MachineOperand
&Operand
=
304 MI
.getOperand(getOperandIdx(MI
.getOpcode(), R600::OpName::literal
));
305 if (Operand
.isImm()) {
306 Result
.push_back(std::pair(&MO
, Operand
.getImm()));
309 assert(Operand
.isGlobal());
311 Result
.push_back(std::pair(&MO
, 0));
316 std::vector
<std::pair
<int, unsigned>>
317 R600InstrInfo::ExtractSrcs(MachineInstr
&MI
,
318 const DenseMap
<unsigned, unsigned> &PV
,
319 unsigned &ConstCount
) const {
321 const std::pair
<int, unsigned> DummyPair(-1, 0);
322 std::vector
<std::pair
<int, unsigned>> Result
;
324 for (const auto &Src
: getSrcs(MI
)) {
326 Register Reg
= Src
.first
->getReg();
327 int Index
= RI
.getEncodingValue(Reg
) & 0xff;
328 if (Reg
== R600::OQAP
) {
329 Result
.emplace_back(Index
, 0U);
331 if (PV
.contains(Reg
)) {
332 // 255 is used to tells its a PS/PV reg
333 Result
.emplace_back(255, 0U);
338 Result
.push_back(DummyPair
);
341 unsigned Chan
= RI
.getHWRegChan(Reg
);
342 Result
.emplace_back(Index
, Chan
);
345 Result
.push_back(DummyPair
);
349 static std::vector
<std::pair
<int, unsigned>>
350 Swizzle(std::vector
<std::pair
<int, unsigned>> Src
,
351 R600InstrInfo::BankSwizzle Swz
) {
352 if (Src
[0] == Src
[1])
355 case R600InstrInfo::ALU_VEC_012_SCL_210
:
357 case R600InstrInfo::ALU_VEC_021_SCL_122
:
358 std::swap(Src
[1], Src
[2]);
360 case R600InstrInfo::ALU_VEC_102_SCL_221
:
361 std::swap(Src
[0], Src
[1]);
363 case R600InstrInfo::ALU_VEC_120_SCL_212
:
364 std::swap(Src
[0], Src
[1]);
365 std::swap(Src
[0], Src
[2]);
367 case R600InstrInfo::ALU_VEC_201
:
368 std::swap(Src
[0], Src
[2]);
369 std::swap(Src
[0], Src
[1]);
371 case R600InstrInfo::ALU_VEC_210
:
372 std::swap(Src
[0], Src
[2]);
378 static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz
, unsigned Op
) {
379 assert(Op
< 3 && "Out of range swizzle index");
381 case R600InstrInfo::ALU_VEC_012_SCL_210
: {
382 unsigned Cycles
[3] = { 2, 1, 0};
385 case R600InstrInfo::ALU_VEC_021_SCL_122
: {
386 unsigned Cycles
[3] = { 1, 2, 2};
389 case R600InstrInfo::ALU_VEC_120_SCL_212
: {
390 unsigned Cycles
[3] = { 2, 1, 2};
393 case R600InstrInfo::ALU_VEC_102_SCL_221
: {
394 unsigned Cycles
[3] = { 2, 2, 1};
398 llvm_unreachable("Wrong Swizzle for Trans Slot");
402 /// returns how many MIs (whose inputs are represented by IGSrcs) can be packed
403 /// in the same Instruction Group while meeting read port limitations given a
404 /// Swz swizzle sequence.
405 unsigned R600InstrInfo::isLegalUpTo(
406 const std::vector
<std::vector
<std::pair
<int, unsigned>>> &IGSrcs
,
407 const std::vector
<R600InstrInfo::BankSwizzle
> &Swz
,
408 const std::vector
<std::pair
<int, unsigned>> &TransSrcs
,
409 R600InstrInfo::BankSwizzle TransSwz
) const {
411 memset(Vector
, -1, sizeof(Vector
));
412 for (unsigned i
= 0, e
= IGSrcs
.size(); i
< e
; i
++) {
413 const std::vector
<std::pair
<int, unsigned>> &Srcs
=
414 Swizzle(IGSrcs
[i
], Swz
[i
]);
415 for (unsigned j
= 0; j
< 3; j
++) {
416 const std::pair
<int, unsigned> &Src
= Srcs
[j
];
417 if (Src
.first
< 0 || Src
.first
== 255)
419 if (Src
.first
== GET_REG_INDEX(RI
.getEncodingValue(R600::OQAP
))) {
420 if (Swz
[i
] != R600InstrInfo::ALU_VEC_012_SCL_210
&&
421 Swz
[i
] != R600InstrInfo::ALU_VEC_021_SCL_122
) {
422 // The value from output queue A (denoted by register OQAP) can
423 // only be fetched during the first cycle.
426 // OQAP does not count towards the normal read port restrictions
429 if (Vector
[Src
.second
][j
] < 0)
430 Vector
[Src
.second
][j
] = Src
.first
;
431 if (Vector
[Src
.second
][j
] != Src
.first
)
435 // Now check Trans Alu
436 for (unsigned i
= 0, e
= TransSrcs
.size(); i
< e
; ++i
) {
437 const std::pair
<int, unsigned> &Src
= TransSrcs
[i
];
438 unsigned Cycle
= getTransSwizzle(TransSwz
, i
);
441 if (Src
.first
== 255)
443 if (Vector
[Src
.second
][Cycle
] < 0)
444 Vector
[Src
.second
][Cycle
] = Src
.first
;
445 if (Vector
[Src
.second
][Cycle
] != Src
.first
)
446 return IGSrcs
.size() - 1;
448 return IGSrcs
.size();
451 /// Given a swizzle sequence SwzCandidate and an index Idx, returns the next
452 /// (in lexicographic term) swizzle sequence assuming that all swizzles after
453 /// Idx can be skipped
455 NextPossibleSolution(
456 std::vector
<R600InstrInfo::BankSwizzle
> &SwzCandidate
,
458 assert(Idx
< SwzCandidate
.size());
460 while (ResetIdx
> -1 && SwzCandidate
[ResetIdx
] == R600InstrInfo::ALU_VEC_210
)
462 for (unsigned i
= ResetIdx
+ 1, e
= SwzCandidate
.size(); i
< e
; i
++) {
463 SwzCandidate
[i
] = R600InstrInfo::ALU_VEC_012_SCL_210
;
467 int NextSwizzle
= SwzCandidate
[ResetIdx
] + 1;
468 SwzCandidate
[ResetIdx
] = (R600InstrInfo::BankSwizzle
)NextSwizzle
;
472 /// Enumerate all possible Swizzle sequence to find one that can meet all
473 /// read port requirements.
474 bool R600InstrInfo::FindSwizzleForVectorSlot(
475 const std::vector
<std::vector
<std::pair
<int, unsigned>>> &IGSrcs
,
476 std::vector
<R600InstrInfo::BankSwizzle
> &SwzCandidate
,
477 const std::vector
<std::pair
<int, unsigned>> &TransSrcs
,
478 R600InstrInfo::BankSwizzle TransSwz
) const {
479 unsigned ValidUpTo
= 0;
481 ValidUpTo
= isLegalUpTo(IGSrcs
, SwzCandidate
, TransSrcs
, TransSwz
);
482 if (ValidUpTo
== IGSrcs
.size())
484 } while (NextPossibleSolution(SwzCandidate
, ValidUpTo
));
488 /// Instructions in Trans slot can't read gpr at cycle 0 if they also read
489 /// a const, and can't read a gpr at cycle 1 if they read 2 const.
491 isConstCompatible(R600InstrInfo::BankSwizzle TransSwz
,
492 const std::vector
<std::pair
<int, unsigned>> &TransOps
,
493 unsigned ConstCount
) {
494 // TransALU can't read 3 constants
497 for (unsigned i
= 0, e
= TransOps
.size(); i
< e
; ++i
) {
498 const std::pair
<int, unsigned> &Src
= TransOps
[i
];
499 unsigned Cycle
= getTransSwizzle(TransSwz
, i
);
502 if (ConstCount
> 0 && Cycle
== 0)
504 if (ConstCount
> 1 && Cycle
== 1)
511 R600InstrInfo::fitsReadPortLimitations(const std::vector
<MachineInstr
*> &IG
,
512 const DenseMap
<unsigned, unsigned> &PV
,
513 std::vector
<BankSwizzle
> &ValidSwizzle
,
516 //Todo : support shared src0 - src1 operand
518 std::vector
<std::vector
<std::pair
<int, unsigned>>> IGSrcs
;
519 ValidSwizzle
.clear();
521 BankSwizzle TransBS
= ALU_VEC_012_SCL_210
;
522 for (MachineInstr
*MI
: IG
) {
523 IGSrcs
.push_back(ExtractSrcs(*MI
, PV
, ConstCount
));
524 unsigned Op
= getOperandIdx(MI
->getOpcode(), R600::OpName::bank_swizzle
);
525 ValidSwizzle
.push_back(
526 (R600InstrInfo::BankSwizzle
)MI
->getOperand(Op
).getImm());
528 std::vector
<std::pair
<int, unsigned>> TransOps
;
530 return FindSwizzleForVectorSlot(IGSrcs
, ValidSwizzle
, TransOps
, TransBS
);
532 TransOps
= std::move(IGSrcs
.back());
534 ValidSwizzle
.pop_back();
536 static const R600InstrInfo::BankSwizzle TransSwz
[] = {
542 for (R600InstrInfo::BankSwizzle TransBS
: TransSwz
) {
543 if (!isConstCompatible(TransBS
, TransOps
, ConstCount
))
545 bool Result
= FindSwizzleForVectorSlot(IGSrcs
, ValidSwizzle
, TransOps
,
548 ValidSwizzle
.push_back(TransBS
);
557 R600InstrInfo::fitsConstReadLimitations(const std::vector
<unsigned> &Consts
)
559 assert (Consts
.size() <= 12 && "Too many operands in instructions group");
560 unsigned Pair1
= 0, Pair2
= 0;
561 for (unsigned Const
: Consts
) {
562 unsigned ReadConstHalf
= Const
& 2;
563 unsigned ReadConstIndex
= Const
& (~3);
564 unsigned ReadHalfConst
= ReadConstIndex
| ReadConstHalf
;
566 Pair1
= ReadHalfConst
;
569 if (Pair1
== ReadHalfConst
)
572 Pair2
= ReadHalfConst
;
575 if (Pair2
!= ReadHalfConst
)
582 R600InstrInfo::fitsConstReadLimitations(const std::vector
<MachineInstr
*> &MIs
)
584 std::vector
<unsigned> Consts
;
585 SmallSet
<int64_t, 4> Literals
;
586 for (MachineInstr
*MI
: MIs
) {
587 if (!isALUInstr(MI
->getOpcode()))
590 for (const auto &Src
: getSrcs(*MI
)) {
591 if (Src
.first
->getReg() == R600::ALU_LITERAL_X
)
592 Literals
.insert(Src
.second
);
593 if (Literals
.size() > 4)
595 if (Src
.first
->getReg() == R600::ALU_CONST
)
596 Consts
.push_back(Src
.second
);
597 if (R600::R600_KC0RegClass
.contains(Src
.first
->getReg()) ||
598 R600::R600_KC1RegClass
.contains(Src
.first
->getReg())) {
599 unsigned Index
= RI
.getEncodingValue(Src
.first
->getReg()) & 0xff;
600 unsigned Chan
= RI
.getHWRegChan(Src
.first
->getReg());
601 Consts
.push_back((Index
<< 2) | Chan
);
605 return fitsConstReadLimitations(Consts
);
609 R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo
&STI
) const {
610 const InstrItineraryData
*II
= STI
.getInstrItineraryData();
611 return static_cast<const R600Subtarget
&>(STI
).createDFAPacketizer(II
);
615 isPredicateSetter(unsigned Opcode
) {
624 static MachineInstr
*
625 findFirstPredicateSetterFrom(MachineBasicBlock
&MBB
,
626 MachineBasicBlock::iterator I
) {
627 while (I
!= MBB
.begin()) {
629 MachineInstr
&MI
= *I
;
630 if (isPredicateSetter(MI
.getOpcode()))
638 bool isJump(unsigned Opcode
) {
639 return Opcode
== R600::JUMP
|| Opcode
== R600::JUMP_COND
;
642 static bool isBranch(unsigned Opcode
) {
643 return Opcode
== R600::BRANCH
|| Opcode
== R600::BRANCH_COND_i32
||
644 Opcode
== R600::BRANCH_COND_f32
;
647 bool R600InstrInfo::analyzeBranch(MachineBasicBlock
&MBB
,
648 MachineBasicBlock
*&TBB
,
649 MachineBasicBlock
*&FBB
,
650 SmallVectorImpl
<MachineOperand
> &Cond
,
651 bool AllowModify
) const {
652 // Most of the following comes from the ARM implementation of analyzeBranch
654 // If the block has no terminators, it just falls into the block after it.
655 MachineBasicBlock::iterator I
= MBB
.getLastNonDebugInstr();
659 // R600::BRANCH* instructions are only available after isel and are not
661 if (isBranch(I
->getOpcode()))
663 if (!isJump(I
->getOpcode())) {
667 // Remove successive JUMP
668 while (I
!= MBB
.begin() && std::prev(I
)->getOpcode() == R600::JUMP
) {
669 MachineBasicBlock::iterator PriorI
= std::prev(I
);
671 I
->removeFromParent();
674 MachineInstr
&LastInst
= *I
;
676 // If there is only one terminator instruction, process it.
677 unsigned LastOpc
= LastInst
.getOpcode();
678 if (I
== MBB
.begin() || !isJump((--I
)->getOpcode())) {
679 if (LastOpc
== R600::JUMP
) {
680 TBB
= LastInst
.getOperand(0).getMBB();
683 if (LastOpc
== R600::JUMP_COND
) {
685 while (!isPredicateSetter(predSet
->getOpcode())) {
688 TBB
= LastInst
.getOperand(0).getMBB();
689 Cond
.push_back(predSet
->getOperand(1));
690 Cond
.push_back(predSet
->getOperand(2));
691 Cond
.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE
, false));
694 return true; // Can't handle indirect branch.
697 // Get the instruction before it if it is a terminator.
698 MachineInstr
&SecondLastInst
= *I
;
699 unsigned SecondLastOpc
= SecondLastInst
.getOpcode();
701 // If the block ends with a B and a Bcc, handle it.
702 if (SecondLastOpc
== R600::JUMP_COND
&& LastOpc
== R600::JUMP
) {
704 while (!isPredicateSetter(predSet
->getOpcode())) {
707 TBB
= SecondLastInst
.getOperand(0).getMBB();
708 FBB
= LastInst
.getOperand(0).getMBB();
709 Cond
.push_back(predSet
->getOperand(1));
710 Cond
.push_back(predSet
->getOperand(2));
711 Cond
.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE
, false));
715 // Otherwise, can't handle this.
720 MachineBasicBlock::iterator
FindLastAluClause(MachineBasicBlock
&MBB
) {
721 for (MachineBasicBlock::reverse_iterator It
= MBB
.rbegin(), E
= MBB
.rend();
723 if (It
->getOpcode() == R600::CF_ALU
||
724 It
->getOpcode() == R600::CF_ALU_PUSH_BEFORE
)
725 return It
.getReverse();
730 unsigned R600InstrInfo::insertBranch(MachineBasicBlock
&MBB
,
731 MachineBasicBlock
*TBB
,
732 MachineBasicBlock
*FBB
,
733 ArrayRef
<MachineOperand
> Cond
,
735 int *BytesAdded
) const {
736 assert(TBB
&& "insertBranch must not be told to insert a fallthrough");
737 assert(!BytesAdded
&& "code size not handled");
741 BuildMI(&MBB
, DL
, get(R600::JUMP
)).addMBB(TBB
);
744 MachineInstr
*PredSet
= findFirstPredicateSetterFrom(MBB
, MBB
.end());
745 assert(PredSet
&& "No previous predicate !");
746 addFlag(*PredSet
, 0, MO_FLAG_PUSH
);
747 PredSet
->getOperand(2).setImm(Cond
[1].getImm());
749 BuildMI(&MBB
, DL
, get(R600::JUMP_COND
))
751 .addReg(R600::PREDICATE_BIT
, RegState::Kill
);
752 MachineBasicBlock::iterator CfAlu
= FindLastAluClause(MBB
);
753 if (CfAlu
== MBB
.end())
755 assert (CfAlu
->getOpcode() == R600::CF_ALU
);
756 CfAlu
->setDesc(get(R600::CF_ALU_PUSH_BEFORE
));
759 MachineInstr
*PredSet
= findFirstPredicateSetterFrom(MBB
, MBB
.end());
760 assert(PredSet
&& "No previous predicate !");
761 addFlag(*PredSet
, 0, MO_FLAG_PUSH
);
762 PredSet
->getOperand(2).setImm(Cond
[1].getImm());
763 BuildMI(&MBB
, DL
, get(R600::JUMP_COND
))
765 .addReg(R600::PREDICATE_BIT
, RegState::Kill
);
766 BuildMI(&MBB
, DL
, get(R600::JUMP
)).addMBB(FBB
);
767 MachineBasicBlock::iterator CfAlu
= FindLastAluClause(MBB
);
768 if (CfAlu
== MBB
.end())
770 assert(CfAlu
->getOpcode() == R600::CF_ALU
);
771 CfAlu
->setDesc(get(R600::CF_ALU_PUSH_BEFORE
));
775 unsigned R600InstrInfo::removeBranch(MachineBasicBlock
&MBB
,
776 int *BytesRemoved
) const {
777 assert(!BytesRemoved
&& "code size not handled");
779 // Note : we leave PRED* instructions there.
780 // They may be needed when predicating instructions.
782 MachineBasicBlock::iterator I
= MBB
.end();
784 if (I
== MBB
.begin()) {
788 switch (I
->getOpcode()) {
791 case R600::JUMP_COND
: {
792 MachineInstr
*predSet
= findFirstPredicateSetterFrom(MBB
, I
);
793 clearFlag(*predSet
, 0, MO_FLAG_PUSH
);
794 I
->eraseFromParent();
795 MachineBasicBlock::iterator CfAlu
= FindLastAluClause(MBB
);
796 if (CfAlu
== MBB
.end())
798 assert (CfAlu
->getOpcode() == R600::CF_ALU_PUSH_BEFORE
);
799 CfAlu
->setDesc(get(R600::CF_ALU
));
803 I
->eraseFromParent();
808 if (I
== MBB
.begin()) {
812 switch (I
->getOpcode()) {
813 // FIXME: only one case??
816 case R600::JUMP_COND
: {
817 MachineInstr
*predSet
= findFirstPredicateSetterFrom(MBB
, I
);
818 clearFlag(*predSet
, 0, MO_FLAG_PUSH
);
819 I
->eraseFromParent();
820 MachineBasicBlock::iterator CfAlu
= FindLastAluClause(MBB
);
821 if (CfAlu
== MBB
.end())
823 assert (CfAlu
->getOpcode() == R600::CF_ALU_PUSH_BEFORE
);
824 CfAlu
->setDesc(get(R600::CF_ALU
));
828 I
->eraseFromParent();
834 bool R600InstrInfo::isPredicated(const MachineInstr
&MI
) const {
835 int idx
= MI
.findFirstPredOperandIdx();
839 Register Reg
= MI
.getOperand(idx
).getReg();
841 default: return false;
842 case R600::PRED_SEL_ONE
:
843 case R600::PRED_SEL_ZERO
:
844 case R600::PREDICATE_BIT
:
849 bool R600InstrInfo::isPredicable(const MachineInstr
&MI
) const {
850 // XXX: KILL* instructions can be predicated, but they must be the last
851 // instruction in a clause, so this means any instructions after them cannot
852 // be predicated. Until we have proper support for instruction clauses in the
853 // backend, we will mark KILL* instructions as unpredicable.
855 if (MI
.getOpcode() == R600::KILLGT
)
857 if (MI
.getOpcode() == R600::CF_ALU
) {
858 // If the clause start in the middle of MBB then the MBB has more
859 // than a single clause, unable to predicate several clauses.
860 if (MI
.getParent()->begin() != MachineBasicBlock::const_iterator(MI
))
862 // TODO: We don't support KC merging atm
863 return MI
.getOperand(3).getImm() == 0 && MI
.getOperand(4).getImm() == 0;
867 return TargetInstrInfo::isPredicable(MI
);
871 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock
&MBB
,
873 unsigned ExtraPredCycles
,
874 BranchProbability Probability
) const{
879 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock
&TMBB
,
881 unsigned ExtraTCycles
,
882 MachineBasicBlock
&FMBB
,
884 unsigned ExtraFCycles
,
885 BranchProbability Probability
) const {
890 R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock
&MBB
,
892 BranchProbability Probability
)
898 R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock
&TMBB
,
899 MachineBasicBlock
&FMBB
) const {
904 R600InstrInfo::reverseBranchCondition(SmallVectorImpl
<MachineOperand
> &Cond
) const {
905 MachineOperand
&MO
= Cond
[1];
906 switch (MO
.getImm()) {
907 case R600::PRED_SETE_INT
:
908 MO
.setImm(R600::PRED_SETNE_INT
);
910 case R600::PRED_SETNE_INT
:
911 MO
.setImm(R600::PRED_SETE_INT
);
913 case R600::PRED_SETE
:
914 MO
.setImm(R600::PRED_SETNE
);
916 case R600::PRED_SETNE
:
917 MO
.setImm(R600::PRED_SETE
);
923 MachineOperand
&MO2
= Cond
[2];
924 switch (MO2
.getReg()) {
925 case R600::PRED_SEL_ZERO
:
926 MO2
.setReg(R600::PRED_SEL_ONE
);
928 case R600::PRED_SEL_ONE
:
929 MO2
.setReg(R600::PRED_SEL_ZERO
);
937 bool R600InstrInfo::ClobbersPredicate(MachineInstr
&MI
,
938 std::vector
<MachineOperand
> &Pred
,
939 bool SkipDead
) const {
940 return isPredicateSetter(MI
.getOpcode());
943 bool R600InstrInfo::PredicateInstruction(MachineInstr
&MI
,
944 ArrayRef
<MachineOperand
> Pred
) const {
945 int PIdx
= MI
.findFirstPredOperandIdx();
947 if (MI
.getOpcode() == R600::CF_ALU
) {
948 MI
.getOperand(8).setImm(0);
952 if (MI
.getOpcode() == R600::DOT_4
) {
953 MI
.getOperand(getOperandIdx(MI
, R600::OpName::pred_sel_X
))
954 .setReg(Pred
[2].getReg());
955 MI
.getOperand(getOperandIdx(MI
, R600::OpName::pred_sel_Y
))
956 .setReg(Pred
[2].getReg());
957 MI
.getOperand(getOperandIdx(MI
, R600::OpName::pred_sel_Z
))
958 .setReg(Pred
[2].getReg());
959 MI
.getOperand(getOperandIdx(MI
, R600::OpName::pred_sel_W
))
960 .setReg(Pred
[2].getReg());
961 MachineInstrBuilder
MIB(*MI
.getParent()->getParent(), MI
);
962 MIB
.addReg(R600::PREDICATE_BIT
, RegState::Implicit
);
967 MachineOperand
&PMO
= MI
.getOperand(PIdx
);
968 PMO
.setReg(Pred
[2].getReg());
969 MachineInstrBuilder
MIB(*MI
.getParent()->getParent(), MI
);
970 MIB
.addReg(R600::PREDICATE_BIT
, RegState::Implicit
);
977 unsigned int R600InstrInfo::getPredicationCost(const MachineInstr
&) const {
981 unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData
*ItinData
,
982 const MachineInstr
&,
983 unsigned *PredCost
) const {
989 unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex
,
990 unsigned Channel
) const {
991 assert(Channel
== 0);
995 bool R600InstrInfo::expandPostRAPseudo(MachineInstr
&MI
) const {
996 switch (MI
.getOpcode()) {
998 MachineBasicBlock
*MBB
= MI
.getParent();
1000 R600::getNamedOperandIdx(MI
.getOpcode(), R600::OpName::addr
);
1001 // addr is a custom operand with multiple MI operands, and only the
1002 // first MI operand is given a name.
1003 int RegOpIdx
= OffsetOpIdx
+ 1;
1005 R600::getNamedOperandIdx(MI
.getOpcode(), R600::OpName::chan
);
1006 if (isRegisterLoad(MI
)) {
1008 R600::getNamedOperandIdx(MI
.getOpcode(), R600::OpName::dst
);
1009 unsigned RegIndex
= MI
.getOperand(RegOpIdx
).getImm();
1010 unsigned Channel
= MI
.getOperand(ChanOpIdx
).getImm();
1011 unsigned Address
= calculateIndirectAddress(RegIndex
, Channel
);
1012 Register OffsetReg
= MI
.getOperand(OffsetOpIdx
).getReg();
1013 if (OffsetReg
== R600::INDIRECT_BASE_ADDR
) {
1014 buildMovInstr(MBB
, MI
, MI
.getOperand(DstOpIdx
).getReg(),
1015 getIndirectAddrRegClass()->getRegister(Address
));
1017 buildIndirectRead(MBB
, MI
, MI
.getOperand(DstOpIdx
).getReg(), Address
,
1020 } else if (isRegisterStore(MI
)) {
1022 R600::getNamedOperandIdx(MI
.getOpcode(), R600::OpName::val
);
1023 unsigned RegIndex
= MI
.getOperand(RegOpIdx
).getImm();
1024 unsigned Channel
= MI
.getOperand(ChanOpIdx
).getImm();
1025 unsigned Address
= calculateIndirectAddress(RegIndex
, Channel
);
1026 Register OffsetReg
= MI
.getOperand(OffsetOpIdx
).getReg();
1027 if (OffsetReg
== R600::INDIRECT_BASE_ADDR
) {
1028 buildMovInstr(MBB
, MI
, getIndirectAddrRegClass()->getRegister(Address
),
1029 MI
.getOperand(ValOpIdx
).getReg());
1031 buildIndirectWrite(MBB
, MI
, MI
.getOperand(ValOpIdx
).getReg(),
1032 calculateIndirectAddress(RegIndex
, Channel
),
1042 case R600::R600_EXTRACT_ELT_V2
:
1043 case R600::R600_EXTRACT_ELT_V4
:
1044 buildIndirectRead(MI
.getParent(), MI
, MI
.getOperand(0).getReg(),
1045 RI
.getHWRegIndex(MI
.getOperand(1).getReg()), // Address
1046 MI
.getOperand(2).getReg(),
1047 RI
.getHWRegChan(MI
.getOperand(1).getReg()));
1049 case R600::R600_INSERT_ELT_V2
:
1050 case R600::R600_INSERT_ELT_V4
:
1051 buildIndirectWrite(MI
.getParent(), MI
, MI
.getOperand(2).getReg(), // Value
1052 RI
.getHWRegIndex(MI
.getOperand(1).getReg()), // Address
1053 MI
.getOperand(3).getReg(), // Offset
1054 RI
.getHWRegChan(MI
.getOperand(1).getReg())); // Channel
1057 MI
.eraseFromParent();
1061 void R600InstrInfo::reserveIndirectRegisters(BitVector
&Reserved
,
1062 const MachineFunction
&MF
,
1063 const R600RegisterInfo
&TRI
) const {
1064 const R600Subtarget
&ST
= MF
.getSubtarget
<R600Subtarget
>();
1065 const R600FrameLowering
*TFL
= ST
.getFrameLowering();
1067 unsigned StackWidth
= TFL
->getStackWidth(MF
);
1068 int End
= getIndirectIndexEnd(MF
);
1073 for (int Index
= getIndirectIndexBegin(MF
); Index
<= End
; ++Index
) {
1074 for (unsigned Chan
= 0; Chan
< StackWidth
; ++Chan
) {
1075 unsigned Reg
= R600::R600_TReg32RegClass
.getRegister((4 * Index
) + Chan
);
1076 TRI
.reserveRegisterTuples(Reserved
, Reg
);
1081 const TargetRegisterClass
*R600InstrInfo::getIndirectAddrRegClass() const {
1082 return &R600::R600_TReg32_XRegClass
;
1085 MachineInstrBuilder
R600InstrInfo::buildIndirectWrite(MachineBasicBlock
*MBB
,
1086 MachineBasicBlock::iterator I
,
1087 unsigned ValueReg
, unsigned Address
,
1088 unsigned OffsetReg
) const {
1089 return buildIndirectWrite(MBB
, I
, ValueReg
, Address
, OffsetReg
, 0);
1092 MachineInstrBuilder
R600InstrInfo::buildIndirectWrite(MachineBasicBlock
*MBB
,
1093 MachineBasicBlock::iterator I
,
1094 unsigned ValueReg
, unsigned Address
,
1096 unsigned AddrChan
) const {
1099 default: llvm_unreachable("Invalid Channel");
1100 case 0: AddrReg
= R600::R600_AddrRegClass
.getRegister(Address
); break;
1101 case 1: AddrReg
= R600::R600_Addr_YRegClass
.getRegister(Address
); break;
1102 case 2: AddrReg
= R600::R600_Addr_ZRegClass
.getRegister(Address
); break;
1103 case 3: AddrReg
= R600::R600_Addr_WRegClass
.getRegister(Address
); break;
1105 MachineInstr
*MOVA
= buildDefaultInstruction(*MBB
, I
, R600::MOVA_INT_eg
,
1106 R600::AR_X
, OffsetReg
);
1107 setImmOperand(*MOVA
, R600::OpName::write
, 0);
1109 MachineInstrBuilder Mov
= buildDefaultInstruction(*MBB
, I
, R600::MOV
,
1112 RegState::Implicit
| RegState::Kill
);
1113 setImmOperand(*Mov
, R600::OpName::dst_rel
, 1);
1117 MachineInstrBuilder
R600InstrInfo::buildIndirectRead(MachineBasicBlock
*MBB
,
1118 MachineBasicBlock::iterator I
,
1119 unsigned ValueReg
, unsigned Address
,
1120 unsigned OffsetReg
) const {
1121 return buildIndirectRead(MBB
, I
, ValueReg
, Address
, OffsetReg
, 0);
1124 MachineInstrBuilder
R600InstrInfo::buildIndirectRead(MachineBasicBlock
*MBB
,
1125 MachineBasicBlock::iterator I
,
1126 unsigned ValueReg
, unsigned Address
,
1128 unsigned AddrChan
) const {
1131 default: llvm_unreachable("Invalid Channel");
1132 case 0: AddrReg
= R600::R600_AddrRegClass
.getRegister(Address
); break;
1133 case 1: AddrReg
= R600::R600_Addr_YRegClass
.getRegister(Address
); break;
1134 case 2: AddrReg
= R600::R600_Addr_ZRegClass
.getRegister(Address
); break;
1135 case 3: AddrReg
= R600::R600_Addr_WRegClass
.getRegister(Address
); break;
1137 MachineInstr
*MOVA
= buildDefaultInstruction(*MBB
, I
, R600::MOVA_INT_eg
,
1140 setImmOperand(*MOVA
, R600::OpName::write
, 0);
1141 MachineInstrBuilder Mov
= buildDefaultInstruction(*MBB
, I
, R600::MOV
,
1145 RegState::Implicit
| RegState::Kill
);
1146 setImmOperand(*Mov
, R600::OpName::src0_rel
, 1);
1151 int R600InstrInfo::getIndirectIndexBegin(const MachineFunction
&MF
) const {
1152 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
1153 const MachineFrameInfo
&MFI
= MF
.getFrameInfo();
1156 if (MFI
.getNumObjects() == 0) {
1160 if (MRI
.livein_empty()) {
1164 const TargetRegisterClass
*IndirectRC
= getIndirectAddrRegClass();
1165 for (std::pair
<unsigned, unsigned> LI
: MRI
.liveins()) {
1166 Register Reg
= LI
.first
;
1167 if (Reg
.isVirtual() || !IndirectRC
->contains(Reg
))
1172 for (RegIndex
= 0, RegEnd
= IndirectRC
->getNumRegs(); RegIndex
!= RegEnd
;
1174 if (IndirectRC
->getRegister(RegIndex
) == (unsigned)Reg
)
1177 Offset
= std::max(Offset
, (int)RegIndex
);
1183 int R600InstrInfo::getIndirectIndexEnd(const MachineFunction
&MF
) const {
1185 const MachineFrameInfo
&MFI
= MF
.getFrameInfo();
1187 // Variable sized objects are not supported
1188 if (MFI
.hasVarSizedObjects()) {
1192 if (MFI
.getNumObjects() == 0) {
1196 const R600Subtarget
&ST
= MF
.getSubtarget
<R600Subtarget
>();
1197 const R600FrameLowering
*TFL
= ST
.getFrameLowering();
1199 Register IgnoredFrameReg
;
1200 Offset
= TFL
->getFrameIndexReference(MF
, -1, IgnoredFrameReg
).getFixed();
1202 return getIndirectIndexBegin(MF
) + Offset
;
1205 unsigned R600InstrInfo::getMaxAlusPerClause() const {
1209 MachineInstrBuilder
R600InstrInfo::buildDefaultInstruction(MachineBasicBlock
&MBB
,
1210 MachineBasicBlock::iterator I
,
1214 unsigned Src1Reg
) const {
1215 MachineInstrBuilder MIB
= BuildMI(MBB
, I
, MBB
.findDebugLoc(I
), get(Opcode
),
1219 MIB
.addImm(0) // $update_exec_mask
1220 .addImm(0); // $update_predicate
1222 MIB
.addImm(1) // $write
1224 .addImm(0) // $dst_rel
1225 .addImm(0) // $dst_clamp
1226 .addReg(Src0Reg
) // $src0
1227 .addImm(0) // $src0_neg
1228 .addImm(0) // $src0_rel
1229 .addImm(0) // $src0_abs
1230 .addImm(-1); // $src0_sel
1233 MIB
.addReg(Src1Reg
) // $src1
1234 .addImm(0) // $src1_neg
1235 .addImm(0) // $src1_rel
1236 .addImm(0) // $src1_abs
1237 .addImm(-1); // $src1_sel
1240 //XXX: The r600g finalizer expects this to be 1, once we've moved the
1241 //scheduling to the backend, we can change the default to 0.
1242 MIB
.addImm(1) // $last
1243 .addReg(R600::PRED_SEL_OFF
) // $pred_sel
1244 .addImm(0) // $literal
1245 .addImm(0); // $bank_swizzle
1250 #define OPERAND_CASE(Label) \
1252 static const unsigned Ops[] = \
1262 static unsigned getSlotedOps(unsigned Op
, unsigned Slot
) {
1264 OPERAND_CASE(R600::OpName::update_exec_mask
)
1265 OPERAND_CASE(R600::OpName::update_pred
)
1266 OPERAND_CASE(R600::OpName::write
)
1267 OPERAND_CASE(R600::OpName::omod
)
1268 OPERAND_CASE(R600::OpName::dst_rel
)
1269 OPERAND_CASE(R600::OpName::clamp
)
1270 OPERAND_CASE(R600::OpName::src0
)
1271 OPERAND_CASE(R600::OpName::src0_neg
)
1272 OPERAND_CASE(R600::OpName::src0_rel
)
1273 OPERAND_CASE(R600::OpName::src0_abs
)
1274 OPERAND_CASE(R600::OpName::src0_sel
)
1275 OPERAND_CASE(R600::OpName::src1
)
1276 OPERAND_CASE(R600::OpName::src1_neg
)
1277 OPERAND_CASE(R600::OpName::src1_rel
)
1278 OPERAND_CASE(R600::OpName::src1_abs
)
1279 OPERAND_CASE(R600::OpName::src1_sel
)
1280 OPERAND_CASE(R600::OpName::pred_sel
)
1282 llvm_unreachable("Wrong Operand");
1288 MachineInstr
*R600InstrInfo::buildSlotOfVectorInstruction(
1289 MachineBasicBlock
&MBB
, MachineInstr
*MI
, unsigned Slot
, unsigned DstReg
)
1291 assert (MI
->getOpcode() == R600::DOT_4
&& "Not Implemented");
1293 if (ST
.getGeneration() <= AMDGPUSubtarget::R700
)
1294 Opcode
= R600::DOT4_r600
;
1296 Opcode
= R600::DOT4_eg
;
1297 MachineBasicBlock::iterator I
= MI
;
1298 MachineOperand
&Src0
= MI
->getOperand(
1299 getOperandIdx(MI
->getOpcode(), getSlotedOps(R600::OpName::src0
, Slot
)));
1300 MachineOperand
&Src1
= MI
->getOperand(
1301 getOperandIdx(MI
->getOpcode(), getSlotedOps(R600::OpName::src1
, Slot
)));
1302 MachineInstr
*MIB
= buildDefaultInstruction(
1303 MBB
, I
, Opcode
, DstReg
, Src0
.getReg(), Src1
.getReg());
1304 static const unsigned Operands
[14] = {
1305 R600::OpName::update_exec_mask
,
1306 R600::OpName::update_pred
,
1307 R600::OpName::write
,
1309 R600::OpName::dst_rel
,
1310 R600::OpName::clamp
,
1311 R600::OpName::src0_neg
,
1312 R600::OpName::src0_rel
,
1313 R600::OpName::src0_abs
,
1314 R600::OpName::src0_sel
,
1315 R600::OpName::src1_neg
,
1316 R600::OpName::src1_rel
,
1317 R600::OpName::src1_abs
,
1318 R600::OpName::src1_sel
,
1321 MachineOperand
&MO
= MI
->getOperand(getOperandIdx(MI
->getOpcode(),
1322 getSlotedOps(R600::OpName::pred_sel
, Slot
)));
1323 MIB
->getOperand(getOperandIdx(Opcode
, R600::OpName::pred_sel
))
1324 .setReg(MO
.getReg());
1326 for (unsigned Operand
: Operands
) {
1327 MachineOperand
&MO
= MI
->getOperand(
1328 getOperandIdx(MI
->getOpcode(), getSlotedOps(Operand
, Slot
)));
1329 assert (MO
.isImm());
1330 setImmOperand(*MIB
, Operand
, MO
.getImm());
1332 MIB
->getOperand(20).setImm(0);
1336 MachineInstr
*R600InstrInfo::buildMovImm(MachineBasicBlock
&BB
,
1337 MachineBasicBlock::iterator I
,
1339 uint64_t Imm
) const {
1340 MachineInstr
*MovImm
= buildDefaultInstruction(BB
, I
, R600::MOV
, DstReg
,
1341 R600::ALU_LITERAL_X
);
1342 setImmOperand(*MovImm
, R600::OpName::literal
, Imm
);
1346 MachineInstr
*R600InstrInfo::buildMovInstr(MachineBasicBlock
*MBB
,
1347 MachineBasicBlock::iterator I
,
1348 unsigned DstReg
, unsigned SrcReg
) const {
1349 return buildDefaultInstruction(*MBB
, I
, R600::MOV
, DstReg
, SrcReg
);
1352 int R600InstrInfo::getOperandIdx(const MachineInstr
&MI
, unsigned Op
) const {
1353 return getOperandIdx(MI
.getOpcode(), Op
);
1356 int R600InstrInfo::getOperandIdx(unsigned Opcode
, unsigned Op
) const {
1357 return R600::getNamedOperandIdx(Opcode
, Op
);
1360 void R600InstrInfo::setImmOperand(MachineInstr
&MI
, unsigned Op
,
1361 int64_t Imm
) const {
1362 int Idx
= getOperandIdx(MI
, Op
);
1363 assert(Idx
!= -1 && "Operand not supported for this instruction.");
1364 assert(MI
.getOperand(Idx
).isImm());
1365 MI
.getOperand(Idx
).setImm(Imm
);
1368 //===----------------------------------------------------------------------===//
1369 // Instruction flag getters/setters
1370 //===----------------------------------------------------------------------===//
1372 MachineOperand
&R600InstrInfo::getFlagOp(MachineInstr
&MI
, unsigned SrcIdx
,
1373 unsigned Flag
) const {
1374 unsigned TargetFlags
= get(MI
.getOpcode()).TSFlags
;
1377 // If we pass something other than the default value of Flag to this
1378 // function, it means we are want to set a flag on an instruction
1379 // that uses native encoding.
1380 assert(HAS_NATIVE_OPERANDS(TargetFlags
));
1381 bool IsOP3
= (TargetFlags
& R600_InstFlag::OP3
) == R600_InstFlag::OP3
;
1384 FlagIndex
= getOperandIdx(MI
, R600::OpName::clamp
);
1387 FlagIndex
= getOperandIdx(MI
, R600::OpName::write
);
1389 case MO_FLAG_NOT_LAST
:
1391 FlagIndex
= getOperandIdx(MI
, R600::OpName::last
);
1396 FlagIndex
= getOperandIdx(MI
, R600::OpName::src0_neg
);
1399 FlagIndex
= getOperandIdx(MI
, R600::OpName::src1_neg
);
1402 FlagIndex
= getOperandIdx(MI
, R600::OpName::src2_neg
);
1408 assert(!IsOP3
&& "Cannot set absolute value modifier for OP3 "
1413 FlagIndex
= getOperandIdx(MI
, R600::OpName::src0_abs
);
1416 FlagIndex
= getOperandIdx(MI
, R600::OpName::src1_abs
);
1425 assert(FlagIndex
!= -1 && "Flag not supported for this instruction");
1427 FlagIndex
= GET_FLAG_OPERAND_IDX(TargetFlags
);
1428 assert(FlagIndex
!= 0 &&
1429 "Instruction flags not supported for this instruction");
1432 MachineOperand
&FlagOp
= MI
.getOperand(FlagIndex
);
1433 assert(FlagOp
.isImm());
1437 void R600InstrInfo::addFlag(MachineInstr
&MI
, unsigned Operand
,
1438 unsigned Flag
) const {
1439 unsigned TargetFlags
= get(MI
.getOpcode()).TSFlags
;
1443 if (HAS_NATIVE_OPERANDS(TargetFlags
)) {
1444 MachineOperand
&FlagOp
= getFlagOp(MI
, Operand
, Flag
);
1445 if (Flag
== MO_FLAG_NOT_LAST
) {
1446 clearFlag(MI
, Operand
, MO_FLAG_LAST
);
1447 } else if (Flag
== MO_FLAG_MASK
) {
1448 clearFlag(MI
, Operand
, Flag
);
1453 MachineOperand
&FlagOp
= getFlagOp(MI
, Operand
);
1454 FlagOp
.setImm(FlagOp
.getImm() | (Flag
<< (NUM_MO_FLAGS
* Operand
)));
1458 void R600InstrInfo::clearFlag(MachineInstr
&MI
, unsigned Operand
,
1459 unsigned Flag
) const {
1460 unsigned TargetFlags
= get(MI
.getOpcode()).TSFlags
;
1461 if (HAS_NATIVE_OPERANDS(TargetFlags
)) {
1462 MachineOperand
&FlagOp
= getFlagOp(MI
, Operand
, Flag
);
1465 MachineOperand
&FlagOp
= getFlagOp(MI
);
1466 unsigned InstFlags
= FlagOp
.getImm();
1467 InstFlags
&= ~(Flag
<< (NUM_MO_FLAGS
* Operand
));
1468 FlagOp
.setImm(InstFlags
);