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