brintos

brintos / llvm-project-archived public Read only

0
0
Text · 47.9 KiB · 7f805e6 Raw
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