SPUInstrInfo.cpp revision dc54d317e7a381ef8e4aca80d54ad1466bb85dda
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/Streams.h" 21#include "llvm/Support/Debug.h" 22 23using namespace llvm; 24 25namespace { 26 //! Predicate for an unconditional branch instruction 27 inline bool isUncondBranch(const MachineInstr *I) { 28 unsigned opc = I->getOpcode(); 29 30 return (opc == SPU::BR 31 || opc == SPU::BRA 32 || opc == SPU::BI); 33 } 34 35 //! Predicate for a conditional branch instruction 36 inline bool isCondBranch(const MachineInstr *I) { 37 unsigned opc = I->getOpcode(); 38 39 return (opc == SPU::BRNZr32 40 || opc == SPU::BRNZv4i32 41 || opc == SPU::BRZr32 42 || opc == SPU::BRZv4i32 43 || opc == SPU::BRHNZr16 44 || opc == SPU::BRHNZv8i16 45 || opc == SPU::BRHZr16 46 || opc == SPU::BRHZv8i16); 47 } 48} 49 50SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) 51 : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), 52 TM(tm), 53 RI(*TM.getSubtargetImpl(), *this) 54{ /* NOP */ } 55 56bool 57SPUInstrInfo::isMoveInstr(const MachineInstr& MI, 58 unsigned& sourceReg, 59 unsigned& destReg, 60 unsigned& SrcSR, unsigned& DstSR) const { 61 SrcSR = DstSR = 0; // No sub-registers. 62 63 // Primarily, ORI and OR are generated by copyRegToReg. But, there are other 64 // cases where we can safely say that what's being done is really a move 65 // (see how PowerPC does this -- it's the model for this code too.) 66 switch (MI.getOpcode()) { 67 default: 68 break; 69 case SPU::ORIv4i32: 70 case SPU::ORIr32: 71 case SPU::ORHIv8i16: 72 case SPU::ORHIr16: 73 case SPU::ORHIi8i16: 74 case SPU::ORBIv16i8: 75 case SPU::ORBIr8: 76 case SPU::ORIi16i32: 77 case SPU::ORIi8i32: 78 case SPU::AHIvec: 79 case SPU::AHIr16: 80 case SPU::AIv4i32: 81 assert(MI.getNumOperands() == 3 && 82 MI.getOperand(0).isReg() && 83 MI.getOperand(1).isReg() && 84 MI.getOperand(2).isImm() && 85 "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!"); 86 if (MI.getOperand(2).getImm() == 0) { 87 sourceReg = MI.getOperand(1).getReg(); 88 destReg = MI.getOperand(0).getReg(); 89 return true; 90 } 91 break; 92 case SPU::AIr32: 93 assert(MI.getNumOperands() == 3 && 94 "wrong number of operands to AIr32"); 95 if (MI.getOperand(0).isReg() && 96 MI.getOperand(1).isReg() && 97 (MI.getOperand(2).isImm() && 98 MI.getOperand(2).getImm() == 0)) { 99 sourceReg = MI.getOperand(1).getReg(); 100 destReg = MI.getOperand(0).getReg(); 101 return true; 102 } 103 break; 104 case SPU::LRr8: 105 case SPU::LRr16: 106 case SPU::LRr32: 107 case SPU::LRf32: 108 case SPU::LRr64: 109 case SPU::LRf64: 110 case SPU::LRr128: 111 case SPU::LRv16i8: 112 case SPU::LRv8i16: 113 case SPU::LRv4i32: 114 case SPU::LRv4f32: 115 case SPU::LRv2i64: 116 case SPU::LRv2f64: 117 case SPU::ORv16i8_i8: 118 case SPU::ORv8i16_i16: 119 case SPU::ORv4i32_i32: 120 case SPU::ORv2i64_i64: 121 case SPU::ORv4f32_f32: 122 case SPU::ORv2f64_f64: 123 case SPU::ORi8_v16i8: 124 case SPU::ORi16_v8i16: 125 case SPU::ORi32_v4i32: 126 case SPU::ORi64_v2i64: 127 case SPU::ORf32_v4f32: 128 case SPU::ORf64_v2f64: 129/* 130 case SPU::ORi128_r64: 131 case SPU::ORi128_f64: 132 case SPU::ORi128_r32: 133 case SPU::ORi128_f32: 134 case SPU::ORi128_r16: 135 case SPU::ORi128_r8: 136 case SPU::ORi128_vec: 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 case SPU::ORvec_i128: 144*/ 145/* 146 case SPU::ORr16_r32: 147 case SPU::ORr8_r32: 148 case SPU::ORr32_r16: 149 case SPU::ORr32_r8: 150 case SPU::ORr16_r64: 151 case SPU::ORr8_r64: 152 case SPU::ORr64_r16: 153 case SPU::ORr64_r8: 154*/ 155 case SPU::ORr64_r32: 156 case SPU::ORr32_r64: 157 case SPU::ORf32_r32: 158 case SPU::ORr32_f32: 159 case SPU::ORf64_r64: 160 case SPU::ORr64_f64: { 161 assert(MI.getNumOperands() == 2 && 162 MI.getOperand(0).isReg() && 163 MI.getOperand(1).isReg() && 164 "invalid SPU OR<type>_<vec> or LR instruction!"); 165 if (MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { 166 sourceReg = MI.getOperand(0).getReg(); 167 destReg = MI.getOperand(0).getReg(); 168 return true; 169 } 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::ORf32: 181 case SPU::ORf64: 182 assert(MI.getNumOperands() == 3 && 183 MI.getOperand(0).isReg() && 184 MI.getOperand(1).isReg() && 185 MI.getOperand(2).isReg() && 186 "invalid SPU OR(vec|r32|r64|gprc) instruction!"); 187 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { 188 sourceReg = MI.getOperand(1).getReg(); 189 destReg = MI.getOperand(0).getReg(); 190 return true; 191 } 192 break; 193 } 194 195 return false; 196} 197 198unsigned 199SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 200 int &FrameIndex) const { 201 switch (MI->getOpcode()) { 202 default: break; 203 case SPU::LQDv16i8: 204 case SPU::LQDv8i16: 205 case SPU::LQDv4i32: 206 case SPU::LQDv4f32: 207 case SPU::LQDv2f64: 208 case SPU::LQDr128: 209 case SPU::LQDr64: 210 case SPU::LQDr32: 211 case SPU::LQDr16: { 212 const MachineOperand MOp1 = MI->getOperand(1); 213 const MachineOperand MOp2 = MI->getOperand(2); 214 if (MOp1.isImm() && MOp2.isFI()) { 215 FrameIndex = MOp2.getIndex(); 216 return MI->getOperand(0).getReg(); 217 } 218 break; 219 } 220 } 221 return 0; 222} 223 224unsigned 225SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 226 int &FrameIndex) const { 227 switch (MI->getOpcode()) { 228 default: break; 229 case SPU::STQDv16i8: 230 case SPU::STQDv8i16: 231 case SPU::STQDv4i32: 232 case SPU::STQDv4f32: 233 case SPU::STQDv2f64: 234 case SPU::STQDr128: 235 case SPU::STQDr64: 236 case SPU::STQDr32: 237 case SPU::STQDr16: 238 case SPU::STQDr8: { 239 const MachineOperand MOp1 = MI->getOperand(1); 240 const MachineOperand MOp2 = MI->getOperand(2); 241 if (MOp1.isImm() && MOp2.isFI()) { 242 FrameIndex = MOp2.getIndex(); 243 return MI->getOperand(0).getReg(); 244 } 245 break; 246 } 247 } 248 return 0; 249} 250 251bool SPUInstrInfo::copyRegToReg(MachineBasicBlock &MBB, 252 MachineBasicBlock::iterator MI, 253 unsigned DestReg, unsigned SrcReg, 254 const TargetRegisterClass *DestRC, 255 const TargetRegisterClass *SrcRC) 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 if (DestRC == SPU::R8CRegisterClass) { 263 BuildMI(MBB, MI, get(SPU::LRr8), DestReg).addReg(SrcReg); 264 } else if (DestRC == SPU::R16CRegisterClass) { 265 BuildMI(MBB, MI, get(SPU::LRr16), DestReg).addReg(SrcReg); 266 } else if (DestRC == SPU::R32CRegisterClass) { 267 BuildMI(MBB, MI, get(SPU::LRr32), DestReg).addReg(SrcReg); 268 } else if (DestRC == SPU::R32FPRegisterClass) { 269 BuildMI(MBB, MI, get(SPU::LRf32), DestReg).addReg(SrcReg); 270 } else if (DestRC == SPU::R64CRegisterClass) { 271 BuildMI(MBB, MI, get(SPU::LRr64), DestReg).addReg(SrcReg); 272 } else if (DestRC == SPU::R64FPRegisterClass) { 273 BuildMI(MBB, MI, get(SPU::LRf64), DestReg).addReg(SrcReg); 274 } else if (DestRC == SPU::GPRCRegisterClass) { 275 BuildMI(MBB, MI, get(SPU::LRr128), DestReg).addReg(SrcReg); 276 } else if (DestRC == SPU::VECREGRegisterClass) { 277 BuildMI(MBB, MI, get(SPU::LRv16i8), DestReg).addReg(SrcReg); 278 } else { 279 // Attempt to copy unknown/unsupported register class! 280 return false; 281 } 282 283 return true; 284} 285 286void 287SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 288 MachineBasicBlock::iterator MI, 289 unsigned SrcReg, bool isKill, int FrameIdx, 290 const TargetRegisterClass *RC) const 291{ 292 unsigned opc; 293 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 294 if (RC == SPU::GPRCRegisterClass) { 295 opc = (isValidFrameIdx ? SPU::STQDr128 : SPU::STQXr128); 296 } else if (RC == SPU::R64CRegisterClass) { 297 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 298 } else if (RC == SPU::R64FPRegisterClass) { 299 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 300 } else if (RC == SPU::R32CRegisterClass) { 301 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 302 } else if (RC == SPU::R32FPRegisterClass) { 303 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 304 } else if (RC == SPU::R16CRegisterClass) { 305 opc = (isValidFrameIdx ? SPU::STQDr16 : SPU::STQXr16); 306 } else if (RC == SPU::R8CRegisterClass) { 307 opc = (isValidFrameIdx ? SPU::STQDr8 : SPU::STQXr8); 308 } else if (RC == SPU::VECREGRegisterClass) { 309 opc = (isValidFrameIdx) ? SPU::STQDv16i8 : SPU::STQXv16i8; 310 } else { 311 assert(0 && "Unknown regclass!"); 312 abort(); 313 } 314 315 addFrameReference(BuildMI(MBB, MI, get(opc)) 316 .addReg(SrcReg, false, false, isKill), FrameIdx); 317} 318 319void SPUInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, 320 bool isKill, 321 SmallVectorImpl<MachineOperand> &Addr, 322 const TargetRegisterClass *RC, 323 SmallVectorImpl<MachineInstr*> &NewMIs) const { 324 cerr << "storeRegToAddr() invoked!\n"; 325 abort(); 326 327 if (Addr[0].isFI()) { 328 /* do what storeRegToStackSlot does here */ 329 } else { 330 unsigned Opc = 0; 331 if (RC == SPU::GPRCRegisterClass) { 332 /* Opc = PPC::STW; */ 333 } else if (RC == SPU::R16CRegisterClass) { 334 /* Opc = PPC::STD; */ 335 } else if (RC == SPU::R32CRegisterClass) { 336 /* Opc = PPC::STFD; */ 337 } else if (RC == SPU::R32FPRegisterClass) { 338 /* Opc = PPC::STFD; */ 339 } else if (RC == SPU::R64FPRegisterClass) { 340 /* Opc = PPC::STFS; */ 341 } else if (RC == SPU::VECREGRegisterClass) { 342 /* Opc = PPC::STVX; */ 343 } else { 344 assert(0 && "Unknown regclass!"); 345 abort(); 346 } 347 MachineInstrBuilder MIB = BuildMI(MF, get(Opc)) 348 .addReg(SrcReg, false, false, isKill); 349 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 350 MachineOperand &MO = Addr[i]; 351 if (MO.isReg()) 352 MIB.addReg(MO.getReg()); 353 else if (MO.isImm()) 354 MIB.addImm(MO.getImm()); 355 else 356 MIB.addFrameIndex(MO.getIndex()); 357 } 358 NewMIs.push_back(MIB); 359 } 360} 361 362void 363SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 364 MachineBasicBlock::iterator MI, 365 unsigned DestReg, int FrameIdx, 366 const TargetRegisterClass *RC) const 367{ 368 unsigned opc; 369 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 370 if (RC == SPU::GPRCRegisterClass) { 371 opc = (isValidFrameIdx ? SPU::LQDr128 : SPU::LQXr128); 372 } else if (RC == SPU::R64CRegisterClass) { 373 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 374 } else if (RC == SPU::R64FPRegisterClass) { 375 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 376 } else if (RC == SPU::R32CRegisterClass) { 377 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 378 } else if (RC == SPU::R32FPRegisterClass) { 379 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 380 } else if (RC == SPU::R16CRegisterClass) { 381 opc = (isValidFrameIdx ? SPU::LQDr16 : SPU::LQXr16); 382 } else if (RC == SPU::R8CRegisterClass) { 383 opc = (isValidFrameIdx ? SPU::LQDr8 : SPU::LQXr8); 384 } else if (RC == SPU::VECREGRegisterClass) { 385 opc = (isValidFrameIdx) ? SPU::LQDv16i8 : SPU::LQXv16i8; 386 } else { 387 assert(0 && "Unknown regclass in loadRegFromStackSlot!"); 388 abort(); 389 } 390 391 addFrameReference(BuildMI(MBB, MI, get(opc)).addReg(DestReg), FrameIdx); 392} 393 394/*! 395 \note We are really pessimistic here about what kind of a load we're doing. 396 */ 397void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, 398 SmallVectorImpl<MachineOperand> &Addr, 399 const TargetRegisterClass *RC, 400 SmallVectorImpl<MachineInstr*> &NewMIs) 401 const { 402 cerr << "loadRegToAddr() invoked!\n"; 403 abort(); 404 405 if (Addr[0].isFI()) { 406 /* do what loadRegFromStackSlot does here... */ 407 } else { 408 unsigned Opc = 0; 409 if (RC == SPU::R8CRegisterClass) { 410 /* do brilliance here */ 411 } else if (RC == SPU::R16CRegisterClass) { 412 /* Opc = PPC::LWZ; */ 413 } else if (RC == SPU::R32CRegisterClass) { 414 /* Opc = PPC::LD; */ 415 } else if (RC == SPU::R32FPRegisterClass) { 416 /* Opc = PPC::LFD; */ 417 } else if (RC == SPU::R64FPRegisterClass) { 418 /* Opc = PPC::LFS; */ 419 } else if (RC == SPU::VECREGRegisterClass) { 420 /* Opc = PPC::LVX; */ 421 } else if (RC == SPU::GPRCRegisterClass) { 422 /* Opc = something else! */ 423 } else { 424 assert(0 && "Unknown regclass!"); 425 abort(); 426 } 427 MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); 428 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 429 MachineOperand &MO = Addr[i]; 430 if (MO.isReg()) 431 MIB.addReg(MO.getReg()); 432 else if (MO.isImm()) 433 MIB.addImm(MO.getImm()); 434 else 435 MIB.addFrameIndex(MO.getIndex()); 436 } 437 NewMIs.push_back(MIB); 438 } 439} 440 441//! Return true if the specified load or store can be folded 442bool 443SPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 444 const SmallVectorImpl<unsigned> &Ops) const { 445 if (Ops.size() != 1) return false; 446 447 // Make sure this is a reg-reg copy. 448 unsigned Opc = MI->getOpcode(); 449 450 switch (Opc) { 451 case SPU::ORv16i8: 452 case SPU::ORv8i16: 453 case SPU::ORv4i32: 454 case SPU::ORv2i64: 455 case SPU::ORr8: 456 case SPU::ORr16: 457 case SPU::ORr32: 458 case SPU::ORr64: 459 case SPU::ORf32: 460 case SPU::ORf64: 461 if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) 462 return true; 463 break; 464 } 465 466 return false; 467} 468 469/// foldMemoryOperand - SPU, like PPC, can only fold spills into 470/// copy instructions, turning them into load/store instructions. 471MachineInstr * 472SPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 473 MachineInstr *MI, 474 const SmallVectorImpl<unsigned> &Ops, 475 int FrameIndex) const 476{ 477 if (Ops.size() != 1) return 0; 478 479 unsigned OpNum = Ops[0]; 480 unsigned Opc = MI->getOpcode(); 481 MachineInstr *NewMI = 0; 482 483 switch (Opc) { 484 case SPU::ORv16i8: 485 case SPU::ORv8i16: 486 case SPU::ORv4i32: 487 case SPU::ORv2i64: 488 case SPU::ORr8: 489 case SPU::ORr16: 490 case SPU::ORr32: 491 case SPU::ORr64: 492 case SPU::ORf32: 493 case SPU::ORf64: 494 if (OpNum == 0) { // move -> store 495 unsigned InReg = MI->getOperand(1).getReg(); 496 bool isKill = MI->getOperand(1).isKill(); 497 if (FrameIndex < SPUFrameInfo::maxFrameOffset()) { 498 MachineInstrBuilder MIB = BuildMI(MF, get(SPU::STQDr32)); 499 500 MIB.addReg(InReg, false, false, isKill); 501 NewMI = addFrameReference(MIB, FrameIndex); 502 } 503 } else { // move -> load 504 unsigned OutReg = MI->getOperand(0).getReg(); 505 bool isDead = MI->getOperand(0).isDead(); 506 MachineInstrBuilder MIB = BuildMI(MF, get(Opc)); 507 508 MIB.addReg(OutReg, true, false, false, isDead); 509 Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset()) 510 ? SPU::STQDr32 : SPU::STQXr32; 511 NewMI = addFrameReference(MIB, FrameIndex); 512 break; 513 } 514 } 515 516 return NewMI; 517} 518 519//! Branch analysis 520/*! 521 \note This code was kiped from PPC. There may be more branch analysis for 522 CellSPU than what's currently done here. 523 */ 524bool 525SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 526 MachineBasicBlock *&FBB, 527 SmallVectorImpl<MachineOperand> &Cond, 528 bool AllowModify) const { 529 // If the block has no terminators, it just falls into the block after it. 530 MachineBasicBlock::iterator I = MBB.end(); 531 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) 532 return false; 533 534 // Get the last instruction in the block. 535 MachineInstr *LastInst = I; 536 537 // If there is only one terminator instruction, process it. 538 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 539 if (isUncondBranch(LastInst)) { 540 TBB = LastInst->getOperand(0).getMBB(); 541 return false; 542 } else if (isCondBranch(LastInst)) { 543 // Block ends with fall-through condbranch. 544 TBB = LastInst->getOperand(1).getMBB(); 545 DEBUG(cerr << "Pushing LastInst: "); 546 DEBUG(LastInst->dump()); 547 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 548 Cond.push_back(LastInst->getOperand(0)); 549 return false; 550 } 551 // Otherwise, don't know what this is. 552 return true; 553 } 554 555 // Get the instruction before it if it's a terminator. 556 MachineInstr *SecondLastInst = I; 557 558 // If there are three terminators, we don't know what sort of block this is. 559 if (SecondLastInst && I != MBB.begin() && 560 isUnpredicatedTerminator(--I)) 561 return true; 562 563 // If the block ends with a conditional and unconditional branch, handle it. 564 if (isCondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 565 TBB = SecondLastInst->getOperand(1).getMBB(); 566 DEBUG(cerr << "Pushing SecondLastInst: "); 567 DEBUG(SecondLastInst->dump()); 568 Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 569 Cond.push_back(SecondLastInst->getOperand(0)); 570 FBB = LastInst->getOperand(0).getMBB(); 571 return false; 572 } 573 574 // If the block ends with two unconditional branches, handle it. The second 575 // one is not executed, so remove it. 576 if (isUncondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 577 TBB = SecondLastInst->getOperand(0).getMBB(); 578 I = LastInst; 579 if (AllowModify) 580 I->eraseFromParent(); 581 return false; 582 } 583 584 // Otherwise, can't handle this. 585 return true; 586} 587 588unsigned 589SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 590 MachineBasicBlock::iterator I = MBB.end(); 591 if (I == MBB.begin()) 592 return 0; 593 --I; 594 if (!isCondBranch(I) && !isUncondBranch(I)) 595 return 0; 596 597 // Remove the first branch. 598 DEBUG(cerr << "Removing branch: "); 599 DEBUG(I->dump()); 600 I->eraseFromParent(); 601 I = MBB.end(); 602 if (I == MBB.begin()) 603 return 1; 604 605 --I; 606 if (!(isCondBranch(I) || isUncondBranch(I))) 607 return 1; 608 609 // Remove the second branch. 610 DEBUG(cerr << "Removing second branch: "); 611 DEBUG(I->dump()); 612 I->eraseFromParent(); 613 return 2; 614} 615 616unsigned 617SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 618 MachineBasicBlock *FBB, 619 const SmallVectorImpl<MachineOperand> &Cond) const { 620 // Shouldn't be a fall through. 621 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 622 assert((Cond.size() == 2 || Cond.size() == 0) && 623 "SPU branch conditions have two components!"); 624 625 // One-way branch. 626 if (FBB == 0) { 627 if (Cond.empty()) { 628 // Unconditional branch 629 MachineInstrBuilder MIB = BuildMI(&MBB, get(SPU::BR)); 630 MIB.addMBB(TBB); 631 632 DEBUG(cerr << "Inserted one-way uncond branch: "); 633 DEBUG((*MIB).dump()); 634 } else { 635 // Conditional branch 636 MachineInstrBuilder MIB = BuildMI(&MBB, get(Cond[0].getImm())); 637 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 638 639 DEBUG(cerr << "Inserted one-way cond branch: "); 640 DEBUG((*MIB).dump()); 641 } 642 return 1; 643 } else { 644 MachineInstrBuilder MIB = BuildMI(&MBB, get(Cond[0].getImm())); 645 MachineInstrBuilder MIB2 = BuildMI(&MBB, get(SPU::BR)); 646 647 // Two-way Conditional Branch. 648 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 649 MIB2.addMBB(FBB); 650 651 DEBUG(cerr << "Inserted conditional branch: "); 652 DEBUG((*MIB).dump()); 653 DEBUG(cerr << "part 2: "); 654 DEBUG((*MIB2).dump()); 655 return 2; 656 } 657} 658 659bool 660SPUInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { 661 return (!MBB.empty() && isUncondBranch(&MBB.back())); 662} 663//! Reverses a branch's condition, returning false on success. 664bool 665SPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) 666 const { 667 // Pretty brainless way of inverting the condition, but it works, considering 668 // there are only two conditions... 669 static struct { 670 unsigned Opc; //! The incoming opcode 671 unsigned RevCondOpc; //! The reversed condition opcode 672 } revconds[] = { 673 { SPU::BRNZr32, SPU::BRZr32 }, 674 { SPU::BRNZv4i32, SPU::BRZv4i32 }, 675 { SPU::BRZr32, SPU::BRNZr32 }, 676 { SPU::BRZv4i32, SPU::BRNZv4i32 }, 677 { SPU::BRHNZr16, SPU::BRHZr16 }, 678 { SPU::BRHNZv8i16, SPU::BRHZv8i16 }, 679 { SPU::BRHZr16, SPU::BRHNZr16 }, 680 { SPU::BRHZv8i16, SPU::BRHNZv8i16 } 681 }; 682 683 unsigned Opc = unsigned(Cond[0].getImm()); 684 // Pretty dull mapping between the two conditions that SPU can generate: 685 for (int i = sizeof(revconds)/sizeof(revconds[0]) - 1; i >= 0; --i) { 686 if (revconds[i].Opc == Opc) { 687 Cond[0].setImm(revconds[i].RevCondOpc); 688 return false; 689 } 690 } 691 692 return true; 693} 694