SPUInstrInfo.cpp revision 600f171486708734e2b9c9c617528cfc51c16850
1//===- SPUInstrInfo.cpp - Cell SPU 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// This file contains the Cell SPU implementation of the TargetInstrInfo class. 11// 12//===----------------------------------------------------------------------===// 13 14#include "SPURegisterNames.h" 15#include "SPUInstrInfo.h" 16#include "SPUInstrBuilder.h" 17#include "SPUTargetMachine.h" 18#include "SPUGenInstrInfo.inc" 19#include "llvm/CodeGen/MachineInstrBuilder.h" 20#include "llvm/Support/Debug.h" 21#include "llvm/Support/ErrorHandling.h" 22#include "llvm/Support/raw_ostream.h" 23 24using namespace llvm; 25 26namespace { 27 //! Predicate for an unconditional branch instruction 28 inline bool isUncondBranch(const MachineInstr *I) { 29 unsigned opc = I->getOpcode(); 30 31 return (opc == SPU::BR 32 || opc == SPU::BRA 33 || opc == SPU::BI); 34 } 35 36 //! Predicate for a conditional branch instruction 37 inline bool isCondBranch(const MachineInstr *I) { 38 unsigned opc = I->getOpcode(); 39 40 return (opc == SPU::BRNZr32 41 || opc == SPU::BRNZv4i32 42 || opc == SPU::BRZr32 43 || opc == SPU::BRZv4i32 44 || opc == SPU::BRHNZr16 45 || opc == SPU::BRHNZv8i16 46 || opc == SPU::BRHZr16 47 || opc == SPU::BRHZv8i16); 48 } 49} 50 51SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) 52 : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), 53 TM(tm), 54 RI(*TM.getSubtargetImpl(), *this) 55{ /* NOP */ } 56 57bool 58SPUInstrInfo::isMoveInstr(const MachineInstr& MI, 59 unsigned& sourceReg, 60 unsigned& destReg, 61 unsigned& SrcSR, unsigned& DstSR) const { 62 SrcSR = DstSR = 0; // No sub-registers. 63 64 switch (MI.getOpcode()) { 65 default: 66 break; 67 case SPU::ORIv4i32: 68 case SPU::ORIr32: 69 case SPU::ORHIv8i16: 70 case SPU::ORHIr16: 71 case SPU::ORHIi8i16: 72 case SPU::ORBIv16i8: 73 case SPU::ORBIr8: 74 case SPU::ORIi16i32: 75 case SPU::ORIi8i32: 76 case SPU::AHIvec: 77 case SPU::AHIr16: 78 case SPU::AIv4i32: 79 assert(MI.getNumOperands() == 3 && 80 MI.getOperand(0).isReg() && 81 MI.getOperand(1).isReg() && 82 MI.getOperand(2).isImm() && 83 "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!"); 84 if (MI.getOperand(2).getImm() == 0) { 85 sourceReg = MI.getOperand(1).getReg(); 86 destReg = MI.getOperand(0).getReg(); 87 return true; 88 } 89 break; 90 case SPU::AIr32: 91 assert(MI.getNumOperands() == 3 && 92 "wrong number of operands to AIr32"); 93 if (MI.getOperand(0).isReg() && 94 MI.getOperand(1).isReg() && 95 (MI.getOperand(2).isImm() && 96 MI.getOperand(2).getImm() == 0)) { 97 sourceReg = MI.getOperand(1).getReg(); 98 destReg = MI.getOperand(0).getReg(); 99 return true; 100 } 101 break; 102 case SPU::LRr8: 103 case SPU::LRr16: 104 case SPU::LRr32: 105 case SPU::LRf32: 106 case SPU::LRr64: 107 case SPU::LRf64: 108 case SPU::LRr128: 109 case SPU::LRv16i8: 110 case SPU::LRv8i16: 111 case SPU::LRv4i32: 112 case SPU::LRv4f32: 113 case SPU::LRv2i64: 114 case SPU::LRv2f64: 115 case SPU::ORv16i8_i8: 116 case SPU::ORv8i16_i16: 117 case SPU::ORv4i32_i32: 118 case SPU::ORv2i64_i64: 119 case SPU::ORv4f32_f32: 120 case SPU::ORv2f64_f64: 121 case SPU::ORi8_v16i8: 122 case SPU::ORi16_v8i16: 123 case SPU::ORi32_v4i32: 124 case SPU::ORi64_v2i64: 125 case SPU::ORf32_v4f32: 126 case SPU::ORf64_v2f64: 127/* 128 case SPU::ORi128_r64: 129 case SPU::ORi128_f64: 130 case SPU::ORi128_r32: 131 case SPU::ORi128_f32: 132 case SPU::ORi128_r16: 133 case SPU::ORi128_r8: 134*/ 135 case SPU::ORi128_vec: 136/* 137 case SPU::ORr64_i128: 138 case SPU::ORf64_i128: 139 case SPU::ORr32_i128: 140 case SPU::ORf32_i128: 141 case SPU::ORr16_i128: 142 case SPU::ORr8_i128: 143*/ 144 case SPU::ORvec_i128: 145/* 146 case SPU::ORr16_r32: 147 case SPU::ORr8_r32: 148 case SPU::ORf32_r32: 149 case SPU::ORr32_f32: 150 case SPU::ORr32_r16: 151 case SPU::ORr32_r8: 152 case SPU::ORr16_r64: 153 case SPU::ORr8_r64: 154 case SPU::ORr64_r16: 155 case SPU::ORr64_r8: 156*/ 157 case SPU::ORr64_r32: 158 case SPU::ORr32_r64: 159 case SPU::ORf32_r32: 160 case SPU::ORr32_f32: 161 case SPU::ORf64_r64: 162 case SPU::ORr64_f64: { 163 assert(MI.getNumOperands() == 2 && 164 MI.getOperand(0).isReg() && 165 MI.getOperand(1).isReg() && 166 "invalid SPU OR<type>_<vec> or LR instruction!"); 167 sourceReg = MI.getOperand(1).getReg(); 168 destReg = MI.getOperand(0).getReg(); 169 return true; 170 break; 171 } 172 case SPU::ORv16i8: 173 case SPU::ORv8i16: 174 case SPU::ORv4i32: 175 case SPU::ORv2i64: 176 case SPU::ORr8: 177 case SPU::ORr16: 178 case SPU::ORr32: 179 case SPU::ORr64: 180 case SPU::ORr128: 181 case SPU::ORf32: 182 case SPU::ORf64: 183 assert(MI.getNumOperands() == 3 && 184 MI.getOperand(0).isReg() && 185 MI.getOperand(1).isReg() && 186 MI.getOperand(2).isReg() && 187 "invalid SPU OR(vec|r32|r64|gprc) instruction!"); 188 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { 189 sourceReg = MI.getOperand(1).getReg(); 190 destReg = MI.getOperand(0).getReg(); 191 return true; 192 } 193 break; 194 } 195 196 return false; 197} 198 199unsigned 200SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 201 int &FrameIndex) const { 202 switch (MI->getOpcode()) { 203 default: break; 204 case SPU::LQDv16i8: 205 case SPU::LQDv8i16: 206 case SPU::LQDv4i32: 207 case SPU::LQDv4f32: 208 case SPU::LQDv2f64: 209 case SPU::LQDr128: 210 case SPU::LQDr64: 211 case SPU::LQDr32: 212 case SPU::LQDr16: { 213 const MachineOperand MOp1 = MI->getOperand(1); 214 const MachineOperand MOp2 = MI->getOperand(2); 215 if (MOp1.isImm() && MOp2.isFI()) { 216 FrameIndex = MOp2.getIndex(); 217 return MI->getOperand(0).getReg(); 218 } 219 break; 220 } 221 } 222 return 0; 223} 224 225unsigned 226SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 227 int &FrameIndex) const { 228 switch (MI->getOpcode()) { 229 default: break; 230 case SPU::STQDv16i8: 231 case SPU::STQDv8i16: 232 case SPU::STQDv4i32: 233 case SPU::STQDv4f32: 234 case SPU::STQDv2f64: 235 case SPU::STQDr128: 236 case SPU::STQDr64: 237 case SPU::STQDr32: 238 case SPU::STQDr16: 239 case SPU::STQDr8: { 240 const MachineOperand MOp1 = MI->getOperand(1); 241 const MachineOperand MOp2 = MI->getOperand(2); 242 if (MOp1.isImm() && MOp2.isFI()) { 243 FrameIndex = MOp2.getIndex(); 244 return MI->getOperand(0).getReg(); 245 } 246 break; 247 } 248 } 249 return 0; 250} 251 252void SPUInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 253 MachineBasicBlock::iterator I, DebugLoc DL, 254 unsigned DestReg, unsigned SrcReg, 255 bool KillSrc) const 256{ 257 // We support cross register class moves for our aliases, such as R3 in any 258 // reg class to any other reg class containing R3. This is required because 259 // we instruction select bitconvert i64 -> f64 as a noop for example, so our 260 // types have no specific meaning. 261 262 BuildMI(MBB, I, DL, get(SPU::LRr128), DestReg) 263 .addReg(SrcReg, getKillRegState(KillSrc)); 264} 265 266void 267SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 268 MachineBasicBlock::iterator MI, 269 unsigned SrcReg, bool isKill, int FrameIdx, 270 const TargetRegisterClass *RC, 271 const TargetRegisterInfo *TRI) const 272{ 273 unsigned opc; 274 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 275 if (RC == SPU::GPRCRegisterClass) { 276 opc = (isValidFrameIdx ? SPU::STQDr128 : SPU::STQXr128); 277 } else if (RC == SPU::R64CRegisterClass) { 278 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 279 } else if (RC == SPU::R64FPRegisterClass) { 280 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 281 } else if (RC == SPU::R32CRegisterClass) { 282 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 283 } else if (RC == SPU::R32FPRegisterClass) { 284 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 285 } else if (RC == SPU::R16CRegisterClass) { 286 opc = (isValidFrameIdx ? SPU::STQDr16 : SPU::STQXr16); 287 } else if (RC == SPU::R8CRegisterClass) { 288 opc = (isValidFrameIdx ? SPU::STQDr8 : SPU::STQXr8); 289 } else if (RC == SPU::VECREGRegisterClass) { 290 opc = (isValidFrameIdx) ? SPU::STQDv16i8 : SPU::STQXv16i8; 291 } else { 292 llvm_unreachable("Unknown regclass!"); 293 } 294 295 DebugLoc DL; 296 if (MI != MBB.end()) DL = MI->getDebugLoc(); 297 addFrameReference(BuildMI(MBB, MI, DL, get(opc)) 298 .addReg(SrcReg, getKillRegState(isKill)), FrameIdx); 299} 300 301void 302SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 303 MachineBasicBlock::iterator MI, 304 unsigned DestReg, int FrameIdx, 305 const TargetRegisterClass *RC, 306 const TargetRegisterInfo *TRI) const 307{ 308 unsigned opc; 309 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 310 if (RC == SPU::GPRCRegisterClass) { 311 opc = (isValidFrameIdx ? SPU::LQDr128 : SPU::LQXr128); 312 } else if (RC == SPU::R64CRegisterClass) { 313 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 314 } else if (RC == SPU::R64FPRegisterClass) { 315 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 316 } else if (RC == SPU::R32CRegisterClass) { 317 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 318 } else if (RC == SPU::R32FPRegisterClass) { 319 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 320 } else if (RC == SPU::R16CRegisterClass) { 321 opc = (isValidFrameIdx ? SPU::LQDr16 : SPU::LQXr16); 322 } else if (RC == SPU::R8CRegisterClass) { 323 opc = (isValidFrameIdx ? SPU::LQDr8 : SPU::LQXr8); 324 } else if (RC == SPU::VECREGRegisterClass) { 325 opc = (isValidFrameIdx) ? SPU::LQDv16i8 : SPU::LQXv16i8; 326 } else { 327 llvm_unreachable("Unknown regclass in loadRegFromStackSlot!"); 328 } 329 330 DebugLoc DL; 331 if (MI != MBB.end()) DL = MI->getDebugLoc(); 332 addFrameReference(BuildMI(MBB, MI, DL, get(opc), DestReg), FrameIdx); 333} 334 335//! Branch analysis 336/*! 337 \note This code was kiped from PPC. There may be more branch analysis for 338 CellSPU than what's currently done here. 339 */ 340bool 341SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 342 MachineBasicBlock *&FBB, 343 SmallVectorImpl<MachineOperand> &Cond, 344 bool AllowModify) const { 345 // If the block has no terminators, it just falls into the block after it. 346 MachineBasicBlock::iterator I = MBB.end(); 347 if (I == MBB.begin()) 348 return false; 349 --I; 350 while (I->isDebugValue()) { 351 if (I == MBB.begin()) 352 return false; 353 --I; 354 } 355 if (!isUnpredicatedTerminator(I)) 356 return false; 357 358 // Get the last instruction in the block. 359 MachineInstr *LastInst = I; 360 361 // If there is only one terminator instruction, process it. 362 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 363 if (isUncondBranch(LastInst)) { 364 // Check for jump tables 365 if (!LastInst->getOperand(0).isMBB()) 366 return true; 367 TBB = LastInst->getOperand(0).getMBB(); 368 return false; 369 } else if (isCondBranch(LastInst)) { 370 // Block ends with fall-through condbranch. 371 TBB = LastInst->getOperand(1).getMBB(); 372 DEBUG(errs() << "Pushing LastInst: "); 373 DEBUG(LastInst->dump()); 374 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 375 Cond.push_back(LastInst->getOperand(0)); 376 return false; 377 } 378 // Otherwise, don't know what this is. 379 return true; 380 } 381 382 // Get the instruction before it if it's a terminator. 383 MachineInstr *SecondLastInst = I; 384 385 // If there are three terminators, we don't know what sort of block this is. 386 if (SecondLastInst && I != MBB.begin() && 387 isUnpredicatedTerminator(--I)) 388 return true; 389 390 // If the block ends with a conditional and unconditional branch, handle it. 391 if (isCondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 392 TBB = SecondLastInst->getOperand(1).getMBB(); 393 DEBUG(errs() << "Pushing SecondLastInst: "); 394 DEBUG(SecondLastInst->dump()); 395 Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 396 Cond.push_back(SecondLastInst->getOperand(0)); 397 FBB = LastInst->getOperand(0).getMBB(); 398 return false; 399 } 400 401 // If the block ends with two unconditional branches, handle it. The second 402 // one is not executed, so remove it. 403 if (isUncondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 404 TBB = SecondLastInst->getOperand(0).getMBB(); 405 I = LastInst; 406 if (AllowModify) 407 I->eraseFromParent(); 408 return false; 409 } 410 411 // Otherwise, can't handle this. 412 return true; 413} 414 415unsigned 416SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 417 MachineBasicBlock::iterator I = MBB.end(); 418 if (I == MBB.begin()) 419 return 0; 420 --I; 421 while (I->isDebugValue()) { 422 if (I == MBB.begin()) 423 return 0; 424 --I; 425 } 426 if (!isCondBranch(I) && !isUncondBranch(I)) 427 return 0; 428 429 // Remove the first branch. 430 DEBUG(errs() << "Removing branch: "); 431 DEBUG(I->dump()); 432 I->eraseFromParent(); 433 I = MBB.end(); 434 if (I == MBB.begin()) 435 return 1; 436 437 --I; 438 if (!(isCondBranch(I) || isUncondBranch(I))) 439 return 1; 440 441 // Remove the second branch. 442 DEBUG(errs() << "Removing second branch: "); 443 DEBUG(I->dump()); 444 I->eraseFromParent(); 445 return 2; 446} 447 448unsigned 449SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 450 MachineBasicBlock *FBB, 451 const SmallVectorImpl<MachineOperand> &Cond, 452 DebugLoc DL) const { 453 // Shouldn't be a fall through. 454 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 455 assert((Cond.size() == 2 || Cond.size() == 0) && 456 "SPU branch conditions have two components!"); 457 458 // One-way branch. 459 if (FBB == 0) { 460 if (Cond.empty()) { 461 // Unconditional branch 462 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(SPU::BR)); 463 MIB.addMBB(TBB); 464 465 DEBUG(errs() << "Inserted one-way uncond branch: "); 466 DEBUG((*MIB).dump()); 467 } else { 468 // Conditional branch 469 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); 470 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 471 472 DEBUG(errs() << "Inserted one-way cond branch: "); 473 DEBUG((*MIB).dump()); 474 } 475 return 1; 476 } else { 477 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); 478 MachineInstrBuilder MIB2 = BuildMI(&MBB, DL, get(SPU::BR)); 479 480 // Two-way Conditional Branch. 481 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 482 MIB2.addMBB(FBB); 483 484 DEBUG(errs() << "Inserted conditional branch: "); 485 DEBUG((*MIB).dump()); 486 DEBUG(errs() << "part 2: "); 487 DEBUG((*MIB2).dump()); 488 return 2; 489 } 490} 491 492//! Reverses a branch's condition, returning false on success. 493bool 494SPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) 495 const { 496 // Pretty brainless way of inverting the condition, but it works, considering 497 // there are only two conditions... 498 static struct { 499 unsigned Opc; //! The incoming opcode 500 unsigned RevCondOpc; //! The reversed condition opcode 501 } revconds[] = { 502 { SPU::BRNZr32, SPU::BRZr32 }, 503 { SPU::BRNZv4i32, SPU::BRZv4i32 }, 504 { SPU::BRZr32, SPU::BRNZr32 }, 505 { SPU::BRZv4i32, SPU::BRNZv4i32 }, 506 { SPU::BRHNZr16, SPU::BRHZr16 }, 507 { SPU::BRHNZv8i16, SPU::BRHZv8i16 }, 508 { SPU::BRHZr16, SPU::BRHNZr16 }, 509 { SPU::BRHZv8i16, SPU::BRHNZv8i16 } 510 }; 511 512 unsigned Opc = unsigned(Cond[0].getImm()); 513 // Pretty dull mapping between the two conditions that SPU can generate: 514 for (int i = sizeof(revconds)/sizeof(revconds[0]) - 1; i >= 0; --i) { 515 if (revconds[i].Opc == Opc) { 516 Cond[0].setImm(revconds[i].RevCondOpc); 517 return false; 518 } 519 } 520 521 return true; 522} 523