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