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