LLVM API Documentation
00001 //===- SPUInstrInfo.cpp - Cell SPU Instruction Information ----------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains the Cell SPU implementation of the TargetInstrInfo class. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "SPURegisterNames.h" 00015 #include "SPUInstrInfo.h" 00016 #include "SPUInstrBuilder.h" 00017 #include "SPUTargetMachine.h" 00018 #include "SPUGenInstrInfo.inc" 00019 #include "llvm/CodeGen/MachineInstrBuilder.h" 00020 #include "llvm/Support/Streams.h" 00021 #include "llvm/Support/Debug.h" 00022 00023 using namespace llvm; 00024 00025 namespace { 00026 //! Predicate for an unconditional branch instruction 00027 inline bool isUncondBranch(const MachineInstr *I) { 00028 unsigned opc = I->getOpcode(); 00029 00030 return (opc == SPU::BR 00031 || opc == SPU::BRA 00032 || opc == SPU::BI); 00033 } 00034 00035 //! Predicate for a conditional branch instruction 00036 inline bool isCondBranch(const MachineInstr *I) { 00037 unsigned opc = I->getOpcode(); 00038 00039 return (opc == SPU::BRNZr32 00040 || opc == SPU::BRNZv4i32 00041 || opc == SPU::BRZr32 00042 || opc == SPU::BRZv4i32 00043 || opc == SPU::BRHNZr16 00044 || opc == SPU::BRHNZv8i16 00045 || opc == SPU::BRHZr16 00046 || opc == SPU::BRHZv8i16); 00047 } 00048 } 00049 00050 SPUInstrInfo::SPUInstrInfo(SPUTargetMachine &tm) 00051 : TargetInstrInfoImpl(SPUInsts, sizeof(SPUInsts)/sizeof(SPUInsts[0])), 00052 TM(tm), 00053 RI(*TM.getSubtargetImpl(), *this) 00054 { /* NOP */ } 00055 00056 /// getPointerRegClass - Return the register class to use to hold pointers. 00057 /// This is used for addressing modes. 00058 const TargetRegisterClass * 00059 SPUInstrInfo::getPointerRegClass() const 00060 { 00061 return &SPU::R32CRegClass; 00062 } 00063 00064 bool 00065 SPUInstrInfo::isMoveInstr(const MachineInstr& MI, 00066 unsigned& sourceReg, 00067 unsigned& destReg, 00068 unsigned& SrcSR, unsigned& DstSR) const { 00069 SrcSR = DstSR = 0; // No sub-registers. 00070 00071 // Primarily, ORI and OR are generated by copyRegToReg. But, there are other 00072 // cases where we can safely say that what's being done is really a move 00073 // (see how PowerPC does this -- it's the model for this code too.) 00074 switch (MI.getOpcode()) { 00075 default: 00076 break; 00077 case SPU::ORIv4i32: 00078 case SPU::ORIr32: 00079 case SPU::ORHIv8i16: 00080 case SPU::ORHIr16: 00081 case SPU::ORHIi8i16: 00082 case SPU::ORBIv16i8: 00083 case SPU::ORBIr8: 00084 case SPU::ORIi16i32: 00085 case SPU::ORIi8i32: 00086 case SPU::AHIvec: 00087 case SPU::AHIr16: 00088 case SPU::AIv4i32: 00089 assert(MI.getNumOperands() == 3 && 00090 MI.getOperand(0).isReg() && 00091 MI.getOperand(1).isReg() && 00092 MI.getOperand(2).isImm() && 00093 "invalid SPU ORI/ORHI/ORBI/AHI/AI/SFI/SFHI instruction!"); 00094 if (MI.getOperand(2).getImm() == 0) { 00095 sourceReg = MI.getOperand(1).getReg(); 00096 destReg = MI.getOperand(0).getReg(); 00097 return true; 00098 } 00099 break; 00100 case SPU::AIr32: 00101 assert(MI.getNumOperands() == 3 && 00102 "wrong number of operands to AIr32"); 00103 if (MI.getOperand(0).isReg() && 00104 MI.getOperand(1).isReg() && 00105 (MI.getOperand(2).isImm() && 00106 MI.getOperand(2).getImm() == 0)) { 00107 sourceReg = MI.getOperand(1).getReg(); 00108 destReg = MI.getOperand(0).getReg(); 00109 return true; 00110 } 00111 break; 00112 case SPU::LRr8: 00113 case SPU::LRr16: 00114 case SPU::LRr32: 00115 case SPU::LRf32: 00116 case SPU::LRr64: 00117 case SPU::LRf64: 00118 case SPU::LRr128: 00119 case SPU::LRv16i8: 00120 case SPU::LRv8i16: 00121 case SPU::LRv4i32: 00122 case SPU::LRv4f32: 00123 case SPU::LRv2i64: 00124 case SPU::LRv2f64: 00125 case SPU::ORv16i8_i8: 00126 case SPU::ORv8i16_i16: 00127 case SPU::ORv4i32_i32: 00128 case SPU::ORv2i64_i64: 00129 case SPU::ORv4f32_f32: 00130 case SPU::ORv2f64_f64: 00131 case SPU::ORi8_v16i8: 00132 case SPU::ORi16_v8i16: 00133 case SPU::ORi32_v4i32: 00134 case SPU::ORi64_v2i64: 00135 case SPU::ORf32_v4f32: 00136 case SPU::ORf64_v2f64: 00137 /* 00138 case SPU::ORi128_r64: 00139 case SPU::ORi128_f64: 00140 case SPU::ORi128_r32: 00141 case SPU::ORi128_f32: 00142 case SPU::ORi128_r16: 00143 case SPU::ORi128_r8: 00144 case SPU::ORi128_vec: 00145 case SPU::ORr64_i128: 00146 case SPU::ORf64_i128: 00147 case SPU::ORr32_i128: 00148 case SPU::ORf32_i128: 00149 case SPU::ORr16_i128: 00150 case SPU::ORr8_i128: 00151 case SPU::ORvec_i128: 00152 */ 00153 /* 00154 case SPU::ORr16_r32: 00155 case SPU::ORr8_r32: 00156 case SPU::ORr32_r16: 00157 case SPU::ORr32_r8: 00158 case SPU::ORr16_r64: 00159 case SPU::ORr8_r64: 00160 case SPU::ORr64_r16: 00161 case SPU::ORr64_r8: 00162 */ 00163 case SPU::ORr64_r32: 00164 case SPU::ORr32_r64: 00165 case SPU::ORf32_r32: 00166 case SPU::ORr32_f32: 00167 case SPU::ORf64_r64: 00168 case SPU::ORr64_f64: { 00169 assert(MI.getNumOperands() == 2 && 00170 MI.getOperand(0).isReg() && 00171 MI.getOperand(1).isReg() && 00172 "invalid SPU OR<type>_<vec> or LR instruction!"); 00173 if (MI.getOperand(0).getReg() == MI.getOperand(1).getReg()) { 00174 sourceReg = MI.getOperand(0).getReg(); 00175 destReg = MI.getOperand(0).getReg(); 00176 return true; 00177 } 00178 break; 00179 } 00180 case SPU::ORv16i8: 00181 case SPU::ORv8i16: 00182 case SPU::ORv4i32: 00183 case SPU::ORv2i64: 00184 case SPU::ORr8: 00185 case SPU::ORr16: 00186 case SPU::ORr32: 00187 case SPU::ORr64: 00188 case SPU::ORf32: 00189 case SPU::ORf64: 00190 assert(MI.getNumOperands() == 3 && 00191 MI.getOperand(0).isReg() && 00192 MI.getOperand(1).isReg() && 00193 MI.getOperand(2).isReg() && 00194 "invalid SPU OR(vec|r32|r64|gprc) instruction!"); 00195 if (MI.getOperand(1).getReg() == MI.getOperand(2).getReg()) { 00196 sourceReg = MI.getOperand(1).getReg(); 00197 destReg = MI.getOperand(0).getReg(); 00198 return true; 00199 } 00200 break; 00201 } 00202 00203 return false; 00204 } 00205 00206 unsigned 00207 SPUInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, 00208 int &FrameIndex) const { 00209 switch (MI->getOpcode()) { 00210 default: break; 00211 case SPU::LQDv16i8: 00212 case SPU::LQDv8i16: 00213 case SPU::LQDv4i32: 00214 case SPU::LQDv4f32: 00215 case SPU::LQDv2f64: 00216 case SPU::LQDr128: 00217 case SPU::LQDr64: 00218 case SPU::LQDr32: 00219 case SPU::LQDr16: { 00220 const MachineOperand MOp1 = MI->getOperand(1); 00221 const MachineOperand MOp2 = MI->getOperand(2); 00222 if (MOp1.isImm() && MOp2.isFI()) { 00223 FrameIndex = MOp2.getIndex(); 00224 return MI->getOperand(0).getReg(); 00225 } 00226 break; 00227 } 00228 } 00229 return 0; 00230 } 00231 00232 unsigned 00233 SPUInstrInfo::isStoreToStackSlot(const MachineInstr *MI, 00234 int &FrameIndex) const { 00235 switch (MI->getOpcode()) { 00236 default: break; 00237 case SPU::STQDv16i8: 00238 case SPU::STQDv8i16: 00239 case SPU::STQDv4i32: 00240 case SPU::STQDv4f32: 00241 case SPU::STQDv2f64: 00242 case SPU::STQDr128: 00243 case SPU::STQDr64: 00244 case SPU::STQDr32: 00245 case SPU::STQDr16: 00246 case SPU::STQDr8: { 00247 const MachineOperand MOp1 = MI->getOperand(1); 00248 const MachineOperand MOp2 = MI->getOperand(2); 00249 if (MOp1.isImm() && MOp2.isFI()) { 00250 FrameIndex = MOp2.getIndex(); 00251 return MI->getOperand(0).getReg(); 00252 } 00253 break; 00254 } 00255 } 00256 return 0; 00257 } 00258 00259 bool SPUInstrInfo::copyRegToReg(MachineBasicBlock &MBB, 00260 MachineBasicBlock::iterator MI, 00261 unsigned DestReg, unsigned SrcReg, 00262 const TargetRegisterClass *DestRC, 00263 const TargetRegisterClass *SrcRC) const 00264 { 00265 // We support cross register class moves for our aliases, such as R3 in any 00266 // reg class to any other reg class containing R3. This is required because 00267 // we instruction select bitconvert i64 -> f64 as a noop for example, so our 00268 // types have no specific meaning. 00269 00270 if (DestRC == SPU::R8CRegisterClass) { 00271 BuildMI(MBB, MI, get(SPU::LRr8), DestReg).addReg(SrcReg); 00272 } else if (DestRC == SPU::R16CRegisterClass) { 00273 BuildMI(MBB, MI, get(SPU::LRr16), DestReg).addReg(SrcReg); 00274 } else if (DestRC == SPU::R32CRegisterClass) { 00275 BuildMI(MBB, MI, get(SPU::LRr32), DestReg).addReg(SrcReg); 00276 } else if (DestRC == SPU::R32FPRegisterClass) { 00277 BuildMI(MBB, MI, get(SPU::LRf32), DestReg).addReg(SrcReg); 00278 } else if (DestRC == SPU::R64CRegisterClass) { 00279 BuildMI(MBB, MI, get(SPU::LRr64), DestReg).addReg(SrcReg); 00280 } else if (DestRC == SPU::R64FPRegisterClass) { 00281 BuildMI(MBB, MI, get(SPU::LRf64), DestReg).addReg(SrcReg); 00282 } else if (DestRC == SPU::GPRCRegisterClass) { 00283 BuildMI(MBB, MI, get(SPU::LRr128), DestReg).addReg(SrcReg); 00284 } else if (DestRC == SPU::VECREGRegisterClass) { 00285 BuildMI(MBB, MI, get(SPU::LRv16i8), DestReg).addReg(SrcReg); 00286 } else { 00287 // Attempt to copy unknown/unsupported register class! 00288 return false; 00289 } 00290 00291 return true; 00292 } 00293 00294 void 00295 SPUInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, 00296 MachineBasicBlock::iterator MI, 00297 unsigned SrcReg, bool isKill, int FrameIdx, 00298 const TargetRegisterClass *RC) const 00299 { 00300 unsigned opc; 00301 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 00302 if (RC == SPU::GPRCRegisterClass) { 00303 opc = (isValidFrameIdx ? SPU::STQDr128 : SPU::STQXr128); 00304 } else if (RC == SPU::R64CRegisterClass) { 00305 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 00306 } else if (RC == SPU::R64FPRegisterClass) { 00307 opc = (isValidFrameIdx ? SPU::STQDr64 : SPU::STQXr64); 00308 } else if (RC == SPU::R32CRegisterClass) { 00309 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 00310 } else if (RC == SPU::R32FPRegisterClass) { 00311 opc = (isValidFrameIdx ? SPU::STQDr32 : SPU::STQXr32); 00312 } else if (RC == SPU::R16CRegisterClass) { 00313 opc = (isValidFrameIdx ? SPU::STQDr16 : SPU::STQXr16); 00314 } else if (RC == SPU::R8CRegisterClass) { 00315 opc = (isValidFrameIdx ? SPU::STQDr8 : SPU::STQXr8); 00316 } else if (RC == SPU::VECREGRegisterClass) { 00317 opc = (isValidFrameIdx) ? SPU::STQDv16i8 : SPU::STQXv16i8; 00318 } else { 00319 assert(0 && "Unknown regclass!"); 00320 abort(); 00321 } 00322 00323 addFrameReference(BuildMI(MBB, MI, get(opc)) 00324 .addReg(SrcReg, false, false, isKill), FrameIdx); 00325 } 00326 00327 void SPUInstrInfo::storeRegToAddr(MachineFunction &MF, unsigned SrcReg, 00328 bool isKill, 00329 SmallVectorImpl<MachineOperand> &Addr, 00330 const TargetRegisterClass *RC, 00331 SmallVectorImpl<MachineInstr*> &NewMIs) const { 00332 cerr << "storeRegToAddr() invoked!\n"; 00333 abort(); 00334 00335 if (Addr[0].isFI()) { 00336 /* do what storeRegToStackSlot does here */ 00337 } else { 00338 unsigned Opc = 0; 00339 if (RC == SPU::GPRCRegisterClass) { 00340 /* Opc = PPC::STW; */ 00341 } else if (RC == SPU::R16CRegisterClass) { 00342 /* Opc = PPC::STD; */ 00343 } else if (RC == SPU::R32CRegisterClass) { 00344 /* Opc = PPC::STFD; */ 00345 } else if (RC == SPU::R32FPRegisterClass) { 00346 /* Opc = PPC::STFD; */ 00347 } else if (RC == SPU::R64FPRegisterClass) { 00348 /* Opc = PPC::STFS; */ 00349 } else if (RC == SPU::VECREGRegisterClass) { 00350 /* Opc = PPC::STVX; */ 00351 } else { 00352 assert(0 && "Unknown regclass!"); 00353 abort(); 00354 } 00355 MachineInstrBuilder MIB = BuildMI(MF, get(Opc)) 00356 .addReg(SrcReg, false, false, isKill); 00357 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 00358 MachineOperand &MO = Addr[i]; 00359 if (MO.isReg()) 00360 MIB.addReg(MO.getReg()); 00361 else if (MO.isImm()) 00362 MIB.addImm(MO.getImm()); 00363 else 00364 MIB.addFrameIndex(MO.getIndex()); 00365 } 00366 NewMIs.push_back(MIB); 00367 } 00368 } 00369 00370 void 00371 SPUInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, 00372 MachineBasicBlock::iterator MI, 00373 unsigned DestReg, int FrameIdx, 00374 const TargetRegisterClass *RC) const 00375 { 00376 unsigned opc; 00377 bool isValidFrameIdx = (FrameIdx < SPUFrameInfo::maxFrameOffset()); 00378 if (RC == SPU::GPRCRegisterClass) { 00379 opc = (isValidFrameIdx ? SPU::LQDr128 : SPU::LQXr128); 00380 } else if (RC == SPU::R64CRegisterClass) { 00381 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 00382 } else if (RC == SPU::R64FPRegisterClass) { 00383 opc = (isValidFrameIdx ? SPU::LQDr64 : SPU::LQXr64); 00384 } else if (RC == SPU::R32CRegisterClass) { 00385 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 00386 } else if (RC == SPU::R32FPRegisterClass) { 00387 opc = (isValidFrameIdx ? SPU::LQDr32 : SPU::LQXr32); 00388 } else if (RC == SPU::R16CRegisterClass) { 00389 opc = (isValidFrameIdx ? SPU::LQDr16 : SPU::LQXr16); 00390 } else if (RC == SPU::R8CRegisterClass) { 00391 opc = (isValidFrameIdx ? SPU::LQDr8 : SPU::LQXr8); 00392 } else if (RC == SPU::VECREGRegisterClass) { 00393 opc = (isValidFrameIdx) ? SPU::LQDv16i8 : SPU::LQXv16i8; 00394 } else { 00395 assert(0 && "Unknown regclass in loadRegFromStackSlot!"); 00396 abort(); 00397 } 00398 00399 addFrameReference(BuildMI(MBB, MI, get(opc)).addReg(DestReg), FrameIdx); 00400 } 00401 00402 /*! 00403 \note We are really pessimistic here about what kind of a load we're doing. 00404 */ 00405 void SPUInstrInfo::loadRegFromAddr(MachineFunction &MF, unsigned DestReg, 00406 SmallVectorImpl<MachineOperand> &Addr, 00407 const TargetRegisterClass *RC, 00408 SmallVectorImpl<MachineInstr*> &NewMIs) 00409 const { 00410 cerr << "loadRegToAddr() invoked!\n"; 00411 abort(); 00412 00413 if (Addr[0].isFI()) { 00414 /* do what loadRegFromStackSlot does here... */ 00415 } else { 00416 unsigned Opc = 0; 00417 if (RC == SPU::R8CRegisterClass) { 00418 /* do brilliance here */ 00419 } else if (RC == SPU::R16CRegisterClass) { 00420 /* Opc = PPC::LWZ; */ 00421 } else if (RC == SPU::R32CRegisterClass) { 00422 /* Opc = PPC::LD; */ 00423 } else if (RC == SPU::R32FPRegisterClass) { 00424 /* Opc = PPC::LFD; */ 00425 } else if (RC == SPU::R64FPRegisterClass) { 00426 /* Opc = PPC::LFS; */ 00427 } else if (RC == SPU::VECREGRegisterClass) { 00428 /* Opc = PPC::LVX; */ 00429 } else if (RC == SPU::GPRCRegisterClass) { 00430 /* Opc = something else! */ 00431 } else { 00432 assert(0 && "Unknown regclass!"); 00433 abort(); 00434 } 00435 MachineInstrBuilder MIB = BuildMI(MF, get(Opc), DestReg); 00436 for (unsigned i = 0, e = Addr.size(); i != e; ++i) { 00437 MachineOperand &MO = Addr[i]; 00438 if (MO.isReg()) 00439 MIB.addReg(MO.getReg()); 00440 else if (MO.isImm()) 00441 MIB.addImm(MO.getImm()); 00442 else 00443 MIB.addFrameIndex(MO.getIndex()); 00444 } 00445 NewMIs.push_back(MIB); 00446 } 00447 } 00448 00449 //! Return true if the specified load or store can be folded 00450 bool 00451 SPUInstrInfo::canFoldMemoryOperand(const MachineInstr *MI, 00452 const SmallVectorImpl<unsigned> &Ops) const { 00453 if (Ops.size() != 1) return false; 00454 00455 // Make sure this is a reg-reg copy. 00456 unsigned Opc = MI->getOpcode(); 00457 00458 switch (Opc) { 00459 case SPU::ORv16i8: 00460 case SPU::ORv8i16: 00461 case SPU::ORv4i32: 00462 case SPU::ORv2i64: 00463 case SPU::ORr8: 00464 case SPU::ORr16: 00465 case SPU::ORr32: 00466 case SPU::ORr64: 00467 case SPU::ORf32: 00468 case SPU::ORf64: 00469 if (MI->getOperand(1).getReg() == MI->getOperand(2).getReg()) 00470 return true; 00471 break; 00472 } 00473 00474 return false; 00475 } 00476 00477 /// foldMemoryOperand - SPU, like PPC, can only fold spills into 00478 /// copy instructions, turning them into load/store instructions. 00479 MachineInstr * 00480 SPUInstrInfo::foldMemoryOperandImpl(MachineFunction &MF, 00481 MachineInstr *MI, 00482 const SmallVectorImpl<unsigned> &Ops, 00483 int FrameIndex) const 00484 { 00485 if (Ops.size() != 1) return 0; 00486 00487 unsigned OpNum = Ops[0]; 00488 unsigned Opc = MI->getOpcode(); 00489 MachineInstr *NewMI = 0; 00490 00491 switch (Opc) { 00492 case SPU::ORv16i8: 00493 case SPU::ORv8i16: 00494 case SPU::ORv4i32: 00495 case SPU::ORv2i64: 00496 case SPU::ORr8: 00497 case SPU::ORr16: 00498 case SPU::ORr32: 00499 case SPU::ORr64: 00500 case SPU::ORf32: 00501 case SPU::ORf64: 00502 if (OpNum == 0) { // move -> store 00503 unsigned InReg = MI->getOperand(1).getReg(); 00504 bool isKill = MI->getOperand(1).isKill(); 00505 if (FrameIndex < SPUFrameInfo::maxFrameOffset()) { 00506 MachineInstrBuilder MIB = BuildMI(MF, get(SPU::STQDr32)); 00507 00508 MIB.addReg(InReg, false, false, isKill); 00509 NewMI = addFrameReference(MIB, FrameIndex); 00510 } 00511 } else { // move -> load 00512 unsigned OutReg = MI->getOperand(0).getReg(); 00513 bool isDead = MI->getOperand(0).isDead(); 00514 MachineInstrBuilder MIB = BuildMI(MF, get(Opc)); 00515 00516 MIB.addReg(OutReg, true, false, false, isDead); 00517 Opc = (FrameIndex < SPUFrameInfo::maxFrameOffset()) 00518 ? SPU::STQDr32 : SPU::STQXr32; 00519 NewMI = addFrameReference(MIB, FrameIndex); 00520 break; 00521 } 00522 } 00523 00524 return NewMI; 00525 } 00526 00527 //! Branch analysis 00528 /*! 00529 \note This code was kiped from PPC. There may be more branch analysis for 00530 CellSPU than what's currently done here. 00531 */ 00532 bool 00533 SPUInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, 00534 MachineBasicBlock *&FBB, 00535 SmallVectorImpl<MachineOperand> &Cond, 00536 bool AllowModify) const { 00537 // If the block has no terminators, it just falls into the block after it. 00538 MachineBasicBlock::iterator I = MBB.end(); 00539 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) 00540 return false; 00541 00542 // Get the last instruction in the block. 00543 MachineInstr *LastInst = I; 00544 00545 // If there is only one terminator instruction, process it. 00546 if (I == MBB.begin() || !isUnpredicatedTerminator(--I)) { 00547 if (isUncondBranch(LastInst)) { 00548 TBB = LastInst->getOperand(0).getMBB(); 00549 return false; 00550 } else if (isCondBranch(LastInst)) { 00551 // Block ends with fall-through condbranch. 00552 TBB = LastInst->getOperand(1).getMBB(); 00553 DEBUG(cerr << "Pushing LastInst: "); 00554 DEBUG(LastInst->dump()); 00555 Cond.push_back(MachineOperand::CreateImm(LastInst->getOpcode())); 00556 Cond.push_back(LastInst->getOperand(0)); 00557 return false; 00558 } 00559 // Otherwise, don't know what this is. 00560 return true; 00561 } 00562 00563 // Get the instruction before it if it's a terminator. 00564 MachineInstr *SecondLastInst = I; 00565 00566 // If there are three terminators, we don't know what sort of block this is. 00567 if (SecondLastInst && I != MBB.begin() && 00568 isUnpredicatedTerminator(--I)) 00569 return true; 00570 00571 // If the block ends with a conditional and unconditional branch, handle it. 00572 if (isCondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 00573 TBB = SecondLastInst->getOperand(1).getMBB(); 00574 DEBUG(cerr << "Pushing SecondLastInst: "); 00575 DEBUG(SecondLastInst->dump()); 00576 Cond.push_back(MachineOperand::CreateImm(SecondLastInst->getOpcode())); 00577 Cond.push_back(SecondLastInst->getOperand(0)); 00578 FBB = LastInst->getOperand(0).getMBB(); 00579 return false; 00580 } 00581 00582 // If the block ends with two unconditional branches, handle it. The second 00583 // one is not executed, so remove it. 00584 if (isUncondBranch(SecondLastInst) && isUncondBranch(LastInst)) { 00585 TBB = SecondLastInst->getOperand(0).getMBB(); 00586 I = LastInst; 00587 if (AllowModify) 00588 I->eraseFromParent(); 00589 return false; 00590 } 00591 00592 // Otherwise, can't handle this. 00593 return true; 00594 } 00595 00596 unsigned 00597 SPUInstrInfo::RemoveBranch(MachineBasicBlock &MBB) const { 00598 MachineBasicBlock::iterator I = MBB.end(); 00599 if (I == MBB.begin()) 00600 return 0; 00601 --I; 00602 if (!isCondBranch(I) && !isUncondBranch(I)) 00603 return 0; 00604 00605 // Remove the first branch. 00606 DEBUG(cerr << "Removing branch: "); 00607 DEBUG(I->dump()); 00608 I->eraseFromParent(); 00609 I = MBB.end(); 00610 if (I == MBB.begin()) 00611 return 1; 00612 00613 --I; 00614 if (!(isCondBranch(I) || isUncondBranch(I))) 00615 return 1; 00616 00617 // Remove the second branch. 00618 DEBUG(cerr << "Removing second branch: "); 00619 DEBUG(I->dump()); 00620 I->eraseFromParent(); 00621 return 2; 00622 } 00623 00624 unsigned 00625 SPUInstrInfo::InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, 00626 MachineBasicBlock *FBB, 00627 const SmallVectorImpl<MachineOperand> &Cond) const { 00628 // Shouldn't be a fall through. 00629 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 00630 assert((Cond.size() == 2 || Cond.size() == 0) && 00631 "SPU branch conditions have two components!"); 00632 00633 // One-way branch. 00634 if (FBB == 0) { 00635 if (Cond.empty()) { 00636 // Unconditional branch 00637 MachineInstrBuilder MIB = BuildMI(&MBB, get(SPU::BR)); 00638 MIB.addMBB(TBB); 00639 00640 DEBUG(cerr << "Inserted one-way uncond branch: "); 00641 DEBUG((*MIB).dump()); 00642 } else { 00643 // Conditional branch 00644 MachineInstrBuilder MIB = BuildMI(&MBB, get(Cond[0].getImm())); 00645 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 00646 00647 DEBUG(cerr << "Inserted one-way cond branch: "); 00648 DEBUG((*MIB).dump()); 00649 } 00650 return 1; 00651 } else { 00652 MachineInstrBuilder MIB = BuildMI(&MBB, get(Cond[0].getImm())); 00653 MachineInstrBuilder MIB2 = BuildMI(&MBB, get(SPU::BR)); 00654 00655 // Two-way Conditional Branch. 00656 MIB.addReg(Cond[1].getReg()).addMBB(TBB); 00657 MIB2.addMBB(FBB); 00658 00659 DEBUG(cerr << "Inserted conditional branch: "); 00660 DEBUG((*MIB).dump()); 00661 DEBUG(cerr << "part 2: "); 00662 DEBUG((*MIB2).dump()); 00663 return 2; 00664 } 00665 } 00666 00667 bool 00668 SPUInstrInfo::BlockHasNoFallThrough(const MachineBasicBlock &MBB) const { 00669 return (!MBB.empty() && isUncondBranch(&MBB.back())); 00670 } 00671 //! Reverses a branch's condition, returning false on success. 00672 bool 00673 SPUInstrInfo::ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) 00674 const { 00675 // Pretty brainless way of inverting the condition, but it works, considering 00676 // there are only two conditions... 00677 static struct { 00678 unsigned Opc; //! The incoming opcode 00679 unsigned RevCondOpc; //! The reversed condition opcode 00680 } revconds[] = { 00681 { SPU::BRNZr32, SPU::BRZr32 }, 00682 { SPU::BRNZv4i32, SPU::BRZv4i32 }, 00683 { SPU::BRZr32, SPU::BRNZr32 }, 00684 { SPU::BRZv4i32, SPU::BRNZv4i32 }, 00685 { SPU::BRHNZr16, SPU::BRHZr16 }, 00686 { SPU::BRHNZv8i16, SPU::BRHZv8i16 }, 00687 { SPU::BRHZr16, SPU::BRHNZr16 }, 00688 { SPU::BRHZv8i16, SPU::BRHNZv8i16 } 00689 }; 00690 00691 unsigned Opc = unsigned(Cond[0].getImm()); 00692 // Pretty dull mapping between the two conditions that SPU can generate: 00693 for (int i = sizeof(revconds)/sizeof(revconds[0]) - 1; i >= 0; --i) { 00694 if (revconds[i].Opc == Opc) { 00695 Cond[0].setImm(revconds[i].RevCondOpc); 00696 return false; 00697 } 00698 } 00699 00700 return true; 00701 }