1458 lines · cpp
1//===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9/// \file10/// R600 Implementation of TargetInstrInfo.11//12//===----------------------------------------------------------------------===//13 14#include "R600InstrInfo.h"15#include "MCTargetDesc/R600MCTargetDesc.h"16#include "R600Defines.h"17#include "R600Subtarget.h"18#include "llvm/ADT/SmallSet.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20 21using namespace llvm;22 23#define GET_INSTRINFO_CTOR_DTOR24#include "R600GenDFAPacketizer.inc"25 26#define GET_INSTRINFO_CTOR_DTOR27#define GET_INSTRMAP_INFO28#define GET_INSTRINFO_NAMED_OPS29#include "R600GenInstrInfo.inc"30 31R600InstrInfo::R600InstrInfo(const R600Subtarget &ST)32 : R600GenInstrInfo(ST, RI, -1, -1), RI(), ST(ST) {}33 34bool R600InstrInfo::isVector(const MachineInstr &MI) const {35 return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR;36}37 38void R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB,39 MachineBasicBlock::iterator MI,40 const DebugLoc &DL, Register DestReg,41 Register SrcReg, bool KillSrc,42 bool RenamableDest, bool RenamableSrc) const {43 unsigned VectorComponents = 0;44 if ((R600::R600_Reg128RegClass.contains(DestReg) ||45 R600::R600_Reg128VerticalRegClass.contains(DestReg)) &&46 (R600::R600_Reg128RegClass.contains(SrcReg) ||47 R600::R600_Reg128VerticalRegClass.contains(SrcReg))) {48 VectorComponents = 4;49 } else if((R600::R600_Reg64RegClass.contains(DestReg) ||50 R600::R600_Reg64VerticalRegClass.contains(DestReg)) &&51 (R600::R600_Reg64RegClass.contains(SrcReg) ||52 R600::R600_Reg64VerticalRegClass.contains(SrcReg))) {53 VectorComponents = 2;54 }55 56 if (VectorComponents > 0) {57 for (unsigned I = 0; I < VectorComponents; I++) {58 unsigned SubRegIndex = R600RegisterInfo::getSubRegFromChannel(I);59 buildDefaultInstruction(MBB, MI, R600::MOV,60 RI.getSubReg(DestReg, SubRegIndex),61 RI.getSubReg(SrcReg, SubRegIndex))62 .addReg(DestReg,63 RegState::Define | RegState::Implicit);64 }65 } else {66 MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, R600::MOV,67 DestReg, SrcReg);68 NewMI->getOperand(getOperandIdx(*NewMI, R600::OpName::src0))69 .setIsKill(KillSrc);70 }71}72 73/// \returns true if \p MBBI can be moved into a new basic.74bool R600InstrInfo::isLegalToSplitMBBAt(MachineBasicBlock &MBB,75 MachineBasicBlock::iterator MBBI) const {76 for (const MachineOperand &MO : MBBI->all_uses())77 if (!MO.getReg().isVirtual() && RI.isPhysRegLiveAcrossClauses(MO.getReg()))78 return false;79 return true;80}81 82bool R600InstrInfo::isMov(unsigned Opcode) const {83 switch(Opcode) {84 default:85 return false;86 case R600::MOV:87 case R600::MOV_IMM_F32:88 case R600::MOV_IMM_I32:89 return true;90 }91}92 93bool R600InstrInfo::isReductionOp(unsigned Opcode) const {94 return false;95}96 97bool R600InstrInfo::isCubeOp(unsigned Opcode) const {98 switch(Opcode) {99 default: return false;100 case R600::CUBE_r600_pseudo:101 case R600::CUBE_r600_real:102 case R600::CUBE_eg_pseudo:103 case R600::CUBE_eg_real:104 return true;105 }106}107 108bool R600InstrInfo::isALUInstr(unsigned Opcode) const {109 unsigned TargetFlags = get(Opcode).TSFlags;110 111 return (TargetFlags & R600_InstFlag::ALU_INST);112}113 114bool R600InstrInfo::hasInstrModifiers(unsigned Opcode) const {115 unsigned TargetFlags = get(Opcode).TSFlags;116 117 return ((TargetFlags & R600_InstFlag::OP1) |118 (TargetFlags & R600_InstFlag::OP2) |119 (TargetFlags & R600_InstFlag::OP3));120}121 122bool R600InstrInfo::isLDSInstr(unsigned Opcode) const {123 unsigned TargetFlags = get(Opcode).TSFlags;124 125 return ((TargetFlags & R600_InstFlag::LDS_1A) |126 (TargetFlags & R600_InstFlag::LDS_1A1D) |127 (TargetFlags & R600_InstFlag::LDS_1A2D));128}129 130bool R600InstrInfo::isLDSRetInstr(unsigned Opcode) const {131 return isLDSInstr(Opcode) && getOperandIdx(Opcode, R600::OpName::dst) != -1;132}133 134bool R600InstrInfo::canBeConsideredALU(const MachineInstr &MI) const {135 if (isALUInstr(MI.getOpcode()))136 return true;137 if (isVector(MI) || isCubeOp(MI.getOpcode()))138 return true;139 switch (MI.getOpcode()) {140 case R600::PRED_X:141 case R600::INTERP_PAIR_XY:142 case R600::INTERP_PAIR_ZW:143 case R600::INTERP_VEC_LOAD:144 case R600::COPY:145 case R600::DOT_4:146 return true;147 default:148 return false;149 }150}151 152bool R600InstrInfo::isTransOnly(unsigned Opcode) const {153 if (ST.hasCaymanISA())154 return false;155 return (get(Opcode).getSchedClass() == R600::Sched::TransALU);156}157 158bool R600InstrInfo::isTransOnly(const MachineInstr &MI) const {159 return isTransOnly(MI.getOpcode());160}161 162bool R600InstrInfo::isVectorOnly(unsigned Opcode) const {163 return (get(Opcode).getSchedClass() == R600::Sched::VecALU);164}165 166bool R600InstrInfo::isVectorOnly(const MachineInstr &MI) const {167 return isVectorOnly(MI.getOpcode());168}169 170bool R600InstrInfo::isExport(unsigned Opcode) const {171 return (get(Opcode).TSFlags & R600_InstFlag::IS_EXPORT);172}173 174bool R600InstrInfo::usesVertexCache(unsigned Opcode) const {175 return ST.hasVertexCache() && IS_VTX(get(Opcode));176}177 178bool R600InstrInfo::usesVertexCache(const MachineInstr &MI) const {179 const MachineFunction *MF = MI.getMF();180 return !AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&181 usesVertexCache(MI.getOpcode());182}183 184bool R600InstrInfo::usesTextureCache(unsigned Opcode) const {185 return (!ST.hasVertexCache() && IS_VTX(get(Opcode))) || IS_TEX(get(Opcode));186}187 188bool R600InstrInfo::usesTextureCache(const MachineInstr &MI) const {189 const MachineFunction *MF = MI.getMF();190 return (AMDGPU::isCompute(MF->getFunction().getCallingConv()) &&191 usesVertexCache(MI.getOpcode())) ||192 usesTextureCache(MI.getOpcode());193}194 195bool R600InstrInfo::mustBeLastInClause(unsigned Opcode) const {196 switch (Opcode) {197 case R600::KILLGT:198 case R600::GROUP_BARRIER:199 return true;200 default:201 return false;202 }203}204 205bool R600InstrInfo::usesAddressRegister(MachineInstr &MI) const {206 return MI.findRegisterUseOperandIdx(R600::AR_X, &RI, false) != -1;207}208 209bool R600InstrInfo::definesAddressRegister(MachineInstr &MI) const {210 return MI.findRegisterDefOperandIdx(R600::AR_X, &RI, false, false) != -1;211}212 213bool R600InstrInfo::readsLDSSrcReg(const MachineInstr &MI) const {214 if (!isALUInstr(MI.getOpcode())) {215 return false;216 }217 for (const MachineOperand &MO : MI.all_uses())218 if (MO.getReg().isPhysical() &&219 R600::R600_LDS_SRC_REGRegClass.contains(MO.getReg()))220 return true;221 return false;222}223 224int R600InstrInfo::getSelIdx(unsigned Opcode, unsigned SrcIdx) const {225 static const R600::OpName SrcSelTable[][2] = {226 {R600::OpName::src0, R600::OpName::src0_sel},227 {R600::OpName::src1, R600::OpName::src1_sel},228 {R600::OpName::src2, R600::OpName::src2_sel},229 {R600::OpName::src0_X, R600::OpName::src0_sel_X},230 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},231 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},232 {R600::OpName::src0_W, R600::OpName::src0_sel_W},233 {R600::OpName::src1_X, R600::OpName::src1_sel_X},234 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},235 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},236 {R600::OpName::src1_W, R600::OpName::src1_sel_W}};237 238 for (const auto &Row : SrcSelTable) {239 if (getOperandIdx(Opcode, Row[0]) == (int)SrcIdx) {240 return getOperandIdx(Opcode, Row[1]);241 }242 }243 return -1;244}245 246SmallVector<std::pair<MachineOperand *, int64_t>, 3>247R600InstrInfo::getSrcs(MachineInstr &MI) const {248 SmallVector<std::pair<MachineOperand *, int64_t>, 3> Result;249 250 if (MI.getOpcode() == R600::DOT_4) {251 static const R600::OpName OpTable[8][2] = {252 {R600::OpName::src0_X, R600::OpName::src0_sel_X},253 {R600::OpName::src0_Y, R600::OpName::src0_sel_Y},254 {R600::OpName::src0_Z, R600::OpName::src0_sel_Z},255 {R600::OpName::src0_W, R600::OpName::src0_sel_W},256 {R600::OpName::src1_X, R600::OpName::src1_sel_X},257 {R600::OpName::src1_Y, R600::OpName::src1_sel_Y},258 {R600::OpName::src1_Z, R600::OpName::src1_sel_Z},259 {R600::OpName::src1_W, R600::OpName::src1_sel_W},260 };261 262 for (const auto &Op : OpTable) {263 MachineOperand &MO = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[0]));264 Register Reg = MO.getReg();265 if (Reg == R600::ALU_CONST) {266 MachineOperand &Sel =267 MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));268 Result.push_back(std::pair(&MO, Sel.getImm()));269 continue;270 }271 }272 return Result;273 }274 275 static const R600::OpName OpTable[3][2] = {276 {R600::OpName::src0, R600::OpName::src0_sel},277 {R600::OpName::src1, R600::OpName::src1_sel},278 {R600::OpName::src2, R600::OpName::src2_sel},279 };280 281 for (const auto &Op : OpTable) {282 int SrcIdx = getOperandIdx(MI.getOpcode(), Op[0]);283 if (SrcIdx < 0)284 break;285 MachineOperand &MO = MI.getOperand(SrcIdx);286 Register Reg = MO.getReg();287 if (Reg == R600::ALU_CONST) {288 MachineOperand &Sel = MI.getOperand(getOperandIdx(MI.getOpcode(), Op[1]));289 Result.push_back(std::pair(&MO, Sel.getImm()));290 continue;291 }292 if (Reg == R600::ALU_LITERAL_X) {293 MachineOperand &Operand =294 MI.getOperand(getOperandIdx(MI.getOpcode(), R600::OpName::literal));295 if (Operand.isImm()) {296 Result.push_back(std::pair(&MO, Operand.getImm()));297 continue;298 }299 assert(Operand.isGlobal());300 }301 Result.push_back(std::pair(&MO, 0));302 }303 return Result;304}305 306std::vector<std::pair<int, unsigned>>307R600InstrInfo::ExtractSrcs(MachineInstr &MI,308 const DenseMap<unsigned, unsigned> &PV,309 unsigned &ConstCount) const {310 ConstCount = 0;311 const std::pair<int, unsigned> DummyPair(-1, 0);312 std::vector<std::pair<int, unsigned>> Result;313 unsigned i = 0;314 for (const auto &Src : getSrcs(MI)) {315 ++i;316 Register Reg = Src.first->getReg();317 int Index = RI.getEncodingValue(Reg) & 0xff;318 if (Reg == R600::OQAP) {319 Result.emplace_back(Index, 0U);320 }321 if (PV.contains(Reg)) {322 // 255 is used to tells its a PS/PV reg323 Result.emplace_back(255, 0U);324 continue;325 }326 if (Index > 127) {327 ConstCount++;328 Result.push_back(DummyPair);329 continue;330 }331 unsigned Chan = RI.getHWRegChan(Reg);332 Result.emplace_back(Index, Chan);333 }334 for (; i < 3; ++i)335 Result.push_back(DummyPair);336 return Result;337}338 339static std::vector<std::pair<int, unsigned>>340Swizzle(std::vector<std::pair<int, unsigned>> Src,341 R600InstrInfo::BankSwizzle Swz) {342 if (Src[0] == Src[1])343 Src[1].first = -1;344 switch (Swz) {345 case R600InstrInfo::ALU_VEC_012_SCL_210:346 break;347 case R600InstrInfo::ALU_VEC_021_SCL_122:348 std::swap(Src[1], Src[2]);349 break;350 case R600InstrInfo::ALU_VEC_102_SCL_221:351 std::swap(Src[0], Src[1]);352 break;353 case R600InstrInfo::ALU_VEC_120_SCL_212:354 std::swap(Src[0], Src[1]);355 std::swap(Src[0], Src[2]);356 break;357 case R600InstrInfo::ALU_VEC_201:358 std::swap(Src[0], Src[2]);359 std::swap(Src[0], Src[1]);360 break;361 case R600InstrInfo::ALU_VEC_210:362 std::swap(Src[0], Src[2]);363 break;364 }365 return Src;366}367 368static unsigned getTransSwizzle(R600InstrInfo::BankSwizzle Swz, unsigned Op) {369 assert(Op < 3 && "Out of range swizzle index");370 switch (Swz) {371 case R600InstrInfo::ALU_VEC_012_SCL_210: {372 unsigned Cycles[3] = { 2, 1, 0};373 return Cycles[Op];374 }375 case R600InstrInfo::ALU_VEC_021_SCL_122: {376 unsigned Cycles[3] = { 1, 2, 2};377 return Cycles[Op];378 }379 case R600InstrInfo::ALU_VEC_120_SCL_212: {380 unsigned Cycles[3] = { 2, 1, 2};381 return Cycles[Op];382 }383 case R600InstrInfo::ALU_VEC_102_SCL_221: {384 unsigned Cycles[3] = { 2, 2, 1};385 return Cycles[Op];386 }387 default:388 llvm_unreachable("Wrong Swizzle for Trans Slot");389 }390}391 392/// returns how many MIs (whose inputs are represented by IGSrcs) can be packed393/// in the same Instruction Group while meeting read port limitations given a394/// Swz swizzle sequence.395unsigned R600InstrInfo::isLegalUpTo(396 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,397 const std::vector<R600InstrInfo::BankSwizzle> &Swz,398 const std::vector<std::pair<int, unsigned>> &TransSrcs,399 R600InstrInfo::BankSwizzle TransSwz) const {400 int Vector[4][3];401 memset(Vector, -1, sizeof(Vector));402 for (unsigned i = 0, e = IGSrcs.size(); i < e; i++) {403 const std::vector<std::pair<int, unsigned>> &Srcs =404 Swizzle(IGSrcs[i], Swz[i]);405 for (unsigned j = 0; j < 3; j++) {406 const std::pair<int, unsigned> &Src = Srcs[j];407 if (Src.first < 0 || Src.first == 255)408 continue;409 if (Src.first == GET_REG_INDEX(RI.getEncodingValue(R600::OQAP))) {410 if (Swz[i] != R600InstrInfo::ALU_VEC_012_SCL_210 &&411 Swz[i] != R600InstrInfo::ALU_VEC_021_SCL_122) {412 // The value from output queue A (denoted by register OQAP) can413 // only be fetched during the first cycle.414 return false;415 }416 // OQAP does not count towards the normal read port restrictions417 continue;418 }419 if (Vector[Src.second][j] < 0)420 Vector[Src.second][j] = Src.first;421 if (Vector[Src.second][j] != Src.first)422 return i;423 }424 }425 // Now check Trans Alu426 for (unsigned i = 0, e = TransSrcs.size(); i < e; ++i) {427 const std::pair<int, unsigned> &Src = TransSrcs[i];428 unsigned Cycle = getTransSwizzle(TransSwz, i);429 if (Src.first < 0)430 continue;431 if (Src.first == 255)432 continue;433 if (Vector[Src.second][Cycle] < 0)434 Vector[Src.second][Cycle] = Src.first;435 if (Vector[Src.second][Cycle] != Src.first)436 return IGSrcs.size() - 1;437 }438 return IGSrcs.size();439}440 441/// Given a swizzle sequence SwzCandidate and an index Idx, returns the next442/// (in lexicographic term) swizzle sequence assuming that all swizzles after443/// Idx can be skipped444static bool445NextPossibleSolution(446 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,447 unsigned Idx) {448 assert(Idx < SwzCandidate.size());449 int ResetIdx = Idx;450 while (ResetIdx > -1 && SwzCandidate[ResetIdx] == R600InstrInfo::ALU_VEC_210)451 ResetIdx --;452 for (unsigned i = ResetIdx + 1, e = SwzCandidate.size(); i < e; i++) {453 SwzCandidate[i] = R600InstrInfo::ALU_VEC_012_SCL_210;454 }455 if (ResetIdx == -1)456 return false;457 int NextSwizzle = SwzCandidate[ResetIdx] + 1;458 SwzCandidate[ResetIdx] = (R600InstrInfo::BankSwizzle)NextSwizzle;459 return true;460}461 462/// Enumerate all possible Swizzle sequence to find one that can meet all463/// read port requirements.464bool R600InstrInfo::FindSwizzleForVectorSlot(465 const std::vector<std::vector<std::pair<int, unsigned>>> &IGSrcs,466 std::vector<R600InstrInfo::BankSwizzle> &SwzCandidate,467 const std::vector<std::pair<int, unsigned>> &TransSrcs,468 R600InstrInfo::BankSwizzle TransSwz) const {469 unsigned ValidUpTo = 0;470 do {471 ValidUpTo = isLegalUpTo(IGSrcs, SwzCandidate, TransSrcs, TransSwz);472 if (ValidUpTo == IGSrcs.size())473 return true;474 } while (NextPossibleSolution(SwzCandidate, ValidUpTo));475 return false;476}477 478/// Instructions in Trans slot can't read gpr at cycle 0 if they also read479/// a const, and can't read a gpr at cycle 1 if they read 2 const.480static bool481isConstCompatible(R600InstrInfo::BankSwizzle TransSwz,482 const std::vector<std::pair<int, unsigned>> &TransOps,483 unsigned ConstCount) {484 // TransALU can't read 3 constants485 if (ConstCount > 2)486 return false;487 for (unsigned i = 0, e = TransOps.size(); i < e; ++i) {488 const std::pair<int, unsigned> &Src = TransOps[i];489 unsigned Cycle = getTransSwizzle(TransSwz, i);490 if (Src.first < 0)491 continue;492 if (ConstCount > 0 && Cycle == 0)493 return false;494 if (ConstCount > 1 && Cycle == 1)495 return false;496 }497 return true;498}499 500bool501R600InstrInfo::fitsReadPortLimitations(const std::vector<MachineInstr *> &IG,502 const DenseMap<unsigned, unsigned> &PV,503 std::vector<BankSwizzle> &ValidSwizzle,504 bool isLastAluTrans)505 const {506 //Todo : support shared src0 - src1 operand507 508 std::vector<std::vector<std::pair<int, unsigned>>> IGSrcs;509 ValidSwizzle.clear();510 unsigned ConstCount;511 BankSwizzle TransBS = ALU_VEC_012_SCL_210;512 for (MachineInstr *MI : IG) {513 IGSrcs.push_back(ExtractSrcs(*MI, PV, ConstCount));514 unsigned Op = getOperandIdx(MI->getOpcode(), R600::OpName::bank_swizzle);515 ValidSwizzle.push_back(516 (R600InstrInfo::BankSwizzle)MI->getOperand(Op).getImm());517 }518 std::vector<std::pair<int, unsigned>> TransOps;519 if (!isLastAluTrans)520 return FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps, TransBS);521 522 TransOps = std::move(IGSrcs.back());523 IGSrcs.pop_back();524 ValidSwizzle.pop_back();525 526 static const R600InstrInfo::BankSwizzle TransSwz[] = {527 ALU_VEC_012_SCL_210,528 ALU_VEC_021_SCL_122,529 ALU_VEC_120_SCL_212,530 ALU_VEC_102_SCL_221531 };532 for (R600InstrInfo::BankSwizzle TransBS : TransSwz) {533 if (!isConstCompatible(TransBS, TransOps, ConstCount))534 continue;535 bool Result = FindSwizzleForVectorSlot(IGSrcs, ValidSwizzle, TransOps,536 TransBS);537 if (Result) {538 ValidSwizzle.push_back(TransBS);539 return true;540 }541 }542 543 return false;544}545 546bool547R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts)548 const {549 assert (Consts.size() <= 12 && "Too many operands in instructions group");550 unsigned Pair1 = 0, Pair2 = 0;551 for (unsigned Const : Consts) {552 unsigned ReadConstHalf = Const & 2;553 unsigned ReadConstIndex = Const & (~3);554 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf;555 if (!Pair1) {556 Pair1 = ReadHalfConst;557 continue;558 }559 if (Pair1 == ReadHalfConst)560 continue;561 if (!Pair2) {562 Pair2 = ReadHalfConst;563 continue;564 }565 if (Pair2 != ReadHalfConst)566 return false;567 }568 return true;569}570 571bool572R600InstrInfo::fitsConstReadLimitations(const std::vector<MachineInstr *> &MIs)573 const {574 std::vector<unsigned> Consts;575 SmallSet<int64_t, 4> Literals;576 for (MachineInstr *MI : MIs) {577 if (!isALUInstr(MI->getOpcode()))578 continue;579 580 for (const auto &Src : getSrcs(*MI)) {581 if (Src.first->getReg() == R600::ALU_LITERAL_X)582 Literals.insert(Src.second);583 if (Literals.size() > 4)584 return false;585 if (Src.first->getReg() == R600::ALU_CONST)586 Consts.push_back(Src.second);587 if (R600::R600_KC0RegClass.contains(Src.first->getReg()) ||588 R600::R600_KC1RegClass.contains(Src.first->getReg())) {589 unsigned Index = RI.getEncodingValue(Src.first->getReg()) & 0xff;590 unsigned Chan = RI.getHWRegChan(Src.first->getReg());591 Consts.push_back((Index << 2) | Chan);592 }593 }594 }595 return fitsConstReadLimitations(Consts);596}597 598DFAPacketizer *599R600InstrInfo::CreateTargetScheduleState(const TargetSubtargetInfo &STI) const {600 const InstrItineraryData *II = STI.getInstrItineraryData();601 return static_cast<const R600Subtarget &>(STI).createDFAPacketizer(II);602}603 604static bool605isPredicateSetter(unsigned Opcode) {606 switch (Opcode) {607 case R600::PRED_X:608 return true;609 default:610 return false;611 }612}613 614static MachineInstr *615findFirstPredicateSetterFrom(MachineBasicBlock &MBB,616 MachineBasicBlock::iterator I) {617 while (I != MBB.begin()) {618 --I;619 MachineInstr &MI = *I;620 if (isPredicateSetter(MI.getOpcode()))621 return &MI;622 }623 624 return nullptr;625}626 627static628bool isJump(unsigned Opcode) {629 return Opcode == R600::JUMP || Opcode == R600::JUMP_COND;630}631 632static bool isBranch(unsigned Opcode) {633 return Opcode == R600::BRANCH || Opcode == R600::BRANCH_COND_i32 ||634 Opcode == R600::BRANCH_COND_f32;635}636 637bool R600InstrInfo::analyzeBranch(MachineBasicBlock &MBB,638 MachineBasicBlock *&TBB,639 MachineBasicBlock *&FBB,640 SmallVectorImpl<MachineOperand> &Cond,641 bool AllowModify) const {642 // Most of the following comes from the ARM implementation of analyzeBranch643 644 // If the block has no terminators, it just falls into the block after it.645 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();646 if (I == MBB.end())647 return false;648 649 // R600::BRANCH* instructions are only available after isel and are not650 // handled651 if (isBranch(I->getOpcode()))652 return true;653 if (!isJump(I->getOpcode())) {654 return false;655 }656 657 // Remove successive JUMP658 while (I != MBB.begin() && std::prev(I)->getOpcode() == R600::JUMP) {659 MachineBasicBlock::iterator PriorI = std::prev(I);660 if (AllowModify)661 I->removeFromParent();662 I = PriorI;663 }664 MachineInstr &LastInst = *I;665 666 // If there is only one terminator instruction, process it.667 unsigned LastOpc = LastInst.getOpcode();668 if (I == MBB.begin() || !isJump((--I)->getOpcode())) {669 if (LastOpc == R600::JUMP) {670 TBB = LastInst.getOperand(0).getMBB();671 return false;672 }673 if (LastOpc == R600::JUMP_COND) {674 auto predSet = I;675 while (!isPredicateSetter(predSet->getOpcode())) {676 predSet = --I;677 }678 TBB = LastInst.getOperand(0).getMBB();679 Cond.push_back(predSet->getOperand(1));680 Cond.push_back(predSet->getOperand(2));681 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));682 return false;683 }684 return true; // Can't handle indirect branch.685 }686 687 // Get the instruction before it if it is a terminator.688 MachineInstr &SecondLastInst = *I;689 unsigned SecondLastOpc = SecondLastInst.getOpcode();690 691 // If the block ends with a B and a Bcc, handle it.692 if (SecondLastOpc == R600::JUMP_COND && LastOpc == R600::JUMP) {693 auto predSet = --I;694 while (!isPredicateSetter(predSet->getOpcode())) {695 predSet = --I;696 }697 TBB = SecondLastInst.getOperand(0).getMBB();698 FBB = LastInst.getOperand(0).getMBB();699 Cond.push_back(predSet->getOperand(1));700 Cond.push_back(predSet->getOperand(2));701 Cond.push_back(MachineOperand::CreateReg(R600::PRED_SEL_ONE, false));702 return false;703 }704 705 // Otherwise, can't handle this.706 return true;707}708 709static710MachineBasicBlock::iterator FindLastAluClause(MachineBasicBlock &MBB) {711 for (MachineBasicBlock::reverse_iterator It = MBB.rbegin(), E = MBB.rend();712 It != E; ++It) {713 if (It->getOpcode() == R600::CF_ALU ||714 It->getOpcode() == R600::CF_ALU_PUSH_BEFORE)715 return It.getReverse();716 }717 return MBB.end();718}719 720unsigned R600InstrInfo::insertBranch(MachineBasicBlock &MBB,721 MachineBasicBlock *TBB,722 MachineBasicBlock *FBB,723 ArrayRef<MachineOperand> Cond,724 const DebugLoc &DL,725 int *BytesAdded) const {726 assert(TBB && "insertBranch must not be told to insert a fallthrough");727 assert(!BytesAdded && "code size not handled");728 729 if (!FBB) {730 if (Cond.empty()) {731 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(TBB);732 return 1;733 }734 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());735 assert(PredSet && "No previous predicate !");736 addFlag(*PredSet, 0, MO_FLAG_PUSH);737 PredSet->getOperand(2).setImm(Cond[1].getImm());738 739 BuildMI(&MBB, DL, get(R600::JUMP_COND))740 .addMBB(TBB)741 .addReg(R600::PREDICATE_BIT, RegState::Kill);742 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);743 if (CfAlu == MBB.end())744 return 1;745 assert (CfAlu->getOpcode() == R600::CF_ALU);746 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));747 return 1;748 }749 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end());750 assert(PredSet && "No previous predicate !");751 addFlag(*PredSet, 0, MO_FLAG_PUSH);752 PredSet->getOperand(2).setImm(Cond[1].getImm());753 BuildMI(&MBB, DL, get(R600::JUMP_COND))754 .addMBB(TBB)755 .addReg(R600::PREDICATE_BIT, RegState::Kill);756 BuildMI(&MBB, DL, get(R600::JUMP)).addMBB(FBB);757 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);758 if (CfAlu == MBB.end())759 return 2;760 assert(CfAlu->getOpcode() == R600::CF_ALU);761 CfAlu->setDesc(get(R600::CF_ALU_PUSH_BEFORE));762 return 2;763}764 765unsigned R600InstrInfo::removeBranch(MachineBasicBlock &MBB,766 int *BytesRemoved) const {767 assert(!BytesRemoved && "code size not handled");768 769 // Note : we leave PRED* instructions there.770 // They may be needed when predicating instructions.771 772 MachineBasicBlock::iterator I = MBB.end();773 774 if (I == MBB.begin()) {775 return 0;776 }777 --I;778 switch (I->getOpcode()) {779 default:780 return 0;781 case R600::JUMP_COND: {782 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);783 clearFlag(*predSet, 0, MO_FLAG_PUSH);784 I->eraseFromParent();785 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);786 if (CfAlu == MBB.end())787 break;788 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);789 CfAlu->setDesc(get(R600::CF_ALU));790 break;791 }792 case R600::JUMP:793 I->eraseFromParent();794 break;795 }796 I = MBB.end();797 798 if (I == MBB.begin()) {799 return 1;800 }801 --I;802 switch (I->getOpcode()) {803 // FIXME: only one case??804 default:805 return 1;806 case R600::JUMP_COND: {807 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I);808 clearFlag(*predSet, 0, MO_FLAG_PUSH);809 I->eraseFromParent();810 MachineBasicBlock::iterator CfAlu = FindLastAluClause(MBB);811 if (CfAlu == MBB.end())812 break;813 assert (CfAlu->getOpcode() == R600::CF_ALU_PUSH_BEFORE);814 CfAlu->setDesc(get(R600::CF_ALU));815 break;816 }817 case R600::JUMP:818 I->eraseFromParent();819 break;820 }821 return 2;822}823 824bool R600InstrInfo::isPredicated(const MachineInstr &MI) const {825 int idx = MI.findFirstPredOperandIdx();826 if (idx < 0)827 return false;828 829 Register Reg = MI.getOperand(idx).getReg();830 switch (Reg) {831 default: return false;832 case R600::PRED_SEL_ONE:833 case R600::PRED_SEL_ZERO:834 case R600::PREDICATE_BIT:835 return true;836 }837}838 839bool R600InstrInfo::isPredicable(const MachineInstr &MI) const {840 // XXX: KILL* instructions can be predicated, but they must be the last841 // instruction in a clause, so this means any instructions after them cannot842 // be predicated. Until we have proper support for instruction clauses in the843 // backend, we will mark KILL* instructions as unpredicable.844 845 if (MI.getOpcode() == R600::KILLGT)846 return false;847 if (MI.getOpcode() == R600::CF_ALU) {848 // If the clause start in the middle of MBB then the MBB has more849 // than a single clause, unable to predicate several clauses.850 if (MI.getParent()->begin() != MachineBasicBlock::const_iterator(MI))851 return false;852 // TODO: We don't support KC merging atm853 return MI.getOperand(3).getImm() == 0 && MI.getOperand(4).getImm() == 0;854 }855 if (isVector(MI))856 return false;857 return TargetInstrInfo::isPredicable(MI);858}859 860bool861R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB,862 unsigned NumCycles,863 unsigned ExtraPredCycles,864 BranchProbability Probability) const{865 return true;866}867 868bool869R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB,870 unsigned NumTCycles,871 unsigned ExtraTCycles,872 MachineBasicBlock &FMBB,873 unsigned NumFCycles,874 unsigned ExtraFCycles,875 BranchProbability Probability) const {876 return true;877}878 879bool880R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB,881 unsigned NumCycles,882 BranchProbability Probability)883 const {884 return true;885}886 887bool888R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB,889 MachineBasicBlock &FMBB) const {890 return false;891}892 893bool894R600InstrInfo::reverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const {895 MachineOperand &MO = Cond[1];896 switch (MO.getImm()) {897 case R600::PRED_SETE_INT:898 MO.setImm(R600::PRED_SETNE_INT);899 break;900 case R600::PRED_SETNE_INT:901 MO.setImm(R600::PRED_SETE_INT);902 break;903 case R600::PRED_SETE:904 MO.setImm(R600::PRED_SETNE);905 break;906 case R600::PRED_SETNE:907 MO.setImm(R600::PRED_SETE);908 break;909 default:910 return true;911 }912 913 MachineOperand &MO2 = Cond[2];914 switch (MO2.getReg()) {915 case R600::PRED_SEL_ZERO:916 MO2.setReg(R600::PRED_SEL_ONE);917 break;918 case R600::PRED_SEL_ONE:919 MO2.setReg(R600::PRED_SEL_ZERO);920 break;921 default:922 return true;923 }924 return false;925}926 927bool R600InstrInfo::ClobbersPredicate(MachineInstr &MI,928 std::vector<MachineOperand> &Pred,929 bool SkipDead) const {930 return isPredicateSetter(MI.getOpcode());931}932 933bool R600InstrInfo::PredicateInstruction(MachineInstr &MI,934 ArrayRef<MachineOperand> Pred) const {935 int PIdx = MI.findFirstPredOperandIdx();936 937 if (MI.getOpcode() == R600::CF_ALU) {938 MI.getOperand(8).setImm(0);939 return true;940 }941 942 if (MI.getOpcode() == R600::DOT_4) {943 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_X))944 .setReg(Pred[2].getReg());945 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Y))946 .setReg(Pred[2].getReg());947 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_Z))948 .setReg(Pred[2].getReg());949 MI.getOperand(getOperandIdx(MI, R600::OpName::pred_sel_W))950 .setReg(Pred[2].getReg());951 MachineInstrBuilder MIB(*MI.getMF(), MI);952 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);953 return true;954 }955 956 if (PIdx != -1) {957 MachineOperand &PMO = MI.getOperand(PIdx);958 PMO.setReg(Pred[2].getReg());959 MachineInstrBuilder MIB(*MI.getMF(), MI);960 MIB.addReg(R600::PREDICATE_BIT, RegState::Implicit);961 return true;962 }963 964 return false;965}966 967unsigned int R600InstrInfo::getPredicationCost(const MachineInstr &) const {968 return 2;969}970 971unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData,972 const MachineInstr &,973 unsigned *PredCost) const {974 if (PredCost)975 *PredCost = 2;976 return 2;977}978 979unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex,980 unsigned Channel) const {981 assert(Channel == 0);982 return RegIndex;983}984 985bool R600InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {986 switch (MI.getOpcode()) {987 default: {988 MachineBasicBlock *MBB = MI.getParent();989 int OffsetOpIdx =990 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::addr);991 // addr is a custom operand with multiple MI operands, and only the992 // first MI operand is given a name.993 int RegOpIdx = OffsetOpIdx + 1;994 int ChanOpIdx =995 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::chan);996 if (isRegisterLoad(MI)) {997 int DstOpIdx =998 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::dst);999 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();1000 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();1001 unsigned Address = calculateIndirectAddress(RegIndex, Channel);1002 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();1003 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {1004 buildMovInstr(MBB, MI, MI.getOperand(DstOpIdx).getReg(),1005 getIndirectAddrRegClass()->getRegister(Address));1006 } else {1007 buildIndirectRead(MBB, MI, MI.getOperand(DstOpIdx).getReg(), Address,1008 OffsetReg);1009 }1010 } else if (isRegisterStore(MI)) {1011 int ValOpIdx =1012 R600::getNamedOperandIdx(MI.getOpcode(), R600::OpName::val);1013 unsigned RegIndex = MI.getOperand(RegOpIdx).getImm();1014 unsigned Channel = MI.getOperand(ChanOpIdx).getImm();1015 unsigned Address = calculateIndirectAddress(RegIndex, Channel);1016 Register OffsetReg = MI.getOperand(OffsetOpIdx).getReg();1017 if (OffsetReg == R600::INDIRECT_BASE_ADDR) {1018 buildMovInstr(MBB, MI, getIndirectAddrRegClass()->getRegister(Address),1019 MI.getOperand(ValOpIdx).getReg());1020 } else {1021 buildIndirectWrite(MBB, MI, MI.getOperand(ValOpIdx).getReg(),1022 calculateIndirectAddress(RegIndex, Channel),1023 OffsetReg);1024 }1025 } else {1026 return false;1027 }1028 1029 MBB->erase(MI);1030 return true;1031 }1032 case R600::R600_EXTRACT_ELT_V2:1033 case R600::R600_EXTRACT_ELT_V4:1034 buildIndirectRead(MI.getParent(), MI, MI.getOperand(0).getReg(),1035 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address1036 MI.getOperand(2).getReg(),1037 RI.getHWRegChan(MI.getOperand(1).getReg()));1038 break;1039 case R600::R600_INSERT_ELT_V2:1040 case R600::R600_INSERT_ELT_V4:1041 buildIndirectWrite(MI.getParent(), MI, MI.getOperand(2).getReg(), // Value1042 RI.getHWRegIndex(MI.getOperand(1).getReg()), // Address1043 MI.getOperand(3).getReg(), // Offset1044 RI.getHWRegChan(MI.getOperand(1).getReg())); // Channel1045 break;1046 }1047 MI.eraseFromParent();1048 return true;1049}1050 1051void R600InstrInfo::reserveIndirectRegisters(BitVector &Reserved,1052 const MachineFunction &MF,1053 const R600RegisterInfo &TRI) const {1054 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();1055 const R600FrameLowering *TFL = ST.getFrameLowering();1056 1057 unsigned StackWidth = TFL->getStackWidth(MF);1058 int End = getIndirectIndexEnd(MF);1059 1060 if (End == -1)1061 return;1062 1063 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) {1064 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) {1065 MCRegister Reg =1066 R600::R600_TReg32RegClass.getRegister((4 * Index) + Chan);1067 TRI.reserveRegisterTuples(Reserved, Reg);1068 }1069 }1070}1071 1072const TargetRegisterClass *R600InstrInfo::getIndirectAddrRegClass() const {1073 return &R600::R600_TReg32_XRegClass;1074}1075 1076MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,1077 MachineBasicBlock::iterator I,1078 unsigned ValueReg, unsigned Address,1079 unsigned OffsetReg) const {1080 return buildIndirectWrite(MBB, I, ValueReg, Address, OffsetReg, 0);1081}1082 1083MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB,1084 MachineBasicBlock::iterator I,1085 unsigned ValueReg, unsigned Address,1086 unsigned OffsetReg,1087 unsigned AddrChan) const {1088 MCRegister AddrReg;1089 switch (AddrChan) {1090 default: llvm_unreachable("Invalid Channel");1091 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;1092 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;1093 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;1094 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;1095 }1096 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,1097 R600::AR_X, OffsetReg);1098 setImmOperand(*MOVA, R600::OpName::write, 0);1099 1100 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,1101 AddrReg, ValueReg)1102 .addReg(R600::AR_X,1103 RegState::Implicit | RegState::Kill);1104 setImmOperand(*Mov, R600::OpName::dst_rel, 1);1105 return Mov;1106}1107 1108MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,1109 MachineBasicBlock::iterator I,1110 unsigned ValueReg, unsigned Address,1111 unsigned OffsetReg) const {1112 return buildIndirectRead(MBB, I, ValueReg, Address, OffsetReg, 0);1113}1114 1115MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB,1116 MachineBasicBlock::iterator I,1117 unsigned ValueReg, unsigned Address,1118 unsigned OffsetReg,1119 unsigned AddrChan) const {1120 MCRegister AddrReg;1121 switch (AddrChan) {1122 default: llvm_unreachable("Invalid Channel");1123 case 0: AddrReg = R600::R600_AddrRegClass.getRegister(Address); break;1124 case 1: AddrReg = R600::R600_Addr_YRegClass.getRegister(Address); break;1125 case 2: AddrReg = R600::R600_Addr_ZRegClass.getRegister(Address); break;1126 case 3: AddrReg = R600::R600_Addr_WRegClass.getRegister(Address); break;1127 }1128 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, R600::MOVA_INT_eg,1129 R600::AR_X,1130 OffsetReg);1131 setImmOperand(*MOVA, R600::OpName::write, 0);1132 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, R600::MOV,1133 ValueReg,1134 AddrReg)1135 .addReg(R600::AR_X,1136 RegState::Implicit | RegState::Kill);1137 setImmOperand(*Mov, R600::OpName::src0_rel, 1);1138 1139 return Mov;1140}1141 1142int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const {1143 const MachineRegisterInfo &MRI = MF.getRegInfo();1144 const MachineFrameInfo &MFI = MF.getFrameInfo();1145 int Offset = -1;1146 1147 if (MFI.getNumObjects() == 0) {1148 return -1;1149 }1150 1151 if (MRI.livein_empty()) {1152 return 0;1153 }1154 1155 const TargetRegisterClass *IndirectRC = getIndirectAddrRegClass();1156 for (std::pair<MCRegister, Register> LI : MRI.liveins()) {1157 Register Reg = LI.first;1158 if (Reg.isVirtual() || !IndirectRC->contains(Reg))1159 continue;1160 1161 unsigned RegIndex;1162 unsigned RegEnd;1163 for (RegIndex = 0, RegEnd = IndirectRC->getNumRegs(); RegIndex != RegEnd;1164 ++RegIndex) {1165 if (IndirectRC->getRegister(RegIndex) == (unsigned)Reg)1166 break;1167 }1168 Offset = std::max(Offset, (int)RegIndex);1169 }1170 1171 return Offset + 1;1172}1173 1174int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const {1175 int Offset = 0;1176 const MachineFrameInfo &MFI = MF.getFrameInfo();1177 1178 // Variable sized objects are not supported1179 if (MFI.hasVarSizedObjects()) {1180 return -1;1181 }1182 1183 if (MFI.getNumObjects() == 0) {1184 return -1;1185 }1186 1187 const R600Subtarget &ST = MF.getSubtarget<R600Subtarget>();1188 const R600FrameLowering *TFL = ST.getFrameLowering();1189 1190 Register IgnoredFrameReg;1191 Offset = TFL->getFrameIndexReference(MF, -1, IgnoredFrameReg).getFixed();1192 1193 return getIndirectIndexBegin(MF) + Offset;1194}1195 1196unsigned R600InstrInfo::getMaxAlusPerClause() const {1197 return 115;1198}1199 1200MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB,1201 MachineBasicBlock::iterator I,1202 unsigned Opcode,1203 unsigned DstReg,1204 unsigned Src0Reg,1205 unsigned Src1Reg) const {1206 MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode),1207 DstReg); // $dst1208 1209 if (Src1Reg) {1210 MIB.addImm(0) // $update_exec_mask1211 .addImm(0); // $update_predicate1212 }1213 MIB.addImm(1) // $write1214 .addImm(0) // $omod1215 .addImm(0) // $dst_rel1216 .addImm(0) // $dst_clamp1217 .addReg(Src0Reg) // $src01218 .addImm(0) // $src0_neg1219 .addImm(0) // $src0_rel1220 .addImm(0) // $src0_abs1221 .addImm(-1); // $src0_sel1222 1223 if (Src1Reg) {1224 MIB.addReg(Src1Reg) // $src11225 .addImm(0) // $src1_neg1226 .addImm(0) // $src1_rel1227 .addImm(0) // $src1_abs1228 .addImm(-1); // $src1_sel1229 }1230 1231 //XXX: The r600g finalizer expects this to be 1, once we've moved the1232 //scheduling to the backend, we can change the default to 0.1233 MIB.addImm(1) // $last1234 .addReg(R600::PRED_SEL_OFF) // $pred_sel1235 .addImm(0) // $literal1236 .addImm(0); // $bank_swizzle1237 1238 return MIB;1239}1240 1241#define OPERAND_CASE(Label) \1242 case Label: { \1243 static const R600::OpName Ops[] = {Label##_X, Label##_Y, Label##_Z, \1244 Label##_W}; \1245 return Ops[Slot]; \1246 }1247 1248static R600::OpName getSlotedOps(R600::OpName Op, unsigned Slot) {1249 switch (Op) {1250 OPERAND_CASE(R600::OpName::update_exec_mask)1251 OPERAND_CASE(R600::OpName::update_pred)1252 OPERAND_CASE(R600::OpName::write)1253 OPERAND_CASE(R600::OpName::omod)1254 OPERAND_CASE(R600::OpName::dst_rel)1255 OPERAND_CASE(R600::OpName::clamp)1256 OPERAND_CASE(R600::OpName::src0)1257 OPERAND_CASE(R600::OpName::src0_neg)1258 OPERAND_CASE(R600::OpName::src0_rel)1259 OPERAND_CASE(R600::OpName::src0_abs)1260 OPERAND_CASE(R600::OpName::src0_sel)1261 OPERAND_CASE(R600::OpName::src1)1262 OPERAND_CASE(R600::OpName::src1_neg)1263 OPERAND_CASE(R600::OpName::src1_rel)1264 OPERAND_CASE(R600::OpName::src1_abs)1265 OPERAND_CASE(R600::OpName::src1_sel)1266 OPERAND_CASE(R600::OpName::pred_sel)1267 default:1268 llvm_unreachable("Wrong Operand");1269 }1270}1271 1272#undef OPERAND_CASE1273 1274MachineInstr *R600InstrInfo::buildSlotOfVectorInstruction(1275 MachineBasicBlock &MBB, MachineInstr *MI, unsigned Slot, unsigned DstReg)1276 const {1277 assert (MI->getOpcode() == R600::DOT_4 && "Not Implemented");1278 unsigned Opcode;1279 if (ST.getGeneration() <= AMDGPUSubtarget::R700)1280 Opcode = R600::DOT4_r600;1281 else1282 Opcode = R600::DOT4_eg;1283 MachineBasicBlock::iterator I = MI;1284 MachineOperand &Src0 = MI->getOperand(1285 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src0, Slot)));1286 MachineOperand &Src1 = MI->getOperand(1287 getOperandIdx(MI->getOpcode(), getSlotedOps(R600::OpName::src1, Slot)));1288 MachineInstr *MIB = buildDefaultInstruction(1289 MBB, I, Opcode, DstReg, Src0.getReg(), Src1.getReg());1290 static const R600::OpName Operands[14] = {1291 R600::OpName::update_exec_mask,1292 R600::OpName::update_pred,1293 R600::OpName::write,1294 R600::OpName::omod,1295 R600::OpName::dst_rel,1296 R600::OpName::clamp,1297 R600::OpName::src0_neg,1298 R600::OpName::src0_rel,1299 R600::OpName::src0_abs,1300 R600::OpName::src0_sel,1301 R600::OpName::src1_neg,1302 R600::OpName::src1_rel,1303 R600::OpName::src1_abs,1304 R600::OpName::src1_sel,1305 };1306 1307 MachineOperand &MO = MI->getOperand(getOperandIdx(MI->getOpcode(),1308 getSlotedOps(R600::OpName::pred_sel, Slot)));1309 MIB->getOperand(getOperandIdx(Opcode, R600::OpName::pred_sel))1310 .setReg(MO.getReg());1311 1312 for (R600::OpName Operand : Operands) {1313 MachineOperand &MO = MI->getOperand(1314 getOperandIdx(MI->getOpcode(), getSlotedOps(Operand, Slot)));1315 assert (MO.isImm());1316 setImmOperand(*MIB, Operand, MO.getImm());1317 }1318 MIB->getOperand(20).setImm(0);1319 return MIB;1320}1321 1322MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB,1323 MachineBasicBlock::iterator I,1324 unsigned DstReg,1325 uint64_t Imm) const {1326 MachineInstr *MovImm = buildDefaultInstruction(BB, I, R600::MOV, DstReg,1327 R600::ALU_LITERAL_X);1328 setImmOperand(*MovImm, R600::OpName::literal, Imm);1329 return MovImm;1330}1331 1332MachineInstr *R600InstrInfo::buildMovInstr(MachineBasicBlock *MBB,1333 MachineBasicBlock::iterator I,1334 unsigned DstReg, unsigned SrcReg) const {1335 return buildDefaultInstruction(*MBB, I, R600::MOV, DstReg, SrcReg);1336}1337 1338int R600InstrInfo::getOperandIdx(const MachineInstr &MI,1339 R600::OpName Op) const {1340 return getOperandIdx(MI.getOpcode(), Op);1341}1342 1343int R600InstrInfo::getOperandIdx(unsigned Opcode, R600::OpName Op) const {1344 return R600::getNamedOperandIdx(Opcode, Op);1345}1346 1347void R600InstrInfo::setImmOperand(MachineInstr &MI, R600::OpName Op,1348 int64_t Imm) const {1349 int Idx = getOperandIdx(MI, Op);1350 assert(Idx != -1 && "Operand not supported for this instruction.");1351 assert(MI.getOperand(Idx).isImm());1352 MI.getOperand(Idx).setImm(Imm);1353}1354 1355//===----------------------------------------------------------------------===//1356// Instruction flag getters/setters1357//===----------------------------------------------------------------------===//1358 1359MachineOperand &R600InstrInfo::getFlagOp(MachineInstr &MI, unsigned SrcIdx,1360 unsigned Flag) const {1361 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;1362 int FlagIndex = 0;1363 if (Flag != 0) {1364 // If we pass something other than the default value of Flag to this1365 // function, it means we are want to set a flag on an instruction1366 // that uses native encoding.1367 assert(HAS_NATIVE_OPERANDS(TargetFlags));1368 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3;1369 switch (Flag) {1370 case MO_FLAG_CLAMP:1371 FlagIndex = getOperandIdx(MI, R600::OpName::clamp);1372 break;1373 case MO_FLAG_MASK:1374 FlagIndex = getOperandIdx(MI, R600::OpName::write);1375 break;1376 case MO_FLAG_NOT_LAST:1377 case MO_FLAG_LAST:1378 FlagIndex = getOperandIdx(MI, R600::OpName::last);1379 break;1380 case MO_FLAG_NEG:1381 switch (SrcIdx) {1382 case 0:1383 FlagIndex = getOperandIdx(MI, R600::OpName::src0_neg);1384 break;1385 case 1:1386 FlagIndex = getOperandIdx(MI, R600::OpName::src1_neg);1387 break;1388 case 2:1389 FlagIndex = getOperandIdx(MI, R600::OpName::src2_neg);1390 break;1391 }1392 break;1393 1394 case MO_FLAG_ABS:1395 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 "1396 "instructions.");1397 (void)IsOP3;1398 switch (SrcIdx) {1399 case 0:1400 FlagIndex = getOperandIdx(MI, R600::OpName::src0_abs);1401 break;1402 case 1:1403 FlagIndex = getOperandIdx(MI, R600::OpName::src1_abs);1404 break;1405 }1406 break;1407 1408 default:1409 FlagIndex = -1;1410 break;1411 }1412 assert(FlagIndex != -1 && "Flag not supported for this instruction");1413 } else {1414 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags);1415 assert(FlagIndex != 0 &&1416 "Instruction flags not supported for this instruction");1417 }1418 1419 MachineOperand &FlagOp = MI.getOperand(FlagIndex);1420 assert(FlagOp.isImm());1421 return FlagOp;1422}1423 1424void R600InstrInfo::addFlag(MachineInstr &MI, unsigned SrcIdx,1425 unsigned Flag) const {1426 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;1427 if (Flag == 0) {1428 return;1429 }1430 if (HAS_NATIVE_OPERANDS(TargetFlags)) {1431 MachineOperand &FlagOp = getFlagOp(MI, SrcIdx, Flag);1432 if (Flag == MO_FLAG_NOT_LAST) {1433 clearFlag(MI, SrcIdx, MO_FLAG_LAST);1434 } else if (Flag == MO_FLAG_MASK) {1435 clearFlag(MI, SrcIdx, Flag);1436 } else {1437 FlagOp.setImm(1);1438 }1439 } else {1440 MachineOperand &FlagOp = getFlagOp(MI, SrcIdx);1441 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * SrcIdx)));1442 }1443}1444 1445void R600InstrInfo::clearFlag(MachineInstr &MI, unsigned SrcIdx,1446 unsigned Flag) const {1447 unsigned TargetFlags = get(MI.getOpcode()).TSFlags;1448 if (HAS_NATIVE_OPERANDS(TargetFlags)) {1449 MachineOperand &FlagOp = getFlagOp(MI, SrcIdx, Flag);1450 FlagOp.setImm(0);1451 } else {1452 MachineOperand &FlagOp = getFlagOp(MI);1453 unsigned InstFlags = FlagOp.getImm();1454 InstFlags &= ~(Flag << (NUM_MO_FLAGS * SrcIdx));1455 FlagOp.setImm(InstFlags);1456 }1457}1458