1 //===-- R600InstrInfo.cpp - R600 Instruction Information ------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 /// \file 11 /// \brief R600 Implementation of TargetInstrInfo. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "R600InstrInfo.h" 16 #include "AMDGPUSubtarget.h" 17 #include "AMDGPUTargetMachine.h" 18 #include "R600Defines.h" 19 #include "R600MachineFunctionInfo.h" 20 #include "R600RegisterInfo.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineFrameInfo.h" 23 #include "llvm/CodeGen/MachineRegisterInfo.h" 24 25 #define GET_INSTRINFO_CTOR 26 #include "AMDGPUGenDFAPacketizer.inc" 27 28 using namespace llvm; 29 30 R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm) 31 : AMDGPUInstrInfo(tm), 32 RI(tm, *this) 33 { } 34 35 const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const { 36 return RI; 37 } 38 39 bool R600InstrInfo::isTrig(const MachineInstr &MI) const { 40 return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG; 41 } 42 43 bool R600InstrInfo::isVector(const MachineInstr &MI) const { 44 return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR; 45 } 46 47 void 48 R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB, 49 MachineBasicBlock::iterator MI, DebugLoc DL, 50 unsigned DestReg, unsigned SrcReg, 51 bool KillSrc) const { 52 if (AMDGPU::R600_Reg128RegClass.contains(DestReg) 53 && AMDGPU::R600_Reg128RegClass.contains(SrcReg)) { 54 for (unsigned I = 0; I < 4; I++) { 55 unsigned SubRegIndex = RI.getSubRegFromChannel(I); 56 buildDefaultInstruction(MBB, MI, AMDGPU::MOV, 57 RI.getSubReg(DestReg, SubRegIndex), 58 RI.getSubReg(SrcReg, SubRegIndex)) 59 .addReg(DestReg, 60 RegState::Define | RegState::Implicit); 61 } 62 } else { 63 64 // We can't copy vec4 registers 65 assert(!AMDGPU::R600_Reg128RegClass.contains(DestReg) 66 && !AMDGPU::R600_Reg128RegClass.contains(SrcReg)); 67 68 MachineInstr *NewMI = buildDefaultInstruction(MBB, MI, AMDGPU::MOV, 69 DestReg, SrcReg); 70 NewMI->getOperand(getOperandIdx(*NewMI, R600Operands::SRC0)) 71 .setIsKill(KillSrc); 72 } 73 } 74 75 MachineInstr * R600InstrInfo::getMovImmInstr(MachineFunction *MF, 76 unsigned DstReg, int64_t Imm) const { 77 MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::MOV), DebugLoc()); 78 MachineInstrBuilder MIB(*MF, MI); 79 MIB.addReg(DstReg, RegState::Define); 80 MIB.addReg(AMDGPU::ALU_LITERAL_X); 81 MIB.addImm(Imm); 82 MIB.addReg(0); // PREDICATE_BIT 83 84 return MI; 85 } 86 87 unsigned R600InstrInfo::getIEQOpcode() const { 88 return AMDGPU::SETE_INT; 89 } 90 91 bool R600InstrInfo::isMov(unsigned Opcode) const { 92 93 94 switch(Opcode) { 95 default: return false; 96 case AMDGPU::MOV: 97 case AMDGPU::MOV_IMM_F32: 98 case AMDGPU::MOV_IMM_I32: 99 return true; 100 } 101 } 102 103 // Some instructions act as place holders to emulate operations that the GPU 104 // hardware does automatically. This function can be used to check if 105 // an opcode falls into this category. 106 bool R600InstrInfo::isPlaceHolderOpcode(unsigned Opcode) const { 107 switch (Opcode) { 108 default: return false; 109 case AMDGPU::RETURN: 110 return true; 111 } 112 } 113 114 bool R600InstrInfo::isReductionOp(unsigned Opcode) const { 115 switch(Opcode) { 116 default: return false; 117 case AMDGPU::DOT4_r600_pseudo: 118 case AMDGPU::DOT4_eg_pseudo: 119 return true; 120 } 121 } 122 123 bool R600InstrInfo::isCubeOp(unsigned Opcode) const { 124 switch(Opcode) { 125 default: return false; 126 case AMDGPU::CUBE_r600_pseudo: 127 case AMDGPU::CUBE_r600_real: 128 case AMDGPU::CUBE_eg_pseudo: 129 case AMDGPU::CUBE_eg_real: 130 return true; 131 } 132 } 133 134 bool R600InstrInfo::isALUInstr(unsigned Opcode) const { 135 unsigned TargetFlags = get(Opcode).TSFlags; 136 137 return ((TargetFlags & R600_InstFlag::OP1) | 138 (TargetFlags & R600_InstFlag::OP2) | 139 (TargetFlags & R600_InstFlag::OP3)); 140 } 141 142 bool 143 R600InstrInfo::fitsConstReadLimitations(const std::vector<unsigned> &Consts) 144 const { 145 assert (Consts.size() <= 12 && "Too many operands in instructions group"); 146 unsigned Pair1 = 0, Pair2 = 0; 147 for (unsigned i = 0, n = Consts.size(); i < n; ++i) { 148 unsigned ReadConstHalf = Consts[i] & 2; 149 unsigned ReadConstIndex = Consts[i] & (~3); 150 unsigned ReadHalfConst = ReadConstIndex | ReadConstHalf; 151 if (!Pair1) { 152 Pair1 = ReadHalfConst; 153 continue; 154 } 155 if (Pair1 == ReadHalfConst) 156 continue; 157 if (!Pair2) { 158 Pair2 = ReadHalfConst; 159 continue; 160 } 161 if (Pair2 != ReadHalfConst) 162 return false; 163 } 164 return true; 165 } 166 167 bool 168 R600InstrInfo::canBundle(const std::vector<MachineInstr *> &MIs) const { 169 std::vector<unsigned> Consts; 170 for (unsigned i = 0, n = MIs.size(); i < n; i++) { 171 const MachineInstr *MI = MIs[i]; 172 173 const R600Operands::Ops OpTable[3][2] = { 174 {R600Operands::SRC0, R600Operands::SRC0_SEL}, 175 {R600Operands::SRC1, R600Operands::SRC1_SEL}, 176 {R600Operands::SRC2, R600Operands::SRC2_SEL}, 177 }; 178 179 if (!isALUInstr(MI->getOpcode())) 180 continue; 181 182 for (unsigned j = 0; j < 3; j++) { 183 int SrcIdx = getOperandIdx(MI->getOpcode(), OpTable[j][0]); 184 if (SrcIdx < 0) 185 break; 186 if (MI->getOperand(SrcIdx).getReg() == AMDGPU::ALU_CONST) { 187 unsigned Const = MI->getOperand( 188 getOperandIdx(MI->getOpcode(), OpTable[j][1])).getImm(); 189 Consts.push_back(Const); 190 } 191 } 192 } 193 return fitsConstReadLimitations(Consts); 194 } 195 196 DFAPacketizer *R600InstrInfo::CreateTargetScheduleState(const TargetMachine *TM, 197 const ScheduleDAG *DAG) const { 198 const InstrItineraryData *II = TM->getInstrItineraryData(); 199 return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II); 200 } 201 202 static bool 203 isPredicateSetter(unsigned Opcode) { 204 switch (Opcode) { 205 case AMDGPU::PRED_X: 206 return true; 207 default: 208 return false; 209 } 210 } 211 212 static MachineInstr * 213 findFirstPredicateSetterFrom(MachineBasicBlock &MBB, 214 MachineBasicBlock::iterator I) { 215 while (I != MBB.begin()) { 216 --I; 217 MachineInstr *MI = I; 218 if (isPredicateSetter(MI->getOpcode())) 219 return MI; 220 } 221 222 return NULL; 223 } 224 225 static 226 bool isJump(unsigned Opcode) { 227 return Opcode == AMDGPU::JUMP || Opcode == AMDGPU::JUMP_COND; 228 } 229 230 bool 231 R600InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 232 MachineBasicBlock *&TBB, 233 MachineBasicBlock *&FBB, 234 SmallVectorImpl<MachineOperand> &Cond, 235 bool AllowModify) const { 236 // Most of the following comes from the ARM implementation of AnalyzeBranch 237 238 // If the block has no terminators, it just falls into the block after it. 239 MachineBasicBlock::iterator I = MBB.end(); 240 if (I == MBB.begin()) 241 return false; 242 --I; 243 while (I->isDebugValue()) { 244 if (I == MBB.begin()) 245 return false; 246 --I; 247 } 248 if (!isJump(static_cast<MachineInstr *>(I)->getOpcode())) { 249 return false; 250 } 251 252 // Get the last instruction in the block. 253 MachineInstr *LastInst = I; 254 255 // If there is only one terminator instruction, process it. 256 unsigned LastOpc = LastInst->getOpcode(); 257 if (I == MBB.begin() || 258 !isJump(static_cast<MachineInstr *>(--I)->getOpcode())) { 259 if (LastOpc == AMDGPU::JUMP) { 260 TBB = LastInst->getOperand(0).getMBB(); 261 return false; 262 } else if (LastOpc == AMDGPU::JUMP_COND) { 263 MachineInstr *predSet = I; 264 while (!isPredicateSetter(predSet->getOpcode())) { 265 predSet = --I; 266 } 267 TBB = LastInst->getOperand(0).getMBB(); 268 Cond.push_back(predSet->getOperand(1)); 269 Cond.push_back(predSet->getOperand(2)); 270 Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false)); 271 return false; 272 } 273 return true; // Can't handle indirect branch. 274 } 275 276 // Get the instruction before it if it is a terminator. 277 MachineInstr *SecondLastInst = I; 278 unsigned SecondLastOpc = SecondLastInst->getOpcode(); 279 280 // If the block ends with a B and a Bcc, handle it. 281 if (SecondLastOpc == AMDGPU::JUMP_COND && LastOpc == AMDGPU::JUMP) { 282 MachineInstr *predSet = --I; 283 while (!isPredicateSetter(predSet->getOpcode())) { 284 predSet = --I; 285 } 286 TBB = SecondLastInst->getOperand(0).getMBB(); 287 FBB = LastInst->getOperand(0).getMBB(); 288 Cond.push_back(predSet->getOperand(1)); 289 Cond.push_back(predSet->getOperand(2)); 290 Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false)); 291 return false; 292 } 293 294 // Otherwise, can't handle this. 295 return true; 296 } 297 298 int R600InstrInfo::getBranchInstr(const MachineOperand &op) const { 299 const MachineInstr *MI = op.getParent(); 300 301 switch (MI->getDesc().OpInfo->RegClass) { 302 default: // FIXME: fallthrough?? 303 case AMDGPU::GPRI32RegClassID: return AMDGPU::BRANCH_COND_i32; 304 case AMDGPU::GPRF32RegClassID: return AMDGPU::BRANCH_COND_f32; 305 }; 306 } 307 308 unsigned 309 R600InstrInfo::InsertBranch(MachineBasicBlock &MBB, 310 MachineBasicBlock *TBB, 311 MachineBasicBlock *FBB, 312 const SmallVectorImpl<MachineOperand> &Cond, 313 DebugLoc DL) const { 314 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 315 316 if (FBB == 0) { 317 if (Cond.empty()) { 318 BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(TBB); 319 return 1; 320 } else { 321 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end()); 322 assert(PredSet && "No previous predicate !"); 323 addFlag(PredSet, 0, MO_FLAG_PUSH); 324 PredSet->getOperand(2).setImm(Cond[1].getImm()); 325 326 BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND)) 327 .addMBB(TBB) 328 .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill); 329 return 1; 330 } 331 } else { 332 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end()); 333 assert(PredSet && "No previous predicate !"); 334 addFlag(PredSet, 0, MO_FLAG_PUSH); 335 PredSet->getOperand(2).setImm(Cond[1].getImm()); 336 BuildMI(&MBB, DL, get(AMDGPU::JUMP_COND)) 337 .addMBB(TBB) 338 .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill); 339 BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(FBB); 340 return 2; 341 } 342 } 343 344 unsigned 345 R600InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 346 347 // Note : we leave PRED* instructions there. 348 // They may be needed when predicating instructions. 349 350 MachineBasicBlock::iterator I = MBB.end(); 351 352 if (I == MBB.begin()) { 353 return 0; 354 } 355 --I; 356 switch (I->getOpcode()) { 357 default: 358 return 0; 359 case AMDGPU::JUMP_COND: { 360 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I); 361 clearFlag(predSet, 0, MO_FLAG_PUSH); 362 I->eraseFromParent(); 363 break; 364 } 365 case AMDGPU::JUMP: 366 I->eraseFromParent(); 367 break; 368 } 369 I = MBB.end(); 370 371 if (I == MBB.begin()) { 372 return 1; 373 } 374 --I; 375 switch (I->getOpcode()) { 376 // FIXME: only one case?? 377 default: 378 return 1; 379 case AMDGPU::JUMP_COND: { 380 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I); 381 clearFlag(predSet, 0, MO_FLAG_PUSH); 382 I->eraseFromParent(); 383 break; 384 } 385 case AMDGPU::JUMP: 386 I->eraseFromParent(); 387 break; 388 } 389 return 2; 390 } 391 392 bool 393 R600InstrInfo::isPredicated(const MachineInstr *MI) const { 394 int idx = MI->findFirstPredOperandIdx(); 395 if (idx < 0) 396 return false; 397 398 unsigned Reg = MI->getOperand(idx).getReg(); 399 switch (Reg) { 400 default: return false; 401 case AMDGPU::PRED_SEL_ONE: 402 case AMDGPU::PRED_SEL_ZERO: 403 case AMDGPU::PREDICATE_BIT: 404 return true; 405 } 406 } 407 408 bool 409 R600InstrInfo::isPredicable(MachineInstr *MI) const { 410 // XXX: KILL* instructions can be predicated, but they must be the last 411 // instruction in a clause, so this means any instructions after them cannot 412 // be predicated. Until we have proper support for instruction clauses in the 413 // backend, we will mark KILL* instructions as unpredicable. 414 415 if (MI->getOpcode() == AMDGPU::KILLGT) { 416 return false; 417 } else if (isVector(*MI)) { 418 return false; 419 } else { 420 return AMDGPUInstrInfo::isPredicable(MI); 421 } 422 } 423 424 425 bool 426 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, 427 unsigned NumCyles, 428 unsigned ExtraPredCycles, 429 const BranchProbability &Probability) const{ 430 return true; 431 } 432 433 bool 434 R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB, 435 unsigned NumTCycles, 436 unsigned ExtraTCycles, 437 MachineBasicBlock &FMBB, 438 unsigned NumFCycles, 439 unsigned ExtraFCycles, 440 const BranchProbability &Probability) const { 441 return true; 442 } 443 444 bool 445 R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB, 446 unsigned NumCyles, 447 const BranchProbability &Probability) 448 const { 449 return true; 450 } 451 452 bool 453 R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB, 454 MachineBasicBlock &FMBB) const { 455 return false; 456 } 457 458 459 bool 460 R600InstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const { 461 MachineOperand &MO = Cond[1]; 462 switch (MO.getImm()) { 463 case OPCODE_IS_ZERO_INT: 464 MO.setImm(OPCODE_IS_NOT_ZERO_INT); 465 break; 466 case OPCODE_IS_NOT_ZERO_INT: 467 MO.setImm(OPCODE_IS_ZERO_INT); 468 break; 469 case OPCODE_IS_ZERO: 470 MO.setImm(OPCODE_IS_NOT_ZERO); 471 break; 472 case OPCODE_IS_NOT_ZERO: 473 MO.setImm(OPCODE_IS_ZERO); 474 break; 475 default: 476 return true; 477 } 478 479 MachineOperand &MO2 = Cond[2]; 480 switch (MO2.getReg()) { 481 case AMDGPU::PRED_SEL_ZERO: 482 MO2.setReg(AMDGPU::PRED_SEL_ONE); 483 break; 484 case AMDGPU::PRED_SEL_ONE: 485 MO2.setReg(AMDGPU::PRED_SEL_ZERO); 486 break; 487 default: 488 return true; 489 } 490 return false; 491 } 492 493 bool 494 R600InstrInfo::DefinesPredicate(MachineInstr *MI, 495 std::vector<MachineOperand> &Pred) const { 496 return isPredicateSetter(MI->getOpcode()); 497 } 498 499 500 bool 501 R600InstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 502 const SmallVectorImpl<MachineOperand> &Pred2) const { 503 return false; 504 } 505 506 507 bool 508 R600InstrInfo::PredicateInstruction(MachineInstr *MI, 509 const SmallVectorImpl<MachineOperand> &Pred) const { 510 int PIdx = MI->findFirstPredOperandIdx(); 511 512 if (PIdx != -1) { 513 MachineOperand &PMO = MI->getOperand(PIdx); 514 PMO.setReg(Pred[2].getReg()); 515 MachineInstrBuilder MIB(*MI->getParent()->getParent(), MI); 516 MIB.addReg(AMDGPU::PREDICATE_BIT, RegState::Implicit); 517 return true; 518 } 519 520 return false; 521 } 522 523 unsigned int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData, 524 const MachineInstr *MI, 525 unsigned *PredCost) const { 526 if (PredCost) 527 *PredCost = 2; 528 return 2; 529 } 530 531 int R600InstrInfo::getIndirectIndexBegin(const MachineFunction &MF) const { 532 const MachineRegisterInfo &MRI = MF.getRegInfo(); 533 const MachineFrameInfo *MFI = MF.getFrameInfo(); 534 int Offset = 0; 535 536 if (MFI->getNumObjects() == 0) { 537 return -1; 538 } 539 540 if (MRI.livein_empty()) { 541 return 0; 542 } 543 544 for (MachineRegisterInfo::livein_iterator LI = MRI.livein_begin(), 545 LE = MRI.livein_end(); 546 LI != LE; ++LI) { 547 Offset = std::max(Offset, 548 GET_REG_INDEX(RI.getEncodingValue(LI->first))); 549 } 550 551 return Offset + 1; 552 } 553 554 int R600InstrInfo::getIndirectIndexEnd(const MachineFunction &MF) const { 555 int Offset = 0; 556 const MachineFrameInfo *MFI = MF.getFrameInfo(); 557 558 // Variable sized objects are not supported 559 assert(!MFI->hasVarSizedObjects()); 560 561 if (MFI->getNumObjects() == 0) { 562 return -1; 563 } 564 565 Offset = TM.getFrameLowering()->getFrameIndexOffset(MF, -1); 566 567 return getIndirectIndexBegin(MF) + Offset; 568 } 569 570 std::vector<unsigned> R600InstrInfo::getIndirectReservedRegs( 571 const MachineFunction &MF) const { 572 const AMDGPUFrameLowering *TFL = 573 static_cast<const AMDGPUFrameLowering*>(TM.getFrameLowering()); 574 std::vector<unsigned> Regs; 575 576 unsigned StackWidth = TFL->getStackWidth(MF); 577 int End = getIndirectIndexEnd(MF); 578 579 if (End == -1) { 580 return Regs; 581 } 582 583 for (int Index = getIndirectIndexBegin(MF); Index <= End; ++Index) { 584 unsigned SuperReg = AMDGPU::R600_Reg128RegClass.getRegister(Index); 585 Regs.push_back(SuperReg); 586 for (unsigned Chan = 0; Chan < StackWidth; ++Chan) { 587 unsigned Reg = AMDGPU::R600_TReg32RegClass.getRegister((4 * Index) + Chan); 588 Regs.push_back(Reg); 589 } 590 } 591 return Regs; 592 } 593 594 unsigned R600InstrInfo::calculateIndirectAddress(unsigned RegIndex, 595 unsigned Channel) const { 596 // XXX: Remove when we support a stack width > 2 597 assert(Channel == 0); 598 return RegIndex; 599 } 600 601 const TargetRegisterClass * R600InstrInfo::getIndirectAddrStoreRegClass( 602 unsigned SourceReg) const { 603 return &AMDGPU::R600_TReg32RegClass; 604 } 605 606 const TargetRegisterClass *R600InstrInfo::getIndirectAddrLoadRegClass() const { 607 return &AMDGPU::TRegMemRegClass; 608 } 609 610 MachineInstrBuilder R600InstrInfo::buildIndirectWrite(MachineBasicBlock *MBB, 611 MachineBasicBlock::iterator I, 612 unsigned ValueReg, unsigned Address, 613 unsigned OffsetReg) const { 614 unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address); 615 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg, 616 AMDGPU::AR_X, OffsetReg); 617 setImmOperand(MOVA, R600Operands::WRITE, 0); 618 619 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV, 620 AddrReg, ValueReg) 621 .addReg(AMDGPU::AR_X, RegState::Implicit); 622 setImmOperand(Mov, R600Operands::DST_REL, 1); 623 return Mov; 624 } 625 626 MachineInstrBuilder R600InstrInfo::buildIndirectRead(MachineBasicBlock *MBB, 627 MachineBasicBlock::iterator I, 628 unsigned ValueReg, unsigned Address, 629 unsigned OffsetReg) const { 630 unsigned AddrReg = AMDGPU::R600_AddrRegClass.getRegister(Address); 631 MachineInstr *MOVA = buildDefaultInstruction(*MBB, I, AMDGPU::MOVA_INT_eg, 632 AMDGPU::AR_X, 633 OffsetReg); 634 setImmOperand(MOVA, R600Operands::WRITE, 0); 635 MachineInstrBuilder Mov = buildDefaultInstruction(*MBB, I, AMDGPU::MOV, 636 ValueReg, 637 AddrReg) 638 .addReg(AMDGPU::AR_X, RegState::Implicit); 639 setImmOperand(Mov, R600Operands::SRC0_REL, 1); 640 641 return Mov; 642 } 643 644 const TargetRegisterClass *R600InstrInfo::getSuperIndirectRegClass() const { 645 return &AMDGPU::IndirectRegRegClass; 646 } 647 648 649 MachineInstrBuilder R600InstrInfo::buildDefaultInstruction(MachineBasicBlock &MBB, 650 MachineBasicBlock::iterator I, 651 unsigned Opcode, 652 unsigned DstReg, 653 unsigned Src0Reg, 654 unsigned Src1Reg) const { 655 MachineInstrBuilder MIB = BuildMI(MBB, I, MBB.findDebugLoc(I), get(Opcode), 656 DstReg); // $dst 657 658 if (Src1Reg) { 659 MIB.addImm(0) // $update_exec_mask 660 .addImm(0); // $update_predicate 661 } 662 MIB.addImm(1) // $write 663 .addImm(0) // $omod 664 .addImm(0) // $dst_rel 665 .addImm(0) // $dst_clamp 666 .addReg(Src0Reg) // $src0 667 .addImm(0) // $src0_neg 668 .addImm(0) // $src0_rel 669 .addImm(0) // $src0_abs 670 .addImm(-1); // $src0_sel 671 672 if (Src1Reg) { 673 MIB.addReg(Src1Reg) // $src1 674 .addImm(0) // $src1_neg 675 .addImm(0) // $src1_rel 676 .addImm(0) // $src1_abs 677 .addImm(-1); // $src1_sel 678 } 679 680 //XXX: The r600g finalizer expects this to be 1, once we've moved the 681 //scheduling to the backend, we can change the default to 0. 682 MIB.addImm(1) // $last 683 .addReg(AMDGPU::PRED_SEL_OFF) // $pred_sel 684 .addImm(0); // $literal 685 686 return MIB; 687 } 688 689 MachineInstr *R600InstrInfo::buildMovImm(MachineBasicBlock &BB, 690 MachineBasicBlock::iterator I, 691 unsigned DstReg, 692 uint64_t Imm) const { 693 MachineInstr *MovImm = buildDefaultInstruction(BB, I, AMDGPU::MOV, DstReg, 694 AMDGPU::ALU_LITERAL_X); 695 setImmOperand(MovImm, R600Operands::IMM, Imm); 696 return MovImm; 697 } 698 699 int R600InstrInfo::getOperandIdx(const MachineInstr &MI, 700 R600Operands::Ops Op) const { 701 return getOperandIdx(MI.getOpcode(), Op); 702 } 703 704 int R600InstrInfo::getOperandIdx(unsigned Opcode, 705 R600Operands::Ops Op) const { 706 unsigned TargetFlags = get(Opcode).TSFlags; 707 unsigned OpTableIdx; 708 709 if (!HAS_NATIVE_OPERANDS(TargetFlags)) { 710 switch (Op) { 711 case R600Operands::DST: return 0; 712 case R600Operands::SRC0: return 1; 713 case R600Operands::SRC1: return 2; 714 case R600Operands::SRC2: return 3; 715 default: 716 assert(!"Unknown operand type for instruction"); 717 return -1; 718 } 719 } 720 721 if (TargetFlags & R600_InstFlag::OP1) { 722 OpTableIdx = 0; 723 } else if (TargetFlags & R600_InstFlag::OP2) { 724 OpTableIdx = 1; 725 } else { 726 assert((TargetFlags & R600_InstFlag::OP3) && "OP1, OP2, or OP3 not defined " 727 "for this instruction"); 728 OpTableIdx = 2; 729 } 730 731 return R600Operands::ALUOpTable[OpTableIdx][Op]; 732 } 733 734 void R600InstrInfo::setImmOperand(MachineInstr *MI, R600Operands::Ops Op, 735 int64_t Imm) const { 736 int Idx = getOperandIdx(*MI, Op); 737 assert(Idx != -1 && "Operand not supported for this instruction."); 738 assert(MI->getOperand(Idx).isImm()); 739 MI->getOperand(Idx).setImm(Imm); 740 } 741 742 //===----------------------------------------------------------------------===// 743 // Instruction flag getters/setters 744 //===----------------------------------------------------------------------===// 745 746 bool R600InstrInfo::hasFlagOperand(const MachineInstr &MI) const { 747 return GET_FLAG_OPERAND_IDX(get(MI.getOpcode()).TSFlags) != 0; 748 } 749 750 MachineOperand &R600InstrInfo::getFlagOp(MachineInstr *MI, unsigned SrcIdx, 751 unsigned Flag) const { 752 unsigned TargetFlags = get(MI->getOpcode()).TSFlags; 753 int FlagIndex = 0; 754 if (Flag != 0) { 755 // If we pass something other than the default value of Flag to this 756 // function, it means we are want to set a flag on an instruction 757 // that uses native encoding. 758 assert(HAS_NATIVE_OPERANDS(TargetFlags)); 759 bool IsOP3 = (TargetFlags & R600_InstFlag::OP3) == R600_InstFlag::OP3; 760 switch (Flag) { 761 case MO_FLAG_CLAMP: 762 FlagIndex = getOperandIdx(*MI, R600Operands::CLAMP); 763 break; 764 case MO_FLAG_MASK: 765 FlagIndex = getOperandIdx(*MI, R600Operands::WRITE); 766 break; 767 case MO_FLAG_NOT_LAST: 768 case MO_FLAG_LAST: 769 FlagIndex = getOperandIdx(*MI, R600Operands::LAST); 770 break; 771 case MO_FLAG_NEG: 772 switch (SrcIdx) { 773 case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_NEG); break; 774 case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_NEG); break; 775 case 2: FlagIndex = getOperandIdx(*MI, R600Operands::SRC2_NEG); break; 776 } 777 break; 778 779 case MO_FLAG_ABS: 780 assert(!IsOP3 && "Cannot set absolute value modifier for OP3 " 781 "instructions."); 782 (void)IsOP3; 783 switch (SrcIdx) { 784 case 0: FlagIndex = getOperandIdx(*MI, R600Operands::SRC0_ABS); break; 785 case 1: FlagIndex = getOperandIdx(*MI, R600Operands::SRC1_ABS); break; 786 } 787 break; 788 789 default: 790 FlagIndex = -1; 791 break; 792 } 793 assert(FlagIndex != -1 && "Flag not supported for this instruction"); 794 } else { 795 FlagIndex = GET_FLAG_OPERAND_IDX(TargetFlags); 796 assert(FlagIndex != 0 && 797 "Instruction flags not supported for this instruction"); 798 } 799 800 MachineOperand &FlagOp = MI->getOperand(FlagIndex); 801 assert(FlagOp.isImm()); 802 return FlagOp; 803 } 804 805 void R600InstrInfo::addFlag(MachineInstr *MI, unsigned Operand, 806 unsigned Flag) const { 807 unsigned TargetFlags = get(MI->getOpcode()).TSFlags; 808 if (Flag == 0) { 809 return; 810 } 811 if (HAS_NATIVE_OPERANDS(TargetFlags)) { 812 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag); 813 if (Flag == MO_FLAG_NOT_LAST) { 814 clearFlag(MI, Operand, MO_FLAG_LAST); 815 } else if (Flag == MO_FLAG_MASK) { 816 clearFlag(MI, Operand, Flag); 817 } else { 818 FlagOp.setImm(1); 819 } 820 } else { 821 MachineOperand &FlagOp = getFlagOp(MI, Operand); 822 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand))); 823 } 824 } 825 826 void R600InstrInfo::clearFlag(MachineInstr *MI, unsigned Operand, 827 unsigned Flag) const { 828 unsigned TargetFlags = get(MI->getOpcode()).TSFlags; 829 if (HAS_NATIVE_OPERANDS(TargetFlags)) { 830 MachineOperand &FlagOp = getFlagOp(MI, Operand, Flag); 831 FlagOp.setImm(0); 832 } else { 833 MachineOperand &FlagOp = getFlagOp(MI); 834 unsigned InstFlags = FlagOp.getImm(); 835 InstFlags &= ~(Flag << (NUM_MO_FLAGS * Operand)); 836 FlagOp.setImm(InstFlags); 837 } 838 } 839