R600InstrInfo.cpp revision 67a47a445b544ac638d10303dc697d70f25d12fb
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// R600 Implementation of TargetInstrInfo. 11// 12//===----------------------------------------------------------------------===// 13 14#include "R600InstrInfo.h" 15#include "AMDGPUTargetMachine.h" 16#include "AMDGPUSubtarget.h" 17#include "R600RegisterInfo.h" 18#include "llvm/CodeGen/MachineInstrBuilder.h" 19#include "AMDILUtilityFunctions.h" 20 21#define GET_INSTRINFO_CTOR 22#include "AMDGPUGenDFAPacketizer.inc" 23 24using namespace llvm; 25 26R600InstrInfo::R600InstrInfo(AMDGPUTargetMachine &tm) 27 : AMDGPUInstrInfo(tm), 28 RI(tm, *this), 29 TM(tm) 30 { } 31 32const R600RegisterInfo &R600InstrInfo::getRegisterInfo() const 33{ 34 return RI; 35} 36 37bool R600InstrInfo::isTrig(const MachineInstr &MI) const 38{ 39 return get(MI.getOpcode()).TSFlags & R600_InstFlag::TRIG; 40} 41 42bool R600InstrInfo::isVector(const MachineInstr &MI) const 43{ 44 return get(MI.getOpcode()).TSFlags & R600_InstFlag::VECTOR; 45} 46 47void 48R600InstrInfo::copyPhysReg(MachineBasicBlock &MBB, 49 MachineBasicBlock::iterator MI, DebugLoc DL, 50 unsigned DestReg, unsigned SrcReg, 51 bool KillSrc) const 52{ 53 if (AMDGPU::R600_Reg128RegClass.contains(DestReg) 54 && AMDGPU::R600_Reg128RegClass.contains(SrcReg)) { 55 for (unsigned i = 0; i < 4; i++) { 56 unsigned SubRegIndex = RI.getSubRegFromChannel(i); 57 BuildMI(MBB, MI, DL, get(AMDGPU::MOV)) 58 .addReg(RI.getSubReg(DestReg, SubRegIndex), RegState::Define) 59 .addReg(RI.getSubReg(SrcReg, SubRegIndex)) 60 .addImm(0) // Flag 61 .addReg(0) // PREDICATE_BIT 62 .addReg(DestReg, RegState::Define | RegState::Implicit); 63 } 64 } else { 65 66 /* We can't copy vec4 registers */ 67 assert(!AMDGPU::R600_Reg128RegClass.contains(DestReg) 68 && !AMDGPU::R600_Reg128RegClass.contains(SrcReg)); 69 70 BuildMI(MBB, MI, DL, get(AMDGPU::MOV), DestReg) 71 .addReg(SrcReg, getKillRegState(KillSrc)) 72 .addImm(0) // Flag 73 .addReg(0); // PREDICATE_BIT 74 } 75} 76 77MachineInstr * R600InstrInfo::getMovImmInstr(MachineFunction *MF, 78 unsigned DstReg, int64_t Imm) const 79{ 80 MachineInstr * MI = MF->CreateMachineInstr(get(AMDGPU::MOV), DebugLoc()); 81 MachineInstrBuilder(MI).addReg(DstReg, RegState::Define); 82 MachineInstrBuilder(MI).addReg(AMDGPU::ALU_LITERAL_X); 83 MachineInstrBuilder(MI).addImm(Imm); 84 MachineInstrBuilder(MI).addReg(0); // PREDICATE_BIT 85 86 return MI; 87} 88 89unsigned R600InstrInfo::getIEQOpcode() const 90{ 91 return AMDGPU::SETE_INT; 92} 93 94bool R600InstrInfo::isMov(unsigned Opcode) const 95{ 96 97 98 switch(Opcode) { 99 default: return false; 100 case AMDGPU::MOV: 101 case AMDGPU::MOV_IMM_F32: 102 case AMDGPU::MOV_IMM_I32: 103 return true; 104 } 105} 106 107// Some instructions act as place holders to emulate operations that the GPU 108// hardware does automatically. This function can be used to check if 109// an opcode falls into this category. 110bool R600InstrInfo::isPlaceHolderOpcode(unsigned opcode) const 111{ 112 switch (opcode) { 113 default: return false; 114 case AMDGPU::RETURN: 115 case AMDGPU::LAST: 116 case AMDGPU::MASK_WRITE: 117 case AMDGPU::RESERVE_REG: 118 return true; 119 } 120} 121 122bool R600InstrInfo::isTexOp(unsigned opcode) const 123{ 124 switch(opcode) { 125 default: return false; 126 case AMDGPU::TEX_LD: 127 case AMDGPU::TEX_GET_TEXTURE_RESINFO: 128 case AMDGPU::TEX_SAMPLE: 129 case AMDGPU::TEX_SAMPLE_C: 130 case AMDGPU::TEX_SAMPLE_L: 131 case AMDGPU::TEX_SAMPLE_C_L: 132 case AMDGPU::TEX_SAMPLE_LB: 133 case AMDGPU::TEX_SAMPLE_C_LB: 134 case AMDGPU::TEX_SAMPLE_G: 135 case AMDGPU::TEX_SAMPLE_C_G: 136 case AMDGPU::TEX_GET_GRADIENTS_H: 137 case AMDGPU::TEX_GET_GRADIENTS_V: 138 case AMDGPU::TEX_SET_GRADIENTS_H: 139 case AMDGPU::TEX_SET_GRADIENTS_V: 140 return true; 141 } 142} 143 144bool R600InstrInfo::isReductionOp(unsigned opcode) const 145{ 146 switch(opcode) { 147 default: return false; 148 case AMDGPU::DOT4_r600: 149 case AMDGPU::DOT4_eg: 150 return true; 151 } 152} 153 154bool R600InstrInfo::isCubeOp(unsigned opcode) const 155{ 156 switch(opcode) { 157 default: return false; 158 case AMDGPU::CUBE_r600_pseudo: 159 case AMDGPU::CUBE_r600_real: 160 case AMDGPU::CUBE_eg_pseudo: 161 case AMDGPU::CUBE_eg_real: 162 return true; 163 } 164} 165 166 167bool R600InstrInfo::isFCOp(unsigned opcode) const 168{ 169 switch(opcode) { 170 default: return false; 171 case AMDGPU::BREAK_LOGICALZ_f32: 172 case AMDGPU::BREAK_LOGICALNZ_i32: 173 case AMDGPU::BREAK_LOGICALZ_i32: 174 case AMDGPU::BREAK_LOGICALNZ_f32: 175 case AMDGPU::CONTINUE_LOGICALNZ_f32: 176 case AMDGPU::IF_LOGICALNZ_i32: 177 case AMDGPU::IF_LOGICALZ_f32: 178 case AMDGPU::ELSE: 179 case AMDGPU::ENDIF: 180 case AMDGPU::ENDLOOP: 181 case AMDGPU::IF_LOGICALNZ_f32: 182 case AMDGPU::WHILELOOP: 183 return true; 184 } 185} 186 187DFAPacketizer *R600InstrInfo::CreateTargetScheduleState(const TargetMachine *TM, 188 const ScheduleDAG *DAG) const 189{ 190 const InstrItineraryData *II = TM->getInstrItineraryData(); 191 return TM->getSubtarget<AMDGPUSubtarget>().createDFAPacketizer(II); 192} 193 194static bool 195isPredicateSetter(unsigned opcode) 196{ 197 switch (opcode) { 198 case AMDGPU::PRED_X: 199 return true; 200 default: 201 return false; 202 } 203} 204 205static MachineInstr * 206findFirstPredicateSetterFrom(MachineBasicBlock &MBB, 207 MachineBasicBlock::iterator I) 208{ 209 while (I != MBB.begin()) { 210 --I; 211 MachineInstr *MI = I; 212 if (isPredicateSetter(MI->getOpcode())) 213 return MI; 214 } 215 216 return NULL; 217} 218 219bool 220R600InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, 221 MachineBasicBlock *&TBB, 222 MachineBasicBlock *&FBB, 223 SmallVectorImpl<MachineOperand> &Cond, 224 bool AllowModify) const 225{ 226 // Most of the following comes from the ARM implementation of AnalyzeBranch 227 228 // If the block has no terminators, it just falls into the block after it. 229 MachineBasicBlock::iterator I = MBB.end(); 230 if (I == MBB.begin()) 231 return false; 232 --I; 233 while (I->isDebugValue()) { 234 if (I == MBB.begin()) 235 return false; 236 --I; 237 } 238 if (static_cast<MachineInstr *>(I)->getOpcode() != AMDGPU::JUMP) { 239 return false; 240 } 241 242 // Get the last instruction in the block. 243 MachineInstr *LastInst = I; 244 245 // If there is only one terminator instruction, process it. 246 unsigned LastOpc = LastInst->getOpcode(); 247 if (I == MBB.begin() || 248 static_cast<MachineInstr *>(--I)->getOpcode() != AMDGPU::JUMP) { 249 if (LastOpc == AMDGPU::JUMP) { 250 if(!isPredicated(LastInst)) { 251 TBB = LastInst->getOperand(0).getMBB(); 252 return false; 253 } else { 254 MachineInstr *predSet = I; 255 while (!isPredicateSetter(predSet->getOpcode())) { 256 predSet = --I; 257 } 258 TBB = LastInst->getOperand(0).getMBB(); 259 Cond.push_back(predSet->getOperand(1)); 260 Cond.push_back(predSet->getOperand(2)); 261 Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false)); 262 return false; 263 } 264 } 265 return true; // Can't handle indirect branch. 266 } 267 268 // Get the instruction before it if it is a terminator. 269 MachineInstr *SecondLastInst = I; 270 unsigned SecondLastOpc = SecondLastInst->getOpcode(); 271 272 // If the block ends with a B and a Bcc, handle it. 273 if (SecondLastOpc == AMDGPU::JUMP && 274 isPredicated(SecondLastInst) && 275 LastOpc == AMDGPU::JUMP && 276 !isPredicated(LastInst)) { 277 MachineInstr *predSet = --I; 278 while (!isPredicateSetter(predSet->getOpcode())) { 279 predSet = --I; 280 } 281 TBB = SecondLastInst->getOperand(0).getMBB(); 282 FBB = LastInst->getOperand(0).getMBB(); 283 Cond.push_back(predSet->getOperand(1)); 284 Cond.push_back(predSet->getOperand(2)); 285 Cond.push_back(MachineOperand::CreateReg(AMDGPU::PRED_SEL_ONE, false)); 286 return false; 287 } 288 289 // Otherwise, can't handle this. 290 return true; 291} 292 293int R600InstrInfo::getBranchInstr(const MachineOperand &op) const { 294 const MachineInstr *MI = op.getParent(); 295 296 switch (MI->getDesc().OpInfo->RegClass) { 297 default: // FIXME: fallthrough?? 298 case AMDGPU::GPRI32RegClassID: return AMDGPU::BRANCH_COND_i32; 299 case AMDGPU::GPRF32RegClassID: return AMDGPU::BRANCH_COND_f32; 300 }; 301} 302 303unsigned 304R600InstrInfo::InsertBranch(MachineBasicBlock &MBB, 305 MachineBasicBlock *TBB, 306 MachineBasicBlock *FBB, 307 const SmallVectorImpl<MachineOperand> &Cond, 308 DebugLoc DL) const 309{ 310 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 311 312 if (FBB == 0) { 313 if (Cond.empty()) { 314 BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(TBB).addReg(0); 315 return 1; 316 } else { 317 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end()); 318 assert(PredSet && "No previous predicate !"); 319 PredSet->getOperand(1).addTargetFlag(1<<4); 320 PredSet->getOperand(2).setImm(Cond[1].getImm()); 321 322 BuildMI(&MBB, DL, get(AMDGPU::JUMP)) 323 .addMBB(TBB) 324 .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill); 325 return 1; 326 } 327 } else { 328 MachineInstr *PredSet = findFirstPredicateSetterFrom(MBB, MBB.end()); 329 assert(PredSet && "No previous predicate !"); 330 PredSet->getOperand(1).addTargetFlag(1<<4); 331 PredSet->getOperand(2).setImm(Cond[1].getImm()); 332 BuildMI(&MBB, DL, get(AMDGPU::JUMP)) 333 .addMBB(TBB) 334 .addReg(AMDGPU::PREDICATE_BIT, RegState::Kill); 335 BuildMI(&MBB, DL, get(AMDGPU::JUMP)).addMBB(FBB).addReg(0); 336 return 2; 337 } 338} 339 340unsigned 341R600InstrInfo::RemoveBranch(MachineBasicBlock &MBB) const 342{ 343 344 // Note : we leave PRED* instructions there. 345 // They may be needed when predicating instructions. 346 347 MachineBasicBlock::iterator I = MBB.end(); 348 349 if (I == MBB.begin()) { 350 return 0; 351 } 352 --I; 353 switch (I->getOpcode()) { 354 default: 355 return 0; 356 case AMDGPU::JUMP: 357 if (isPredicated(I)) { 358 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I); 359 char flag = predSet->getOperand(1).getTargetFlags() & (~(1<<4)); 360 predSet->getOperand(1).setTargetFlags(flag); 361 } 362 I->eraseFromParent(); 363 break; 364 } 365 I = MBB.end(); 366 367 if (I == MBB.begin()) { 368 return 1; 369 } 370 --I; 371 switch (I->getOpcode()) { 372 // FIXME: only one case?? 373 default: 374 return 1; 375 case AMDGPU::JUMP: 376 if (isPredicated(I)) { 377 MachineInstr *predSet = findFirstPredicateSetterFrom(MBB, I); 378 char flag = predSet->getOperand(1).getTargetFlags() & (~(1<<4)); 379 predSet->getOperand(1).setTargetFlags(flag); 380 } 381 I->eraseFromParent(); 382 break; 383 } 384 return 2; 385} 386 387bool 388R600InstrInfo::isPredicated(const MachineInstr *MI) const 389{ 390 int idx = MI->findFirstPredOperandIdx(); 391 if (idx < 0) 392 return false; 393 394 unsigned Reg = MI->getOperand(idx).getReg(); 395 switch (Reg) { 396 default: return false; 397 case AMDGPU::PRED_SEL_ONE: 398 case AMDGPU::PRED_SEL_ZERO: 399 case AMDGPU::PREDICATE_BIT: 400 return true; 401 } 402} 403 404bool 405R600InstrInfo::isPredicable(MachineInstr *MI) const 406{ 407 return AMDGPUInstrInfo::isPredicable(MI); 408} 409 410 411bool 412R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &MBB, 413 unsigned NumCyles, 414 unsigned ExtraPredCycles, 415 const BranchProbability &Probability) const{ 416 return true; 417} 418 419bool 420R600InstrInfo::isProfitableToIfCvt(MachineBasicBlock &TMBB, 421 unsigned NumTCycles, 422 unsigned ExtraTCycles, 423 MachineBasicBlock &FMBB, 424 unsigned NumFCycles, 425 unsigned ExtraFCycles, 426 const BranchProbability &Probability) const 427{ 428 return true; 429} 430 431bool 432R600InstrInfo::isProfitableToDupForIfCvt(MachineBasicBlock &MBB, 433 unsigned NumCyles, 434 const BranchProbability &Probability) 435 const 436{ 437 return true; 438} 439 440bool 441R600InstrInfo::isProfitableToUnpredicate(MachineBasicBlock &TMBB, 442 MachineBasicBlock &FMBB) const 443{ 444 return false; 445} 446 447 448bool 449R600InstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const 450{ 451 MachineOperand &MO = Cond[1]; 452 switch (MO.getImm()) { 453 case OPCODE_IS_ZERO_INT: 454 MO.setImm(OPCODE_IS_NOT_ZERO_INT); 455 break; 456 case OPCODE_IS_NOT_ZERO_INT: 457 MO.setImm(OPCODE_IS_ZERO_INT); 458 break; 459 case OPCODE_IS_ZERO: 460 MO.setImm(OPCODE_IS_NOT_ZERO); 461 break; 462 case OPCODE_IS_NOT_ZERO: 463 MO.setImm(OPCODE_IS_ZERO); 464 break; 465 default: 466 return true; 467 } 468 469 MachineOperand &MO2 = Cond[2]; 470 switch (MO2.getReg()) { 471 case AMDGPU::PRED_SEL_ZERO: 472 MO2.setReg(AMDGPU::PRED_SEL_ONE); 473 break; 474 case AMDGPU::PRED_SEL_ONE: 475 MO2.setReg(AMDGPU::PRED_SEL_ZERO); 476 break; 477 default: 478 return true; 479 } 480 return false; 481} 482 483bool 484R600InstrInfo::DefinesPredicate(MachineInstr *MI, 485 std::vector<MachineOperand> &Pred) const 486{ 487 return isPredicateSetter(MI->getOpcode()); 488} 489 490 491bool 492R600InstrInfo::SubsumesPredicate(const SmallVectorImpl<MachineOperand> &Pred1, 493 const SmallVectorImpl<MachineOperand> &Pred2) const 494{ 495 return false; 496} 497 498 499bool 500R600InstrInfo::PredicateInstruction(MachineInstr *MI, 501 const SmallVectorImpl<MachineOperand> &Pred) const 502{ 503 int PIdx = MI->findFirstPredOperandIdx(); 504 505 if (PIdx != -1) { 506 MachineOperand &PMO = MI->getOperand(PIdx); 507 PMO.setReg(Pred[2].getReg()); 508 MachineInstrBuilder(MI).addReg(AMDGPU::PREDICATE_BIT, RegState::Implicit); 509 return true; 510 } 511 512 return false; 513} 514 515int R600InstrInfo::getInstrLatency(const InstrItineraryData *ItinData, 516 const MachineInstr *MI, 517 unsigned *PredCost) const 518{ 519 if (PredCost) 520 *PredCost = 2; 521 return 2; 522} 523 524//===----------------------------------------------------------------------===// 525// Instruction flag getters/setters 526//===----------------------------------------------------------------------===// 527 528#define GET_FLAG_OPERAND_IDX(MI) (((MI).getDesc().TSFlags >> 7) & 0x3) 529 530bool R600InstrInfo::HasFlagOperand(const MachineInstr &MI) const 531{ 532 return GET_FLAG_OPERAND_IDX(MI) != 0; 533} 534 535void R600InstrInfo::AddFlag(MachineInstr *MI, unsigned Operand, 536 unsigned Flag) const 537{ 538 unsigned FlagIndex = GET_FLAG_OPERAND_IDX(*MI); 539 assert(FlagIndex != 0 && 540 "Instruction flags not supported for this instruction"); 541 MachineOperand &FlagOp = MI->getOperand(FlagIndex); 542 assert(FlagOp.isImm()); 543 FlagOp.setImm(FlagOp.getImm() | (Flag << (NUM_MO_FLAGS * Operand))); 544} 545 546bool R600InstrInfo::IsFlagSet(const MachineInstr &MI, unsigned Operand, 547 unsigned Flag) const 548{ 549 unsigned FlagIndex = GET_FLAG_OPERAND_IDX(MI); 550 if (FlagIndex == 0) { 551 return false; 552 } 553 assert(MI.getOperand(FlagIndex).isImm()); 554 return !!((MI.getOperand(FlagIndex).getImm() >> 555 (NUM_MO_FLAGS * Operand)) & Flag); 556} 557