1 //===- XtensaInstrInfo.cpp - Xtensa Instruction Information ---------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 6 // See https://llvm.org/LICENSE.txt for license information. 7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 8 // 9 //===----------------------------------------------------------------------===// 10 // 11 // This file contains the Xtensa implementation of the TargetInstrInfo class. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "XtensaInstrInfo.h" 16 #include "XtensaConstantPoolValue.h" 17 #include "XtensaMachineFunctionInfo.h" 18 #include "XtensaTargetMachine.h" 19 #include "llvm/CodeGen/MachineConstantPool.h" 20 #include "llvm/CodeGen/MachineFrameInfo.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineRegisterInfo.h" 23 #include "llvm/CodeGen/RegisterScavenging.h" 24 25 #define GET_INSTRINFO_CTOR_DTOR 26 #include "XtensaGenInstrInfo.inc" 27 28 using namespace llvm; 29 30 static const MachineInstrBuilder & 31 addFrameReference(const MachineInstrBuilder &MIB, int FI) { 32 MachineInstr *MI = MIB; 33 MachineFunction &MF = *MI->getParent()->getParent(); 34 MachineFrameInfo &MFFrame = MF.getFrameInfo(); 35 const MCInstrDesc &MCID = MI->getDesc(); 36 MachineMemOperand::Flags Flags = MachineMemOperand::MONone; 37 if (MCID.mayLoad()) 38 Flags |= MachineMemOperand::MOLoad; 39 if (MCID.mayStore()) 40 Flags |= MachineMemOperand::MOStore; 41 int64_t Offset = 0; 42 Align Alignment = MFFrame.getObjectAlign(FI); 43 44 MachineMemOperand *MMO = 45 MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI, Offset), 46 Flags, MFFrame.getObjectSize(FI), Alignment); 47 return MIB.addFrameIndex(FI).addImm(Offset).addMemOperand(MMO); 48 } 49 50 XtensaInstrInfo::XtensaInstrInfo(const XtensaSubtarget &STI) 51 : XtensaGenInstrInfo(Xtensa::ADJCALLSTACKDOWN, Xtensa::ADJCALLSTACKUP), 52 RI(STI), STI(STI) {} 53 54 Register XtensaInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, 55 int &FrameIndex) const { 56 if (MI.getOpcode() == Xtensa::L32I) { 57 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 58 MI.getOperand(2).getImm() == 0) { 59 FrameIndex = MI.getOperand(1).getIndex(); 60 return MI.getOperand(0).getReg(); 61 } 62 } 63 return Register(); 64 } 65 66 Register XtensaInstrInfo::isStoreToStackSlot(const MachineInstr &MI, 67 int &FrameIndex) const { 68 if (MI.getOpcode() == Xtensa::S32I) { 69 if (MI.getOperand(1).isFI() && MI.getOperand(2).isImm() && 70 MI.getOperand(2).getImm() == 0) { 71 FrameIndex = MI.getOperand(1).getIndex(); 72 return MI.getOperand(0).getReg(); 73 } 74 } 75 return Register(); 76 } 77 78 /// Adjust SP by Amount bytes. 79 void XtensaInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, 80 MachineBasicBlock &MBB, 81 MachineBasicBlock::iterator I) const { 82 DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); 83 84 if (Amount == 0) 85 return; 86 87 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); 88 const TargetRegisterClass *RC = &Xtensa::ARRegClass; 89 90 // create virtual reg to store immediate 91 unsigned Reg = RegInfo.createVirtualRegister(RC); 92 93 if (isInt<8>(Amount)) { // addi sp, sp, amount 94 BuildMI(MBB, I, DL, get(Xtensa::ADDI), Reg).addReg(SP).addImm(Amount); 95 } else { // Expand immediate that doesn't fit in 8-bit. 96 unsigned Reg1; 97 loadImmediate(MBB, I, &Reg1, Amount); 98 BuildMI(MBB, I, DL, get(Xtensa::ADD), Reg) 99 .addReg(SP) 100 .addReg(Reg1, RegState::Kill); 101 } 102 103 BuildMI(MBB, I, DL, get(Xtensa::OR), SP) 104 .addReg(Reg, RegState::Kill) 105 .addReg(Reg, RegState::Kill); 106 } 107 108 void XtensaInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 109 MachineBasicBlock::iterator MBBI, 110 const DebugLoc &DL, MCRegister DestReg, 111 MCRegister SrcReg, bool KillSrc, 112 bool RenamableDest, bool RenamableSrc) const { 113 // The MOV instruction is not present in core ISA, 114 // so use OR instruction. 115 if (Xtensa::ARRegClass.contains(DestReg, SrcReg)) 116 BuildMI(MBB, MBBI, DL, get(Xtensa::OR), DestReg) 117 .addReg(SrcReg, getKillRegState(KillSrc)) 118 .addReg(SrcReg, getKillRegState(KillSrc)); 119 else 120 report_fatal_error("Impossible reg-to-reg copy"); 121 } 122 123 void XtensaInstrInfo::storeRegToStackSlot( 124 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, 125 bool isKill, int FrameIdx, const TargetRegisterClass *RC, 126 const TargetRegisterInfo *TRI, Register VReg, 127 MachineInstr::MIFlag Flags) const { 128 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 129 unsigned LoadOpcode, StoreOpcode; 130 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); 131 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, DL, get(StoreOpcode)) 132 .addReg(SrcReg, getKillRegState(isKill)); 133 addFrameReference(MIB, FrameIdx); 134 } 135 136 void XtensaInstrInfo::loadRegFromStackSlot( 137 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DestReg, 138 int FrameIdx, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, 139 Register VReg, MachineInstr::MIFlag Flags) const { 140 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 141 unsigned LoadOpcode, StoreOpcode; 142 getLoadStoreOpcodes(RC, LoadOpcode, StoreOpcode, FrameIdx); 143 addFrameReference(BuildMI(MBB, MBBI, DL, get(LoadOpcode), DestReg), FrameIdx); 144 } 145 146 void XtensaInstrInfo::getLoadStoreOpcodes(const TargetRegisterClass *RC, 147 unsigned &LoadOpcode, 148 unsigned &StoreOpcode, 149 int64_t offset) const { 150 assert((RC == &Xtensa::ARRegClass) && 151 "Unsupported regclass to load or store"); 152 153 LoadOpcode = Xtensa::L32I; 154 StoreOpcode = Xtensa::S32I; 155 } 156 157 void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB, 158 MachineBasicBlock::iterator MBBI, 159 unsigned *Reg, int64_t Value) const { 160 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 161 MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); 162 const TargetRegisterClass *RC = &Xtensa::ARRegClass; 163 164 // create virtual reg to store immediate 165 *Reg = RegInfo.createVirtualRegister(RC); 166 if (Value >= -2048 && Value <= 2047) { 167 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Value); 168 } else if (Value >= -32768 && Value <= 32767) { 169 int Low = Value & 0xFF; 170 int High = Value & ~0xFF; 171 172 BuildMI(MBB, MBBI, DL, get(Xtensa::MOVI), *Reg).addImm(Low); 173 BuildMI(MBB, MBBI, DL, get(Xtensa::ADDMI), *Reg).addReg(*Reg).addImm(High); 174 } else if (Value >= -4294967296LL && Value <= 4294967295LL) { 175 // 32 bit arbitrary constant 176 MachineConstantPool *MCP = MBB.getParent()->getConstantPool(); 177 uint64_t UVal = ((uint64_t)Value) & 0xFFFFFFFFLL; 178 const Constant *CVal = ConstantInt::get( 179 Type::getInt32Ty(MBB.getParent()->getFunction().getContext()), UVal, 180 false); 181 unsigned Idx = MCP->getConstantPoolIndex(CVal, Align(2U)); 182 // MCSymbol MSym 183 BuildMI(MBB, MBBI, DL, get(Xtensa::L32R), *Reg).addConstantPoolIndex(Idx); 184 } else { 185 // use L32R to let assembler load immediate best 186 // TODO replace to L32R 187 report_fatal_error("Unsupported load immediate value"); 188 } 189 } 190 191 unsigned XtensaInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 192 switch (MI.getOpcode()) { 193 case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. 194 const MachineFunction *MF = MI.getParent()->getParent(); 195 const char *AsmStr = MI.getOperand(0).getSymbolName(); 196 return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); 197 } 198 default: 199 return MI.getDesc().getSize(); 200 } 201 } 202 203 bool XtensaInstrInfo::reverseBranchCondition( 204 SmallVectorImpl<MachineOperand> &Cond) const { 205 assert(Cond.size() <= 4 && "Invalid branch condition!"); 206 207 switch (Cond[0].getImm()) { 208 case Xtensa::BEQ: 209 Cond[0].setImm(Xtensa::BNE); 210 return false; 211 case Xtensa::BNE: 212 Cond[0].setImm(Xtensa::BEQ); 213 return false; 214 case Xtensa::BLT: 215 Cond[0].setImm(Xtensa::BGE); 216 return false; 217 case Xtensa::BGE: 218 Cond[0].setImm(Xtensa::BLT); 219 return false; 220 case Xtensa::BLTU: 221 Cond[0].setImm(Xtensa::BGEU); 222 return false; 223 case Xtensa::BGEU: 224 Cond[0].setImm(Xtensa::BLTU); 225 return false; 226 case Xtensa::BEQI: 227 Cond[0].setImm(Xtensa::BNEI); 228 return false; 229 case Xtensa::BNEI: 230 Cond[0].setImm(Xtensa::BEQI); 231 return false; 232 case Xtensa::BGEI: 233 Cond[0].setImm(Xtensa::BLTI); 234 return false; 235 case Xtensa::BLTI: 236 Cond[0].setImm(Xtensa::BGEI); 237 return false; 238 case Xtensa::BGEUI: 239 Cond[0].setImm(Xtensa::BLTUI); 240 return false; 241 case Xtensa::BLTUI: 242 Cond[0].setImm(Xtensa::BGEUI); 243 return false; 244 case Xtensa::BEQZ: 245 Cond[0].setImm(Xtensa::BNEZ); 246 return false; 247 case Xtensa::BNEZ: 248 Cond[0].setImm(Xtensa::BEQZ); 249 return false; 250 case Xtensa::BLTZ: 251 Cond[0].setImm(Xtensa::BGEZ); 252 return false; 253 case Xtensa::BGEZ: 254 Cond[0].setImm(Xtensa::BLTZ); 255 return false; 256 default: 257 report_fatal_error("Invalid branch condition!"); 258 } 259 } 260 261 MachineBasicBlock * 262 XtensaInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { 263 unsigned OpCode = MI.getOpcode(); 264 switch (OpCode) { 265 case Xtensa::BR_JT: 266 case Xtensa::JX: 267 return nullptr; 268 case Xtensa::J: 269 return MI.getOperand(0).getMBB(); 270 case Xtensa::BEQ: 271 case Xtensa::BNE: 272 case Xtensa::BLT: 273 case Xtensa::BLTU: 274 case Xtensa::BGE: 275 case Xtensa::BGEU: 276 return MI.getOperand(2).getMBB(); 277 case Xtensa::BEQI: 278 case Xtensa::BNEI: 279 case Xtensa::BLTI: 280 case Xtensa::BLTUI: 281 case Xtensa::BGEI: 282 case Xtensa::BGEUI: 283 return MI.getOperand(2).getMBB(); 284 case Xtensa::BEQZ: 285 case Xtensa::BNEZ: 286 case Xtensa::BLTZ: 287 case Xtensa::BGEZ: 288 return MI.getOperand(1).getMBB(); 289 default: 290 llvm_unreachable("Unknown branch opcode"); 291 } 292 } 293 294 bool XtensaInstrInfo::isBranchOffsetInRange(unsigned BranchOp, 295 int64_t BrOffset) const { 296 switch (BranchOp) { 297 case Xtensa::J: 298 BrOffset -= 4; 299 return isIntN(18, BrOffset); 300 case Xtensa::JX: 301 return true; 302 case Xtensa::BR_JT: 303 return true; 304 case Xtensa::BEQ: 305 case Xtensa::BNE: 306 case Xtensa::BLT: 307 case Xtensa::BLTU: 308 case Xtensa::BGE: 309 case Xtensa::BGEU: 310 case Xtensa::BEQI: 311 case Xtensa::BNEI: 312 case Xtensa::BLTI: 313 case Xtensa::BLTUI: 314 case Xtensa::BGEI: 315 case Xtensa::BGEUI: 316 BrOffset -= 4; 317 return isIntN(8, BrOffset); 318 case Xtensa::BEQZ: 319 case Xtensa::BNEZ: 320 case Xtensa::BLTZ: 321 case Xtensa::BGEZ: 322 BrOffset -= 4; 323 return isIntN(12, BrOffset); 324 default: 325 llvm_unreachable("Unknown branch opcode"); 326 } 327 } 328 329 bool XtensaInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 330 MachineBasicBlock *&TBB, 331 MachineBasicBlock *&FBB, 332 SmallVectorImpl<MachineOperand> &Cond, 333 bool AllowModify = false) const { 334 // Most of the code and comments here are boilerplate. 335 336 // Start from the bottom of the block and work up, examining the 337 // terminator instructions. 338 MachineBasicBlock::iterator I = MBB.end(); 339 while (I != MBB.begin()) { 340 --I; 341 if (I->isDebugValue()) 342 continue; 343 344 // Working from the bottom, when we see a non-terminator instruction, we're 345 // done. 346 if (!isUnpredicatedTerminator(*I)) 347 break; 348 349 // A terminator that isn't a branch can't easily be handled by this 350 // analysis. 351 SmallVector<MachineOperand, 4> ThisCond; 352 ThisCond.push_back(MachineOperand::CreateImm(0)); 353 const MachineOperand *ThisTarget; 354 if (!isBranch(I, ThisCond, ThisTarget)) 355 return true; 356 357 // Can't handle indirect branches. 358 if (!ThisTarget->isMBB()) 359 return true; 360 361 if (ThisCond[0].getImm() == Xtensa::J) { 362 // Handle unconditional branches. 363 if (!AllowModify) { 364 TBB = ThisTarget->getMBB(); 365 continue; 366 } 367 368 // If the block has any instructions after a JMP, delete them. 369 while (std::next(I) != MBB.end()) 370 std::next(I)->eraseFromParent(); 371 372 Cond.clear(); 373 FBB = 0; 374 375 // TBB is used to indicate the unconditinal destination. 376 TBB = ThisTarget->getMBB(); 377 continue; 378 } 379 380 // Working from the bottom, handle the first conditional branch. 381 if (Cond.empty()) { 382 // FIXME: add X86-style branch swap 383 FBB = TBB; 384 TBB = ThisTarget->getMBB(); 385 Cond.push_back(MachineOperand::CreateImm(ThisCond[0].getImm())); 386 387 // push remaining operands 388 for (unsigned int i = 0; i < (I->getNumExplicitOperands() - 1); i++) 389 Cond.push_back(I->getOperand(i)); 390 391 continue; 392 } 393 394 // Handle subsequent conditional branches. 395 assert(Cond.size() <= 4); 396 assert(TBB); 397 398 // Only handle the case where all conditional branches branch to the same 399 // destination. 400 if (TBB != ThisTarget->getMBB()) 401 return true; 402 403 // If the conditions are the same, we can leave them alone. 404 unsigned OldCond = Cond[0].getImm(); 405 if (OldCond == ThisCond[0].getImm()) 406 continue; 407 } 408 409 return false; 410 } 411 412 unsigned XtensaInstrInfo::removeBranch(MachineBasicBlock &MBB, 413 int *BytesRemoved) const { 414 // Most of the code and comments here are boilerplate. 415 MachineBasicBlock::iterator I = MBB.end(); 416 unsigned Count = 0; 417 if (BytesRemoved) 418 *BytesRemoved = 0; 419 420 while (I != MBB.begin()) { 421 --I; 422 SmallVector<MachineOperand, 4> Cond; 423 Cond.push_back(MachineOperand::CreateImm(0)); 424 const MachineOperand *Target; 425 if (!isBranch(I, Cond, Target)) 426 break; 427 if (!Target->isMBB()) 428 break; 429 // Remove the branch. 430 if (BytesRemoved) 431 *BytesRemoved += getInstSizeInBytes(*I); 432 I->eraseFromParent(); 433 I = MBB.end(); 434 ++Count; 435 } 436 return Count; 437 } 438 439 unsigned XtensaInstrInfo::insertBranch( 440 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 441 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 442 unsigned Count = 0; 443 if (BytesAdded) 444 *BytesAdded = 0; 445 if (FBB) { 446 // Need to build two branches then 447 // one to branch to TBB on Cond 448 // and a second one immediately after to unconditionally jump to FBB 449 Count = insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded); 450 auto &MI = *BuildMI(&MBB, DL, get(Xtensa::J)).addMBB(FBB); 451 Count++; 452 if (BytesAdded) 453 *BytesAdded += getInstSizeInBytes(MI); 454 return Count; 455 } 456 // This function inserts the branch at the end of the MBB 457 Count += insertBranchAtInst(MBB, MBB.end(), TBB, Cond, DL, BytesAdded); 458 return Count; 459 } 460 461 void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, 462 MachineBasicBlock &DestBB, 463 MachineBasicBlock &RestoreBB, 464 const DebugLoc &DL, int64_t BrOffset, 465 RegScavenger *RS) const { 466 assert(RS && "RegScavenger required for long branching"); 467 assert(MBB.empty() && 468 "new block should be inserted for expanding unconditional branch"); 469 assert(MBB.pred_size() == 1); 470 471 MachineFunction *MF = MBB.getParent(); 472 MachineRegisterInfo &MRI = MF->getRegInfo(); 473 MachineConstantPool *ConstantPool = MF->getConstantPool(); 474 auto *XtensaFI = MF->getInfo<XtensaMachineFunctionInfo>(); 475 MachineBasicBlock *JumpToMBB = &DestBB; 476 477 if (!isInt<32>(BrOffset)) 478 report_fatal_error( 479 "Branch offsets outside of the signed 32-bit range not supported"); 480 481 Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass); 482 auto II = MBB.end(); 483 484 // Create l32r without last operand. We will add this operand later when 485 // JumpToMMB will be calculated and placed to the ConstantPool. 486 MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg); 487 BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill); 488 489 RS->enterBasicBlockEnd(MBB); 490 Register ScavRegister = 491 RS->scavengeRegisterBackwards(Xtensa::ARRegClass, L32R.getIterator(), 492 /*RestoreAfter=*/false, /*SpAdj=*/0, 493 /*AllowSpill=*/false); 494 if (ScavRegister != Xtensa::NoRegister) 495 RS->setRegUsed(ScavRegister); 496 else { 497 // The case when there is no scavenged register needs special handling. 498 // Pick A8 because it doesn't make a difference 499 ScavRegister = Xtensa::A12; 500 501 int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex(); 502 if (FrameIndex == -1) 503 report_fatal_error( 504 "Unable to properly handle scavenged register for indirect jump, " 505 "function code size is significantly larger than estimated"); 506 507 storeRegToStackSlot(MBB, L32R, ScavRegister, /*IsKill=*/true, FrameIndex, 508 &Xtensa::ARRegClass, &RI, Register()); 509 RI.eliminateFrameIndex(std::prev(L32R.getIterator()), 510 /*SpAdj=*/0, /*FIOperandNum=*/1); 511 512 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex, 513 &Xtensa::ARRegClass, &RI, Register()); 514 RI.eliminateFrameIndex(RestoreBB.back(), 515 /*SpAdj=*/0, /*FIOperandNum=*/1); 516 JumpToMBB = &RestoreBB; 517 } 518 519 XtensaConstantPoolValue *C = XtensaConstantPoolMBB::Create( 520 MF->getFunction().getContext(), JumpToMBB, 0); 521 unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4)); 522 L32R.addOperand(MachineOperand::CreateCPI(Idx, 0)); 523 524 MRI.replaceRegWith(ScratchReg, ScavRegister); 525 MRI.clearVirtRegs(); 526 } 527 528 unsigned XtensaInstrInfo::insertConstBranchAtInst( 529 MachineBasicBlock &MBB, MachineInstr *I, int64_t offset, 530 ArrayRef<MachineOperand> Cond, DebugLoc DL, int *BytesAdded) const { 531 assert(Cond.size() <= 4 && 532 "Xtensa branch conditions have less than four components!"); 533 534 if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) { 535 // Unconditional branch 536 MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addImm(offset); 537 if (BytesAdded && MI) 538 *BytesAdded += getInstSizeInBytes(*MI); 539 return 1; 540 } 541 542 unsigned Count = 0; 543 unsigned BR_C = Cond[0].getImm(); 544 MachineInstr *MI = nullptr; 545 switch (BR_C) { 546 case Xtensa::BEQ: 547 case Xtensa::BNE: 548 case Xtensa::BLT: 549 case Xtensa::BLTU: 550 case Xtensa::BGE: 551 case Xtensa::BGEU: 552 MI = BuildMI(MBB, I, DL, get(BR_C)) 553 .addImm(offset) 554 .addReg(Cond[1].getReg()) 555 .addReg(Cond[2].getReg()); 556 break; 557 case Xtensa::BEQI: 558 case Xtensa::BNEI: 559 case Xtensa::BLTI: 560 case Xtensa::BLTUI: 561 case Xtensa::BGEI: 562 case Xtensa::BGEUI: 563 MI = BuildMI(MBB, I, DL, get(BR_C)) 564 .addImm(offset) 565 .addReg(Cond[1].getReg()) 566 .addImm(Cond[2].getImm()); 567 break; 568 case Xtensa::BEQZ: 569 case Xtensa::BNEZ: 570 case Xtensa::BLTZ: 571 case Xtensa::BGEZ: 572 MI = BuildMI(MBB, I, DL, get(BR_C)).addImm(offset).addReg(Cond[1].getReg()); 573 break; 574 default: 575 llvm_unreachable("Invalid branch type!"); 576 } 577 if (BytesAdded && MI) 578 *BytesAdded += getInstSizeInBytes(*MI); 579 ++Count; 580 return Count; 581 } 582 583 unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB, 584 MachineBasicBlock::iterator I, 585 MachineBasicBlock *TBB, 586 ArrayRef<MachineOperand> Cond, 587 const DebugLoc &DL, 588 int *BytesAdded) const { 589 // Shouldn't be a fall through. 590 assert(TBB && "InsertBranch must not be told to insert a fallthrough"); 591 assert(Cond.size() <= 4 && 592 "Xtensa branch conditions have less than four components!"); 593 594 if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) { 595 // Unconditional branch 596 MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addMBB(TBB); 597 if (BytesAdded && MI) 598 *BytesAdded += getInstSizeInBytes(*MI); 599 return 1; 600 } 601 602 unsigned Count = 0; 603 unsigned BR_C = Cond[0].getImm(); 604 MachineInstr *MI = nullptr; 605 switch (BR_C) { 606 case Xtensa::BEQ: 607 case Xtensa::BNE: 608 case Xtensa::BLT: 609 case Xtensa::BLTU: 610 case Xtensa::BGE: 611 case Xtensa::BGEU: 612 MI = BuildMI(MBB, I, DL, get(BR_C)) 613 .addReg(Cond[1].getReg()) 614 .addReg(Cond[2].getReg()) 615 .addMBB(TBB); 616 break; 617 case Xtensa::BEQI: 618 case Xtensa::BNEI: 619 case Xtensa::BLTI: 620 case Xtensa::BLTUI: 621 case Xtensa::BGEI: 622 case Xtensa::BGEUI: 623 MI = BuildMI(MBB, I, DL, get(BR_C)) 624 .addReg(Cond[1].getReg()) 625 .addImm(Cond[2].getImm()) 626 .addMBB(TBB); 627 break; 628 case Xtensa::BEQZ: 629 case Xtensa::BNEZ: 630 case Xtensa::BLTZ: 631 case Xtensa::BGEZ: 632 MI = BuildMI(MBB, I, DL, get(BR_C)).addReg(Cond[1].getReg()).addMBB(TBB); 633 break; 634 default: 635 report_fatal_error("Invalid branch type!"); 636 } 637 if (BytesAdded && MI) 638 *BytesAdded += getInstSizeInBytes(*MI); 639 ++Count; 640 return Count; 641 } 642 643 bool XtensaInstrInfo::isBranch(const MachineBasicBlock::iterator &MI, 644 SmallVectorImpl<MachineOperand> &Cond, 645 const MachineOperand *&Target) const { 646 unsigned OpCode = MI->getOpcode(); 647 switch (OpCode) { 648 case Xtensa::J: 649 case Xtensa::JX: 650 case Xtensa::BR_JT: 651 Cond[0].setImm(OpCode); 652 Target = &MI->getOperand(0); 653 return true; 654 case Xtensa::BEQ: 655 case Xtensa::BNE: 656 case Xtensa::BLT: 657 case Xtensa::BLTU: 658 case Xtensa::BGE: 659 case Xtensa::BGEU: 660 Cond[0].setImm(OpCode); 661 Target = &MI->getOperand(2); 662 return true; 663 664 case Xtensa::BEQI: 665 case Xtensa::BNEI: 666 case Xtensa::BLTI: 667 case Xtensa::BLTUI: 668 case Xtensa::BGEI: 669 case Xtensa::BGEUI: 670 Cond[0].setImm(OpCode); 671 Target = &MI->getOperand(2); 672 return true; 673 674 case Xtensa::BEQZ: 675 case Xtensa::BNEZ: 676 case Xtensa::BLTZ: 677 case Xtensa::BGEZ: 678 Cond[0].setImm(OpCode); 679 Target = &MI->getOperand(1); 680 return true; 681 682 default: 683 assert(!MI->getDesc().isBranch() && "Unknown branch opcode"); 684 return false; 685 } 686 } 687