|
13 | 13 | //===----------------------------------------------------------------------===//
|
14 | 14 |
|
15 | 15 | #include "XtensaInstrInfo.h"
|
| 16 | +#include "XtensaConstantPoolValue.h" |
| 17 | +#include "XtensaMachineFunctionInfo.h" |
16 | 18 | #include "XtensaTargetMachine.h"
|
17 | 19 | #include "llvm/CodeGen/MachineConstantPool.h"
|
18 | 20 | #include "llvm/CodeGen/MachineFrameInfo.h"
|
19 | 21 | #include "llvm/CodeGen/MachineInstrBuilder.h"
|
20 | 22 | #include "llvm/CodeGen/MachineRegisterInfo.h"
|
| 23 | +#include "llvm/CodeGen/RegisterScavenging.h" |
21 | 24 |
|
22 | 25 | #define GET_INSTRINFO_CTOR_DTOR
|
23 | 26 | #include "XtensaGenInstrInfo.inc"
|
@@ -186,6 +189,18 @@ void XtensaInstrInfo::loadImmediate(MachineBasicBlock &MBB,
|
186 | 189 | }
|
187 | 190 | }
|
188 | 191 |
|
| 192 | +unsigned XtensaInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { |
| 193 | + switch (MI.getOpcode()) { |
| 194 | + case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. |
| 195 | + const MachineFunction *MF = MI.getParent()->getParent(); |
| 196 | + const char *AsmStr = MI.getOperand(0).getSymbolName(); |
| 197 | + return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); |
| 198 | + } |
| 199 | + default: |
| 200 | + return MI.getDesc().getSize(); |
| 201 | + } |
| 202 | +} |
| 203 | + |
189 | 204 | bool XtensaInstrInfo::reverseBranchCondition(
|
190 | 205 | SmallVectorImpl<MachineOperand> &Cond) const {
|
191 | 206 | assert(Cond.size() <= 4 && "Invalid branch condition!");
|
@@ -244,6 +259,74 @@ bool XtensaInstrInfo::reverseBranchCondition(
|
244 | 259 | }
|
245 | 260 | }
|
246 | 261 |
|
| 262 | +MachineBasicBlock * |
| 263 | +XtensaInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { |
| 264 | + unsigned OpCode = MI.getOpcode(); |
| 265 | + switch (OpCode) { |
| 266 | + case Xtensa::BR_JT: |
| 267 | + case Xtensa::JX: |
| 268 | + return nullptr; |
| 269 | + case Xtensa::J: |
| 270 | + return MI.getOperand(0).getMBB(); |
| 271 | + case Xtensa::BEQ: |
| 272 | + case Xtensa::BNE: |
| 273 | + case Xtensa::BLT: |
| 274 | + case Xtensa::BLTU: |
| 275 | + case Xtensa::BGE: |
| 276 | + case Xtensa::BGEU: |
| 277 | + return MI.getOperand(2).getMBB(); |
| 278 | + case Xtensa::BEQI: |
| 279 | + case Xtensa::BNEI: |
| 280 | + case Xtensa::BLTI: |
| 281 | + case Xtensa::BLTUI: |
| 282 | + case Xtensa::BGEI: |
| 283 | + case Xtensa::BGEUI: |
| 284 | + return MI.getOperand(2).getMBB(); |
| 285 | + case Xtensa::BEQZ: |
| 286 | + case Xtensa::BNEZ: |
| 287 | + case Xtensa::BLTZ: |
| 288 | + case Xtensa::BGEZ: |
| 289 | + return MI.getOperand(1).getMBB(); |
| 290 | + default: |
| 291 | + llvm_unreachable("Unknown branch opcode"); |
| 292 | + } |
| 293 | +} |
| 294 | + |
| 295 | +bool XtensaInstrInfo::isBranchOffsetInRange(unsigned BranchOp, |
| 296 | + int64_t BrOffset) const { |
| 297 | + switch (BranchOp) { |
| 298 | + case Xtensa::J: |
| 299 | + BrOffset -= 4; |
| 300 | + return isIntN(18, BrOffset); |
| 301 | + case Xtensa::JX: |
| 302 | + return true; |
| 303 | + case Xtensa::BR_JT: |
| 304 | + return true; |
| 305 | + case Xtensa::BEQ: |
| 306 | + case Xtensa::BNE: |
| 307 | + case Xtensa::BLT: |
| 308 | + case Xtensa::BLTU: |
| 309 | + case Xtensa::BGE: |
| 310 | + case Xtensa::BGEU: |
| 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 | + BrOffset -= 4; |
| 318 | + return isIntN(8, BrOffset); |
| 319 | + case Xtensa::BEQZ: |
| 320 | + case Xtensa::BNEZ: |
| 321 | + case Xtensa::BLTZ: |
| 322 | + case Xtensa::BGEZ: |
| 323 | + BrOffset -= 4; |
| 324 | + return isIntN(12, BrOffset); |
| 325 | + default: |
| 326 | + llvm_unreachable("Unknown branch opcode"); |
| 327 | + } |
| 328 | +} |
| 329 | + |
247 | 330 | bool XtensaInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
|
248 | 331 | MachineBasicBlock *&TBB,
|
249 | 332 | MachineBasicBlock *&FBB,
|
@@ -376,6 +459,130 @@ unsigned XtensaInstrInfo::insertBranch(
|
376 | 459 | return Count;
|
377 | 460 | }
|
378 | 461 |
|
| 462 | +void XtensaInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, |
| 463 | + MachineBasicBlock &DestBB, |
| 464 | + MachineBasicBlock &RestoreBB, |
| 465 | + const DebugLoc &DL, int64_t BrOffset, |
| 466 | + RegScavenger *RS) const { |
| 467 | + assert(RS && "RegScavenger required for long branching"); |
| 468 | + assert(MBB.empty() && |
| 469 | + "new block should be inserted for expanding unconditional branch"); |
| 470 | + assert(MBB.pred_size() == 1); |
| 471 | + |
| 472 | + MachineFunction *MF = MBB.getParent(); |
| 473 | + MachineRegisterInfo &MRI = MF->getRegInfo(); |
| 474 | + MachineConstantPool *ConstantPool = MF->getConstantPool(); |
| 475 | + auto *XtensaFI = MF->getInfo<XtensaMachineFunctionInfo>(); |
| 476 | + MachineBasicBlock *JumpToMBB = &DestBB; |
| 477 | + |
| 478 | + if (!isInt<32>(BrOffset)) |
| 479 | + report_fatal_error( |
| 480 | + "Branch offsets outside of the signed 32-bit range not supported"); |
| 481 | + |
| 482 | + Register ScratchReg = MRI.createVirtualRegister(&Xtensa::ARRegClass); |
| 483 | + auto II = MBB.end(); |
| 484 | + |
| 485 | + // Create l32r without last operand. We will add this operand later when |
| 486 | + // JumpToMMB will be calculated and placed to the ConstantPool. |
| 487 | + MachineInstr &L32R = *BuildMI(MBB, II, DL, get(Xtensa::L32R), ScratchReg); |
| 488 | + BuildMI(MBB, II, DL, get(Xtensa::JX)).addReg(ScratchReg, RegState::Kill); |
| 489 | + |
| 490 | + RS->enterBasicBlockEnd(MBB); |
| 491 | + Register ScavRegister = |
| 492 | + RS->scavengeRegisterBackwards(Xtensa::ARRegClass, L32R.getIterator(), |
| 493 | + /*RestoreAfter=*/false, /*SpAdj=*/0, |
| 494 | + /*AllowSpill=*/false); |
| 495 | + if (ScavRegister != Xtensa::NoRegister) |
| 496 | + RS->setRegUsed(ScavRegister); |
| 497 | + else { |
| 498 | + // The case when there is no scavenged register needs special handling. |
| 499 | + // Pick A8 because it doesn't make a difference |
| 500 | + ScavRegister = Xtensa::A12; |
| 501 | + |
| 502 | + int FrameIndex = XtensaFI->getBranchRelaxationScratchFrameIndex(); |
| 503 | + if (FrameIndex == -1) |
| 504 | + report_fatal_error( |
| 505 | + "Unable to properly handle scavenged register for indirect jump, " |
| 506 | + "function code size is significantly larger than estimated"); |
| 507 | + |
| 508 | + storeRegToStackSlot(MBB, L32R, ScavRegister, /*IsKill=*/true, FrameIndex, |
| 509 | + &Xtensa::ARRegClass, &RI, Register()); |
| 510 | + RI.eliminateFrameIndex(std::prev(L32R.getIterator()), |
| 511 | + /*SpAdj=*/0, /*FIOperandNum=*/1); |
| 512 | + |
| 513 | + loadRegFromStackSlot(RestoreBB, RestoreBB.end(), ScavRegister, FrameIndex, |
| 514 | + &Xtensa::ARRegClass, &RI, Register()); |
| 515 | + RI.eliminateFrameIndex(RestoreBB.back(), |
| 516 | + /*SpAdj=*/0, /*FIOperandNum=*/1); |
| 517 | + JumpToMBB = &RestoreBB; |
| 518 | + } |
| 519 | + |
| 520 | + XtensaConstantPoolValue *C = XtensaConstantPoolMBB::Create( |
| 521 | + MF->getFunction().getContext(), JumpToMBB, 0); |
| 522 | + unsigned Idx = ConstantPool->getConstantPoolIndex(C, Align(4)); |
| 523 | + L32R.addOperand(MachineOperand::CreateCPI(Idx, 0)); |
| 524 | + |
| 525 | + MRI.replaceRegWith(ScratchReg, ScavRegister); |
| 526 | + MRI.clearVirtRegs(); |
| 527 | +} |
| 528 | + |
| 529 | +unsigned XtensaInstrInfo::insertConstBranchAtInst( |
| 530 | + MachineBasicBlock &MBB, MachineInstr *I, int64_t offset, |
| 531 | + ArrayRef<MachineOperand> Cond, DebugLoc DL, int *BytesAdded) const { |
| 532 | + // Shouldn't be a fall through. |
| 533 | + assert(&MBB && "InsertBranch must not be told to insert a fallthrough"); |
| 534 | + assert(Cond.size() <= 4 && |
| 535 | + "Xtensa branch conditions have less than four components!"); |
| 536 | + |
| 537 | + if (Cond.empty() || (Cond[0].getImm() == Xtensa::J)) { |
| 538 | + // Unconditional branch |
| 539 | + MachineInstr *MI = BuildMI(MBB, I, DL, get(Xtensa::J)).addImm(offset); |
| 540 | + if (BytesAdded && MI) |
| 541 | + *BytesAdded += getInstSizeInBytes(*MI); |
| 542 | + return 1; |
| 543 | + } |
| 544 | + |
| 545 | + unsigned Count = 0; |
| 546 | + unsigned BR_C = Cond[0].getImm(); |
| 547 | + MachineInstr *MI = nullptr; |
| 548 | + switch (BR_C) { |
| 549 | + case Xtensa::BEQ: |
| 550 | + case Xtensa::BNE: |
| 551 | + case Xtensa::BLT: |
| 552 | + case Xtensa::BLTU: |
| 553 | + case Xtensa::BGE: |
| 554 | + case Xtensa::BGEU: |
| 555 | + MI = BuildMI(MBB, I, DL, get(BR_C)) |
| 556 | + .addImm(offset) |
| 557 | + .addReg(Cond[1].getReg()) |
| 558 | + .addReg(Cond[2].getReg()); |
| 559 | + break; |
| 560 | + case Xtensa::BEQI: |
| 561 | + case Xtensa::BNEI: |
| 562 | + case Xtensa::BLTI: |
| 563 | + case Xtensa::BLTUI: |
| 564 | + case Xtensa::BGEI: |
| 565 | + case Xtensa::BGEUI: |
| 566 | + MI = BuildMI(MBB, I, DL, get(BR_C)) |
| 567 | + .addImm(offset) |
| 568 | + .addReg(Cond[1].getReg()) |
| 569 | + .addImm(Cond[2].getImm()); |
| 570 | + break; |
| 571 | + case Xtensa::BEQZ: |
| 572 | + case Xtensa::BNEZ: |
| 573 | + case Xtensa::BLTZ: |
| 574 | + case Xtensa::BGEZ: |
| 575 | + MI = BuildMI(MBB, I, DL, get(BR_C)).addImm(offset).addReg(Cond[1].getReg()); |
| 576 | + break; |
| 577 | + default: |
| 578 | + llvm_unreachable("Invalid branch type!"); |
| 579 | + } |
| 580 | + if (BytesAdded && MI) |
| 581 | + *BytesAdded += getInstSizeInBytes(*MI); |
| 582 | + ++Count; |
| 583 | + return Count; |
| 584 | +} |
| 585 | + |
379 | 586 | unsigned XtensaInstrInfo::insertBranchAtInst(MachineBasicBlock &MBB,
|
380 | 587 | MachineBasicBlock::iterator I,
|
381 | 588 | MachineBasicBlock *TBB,
|
|
0 commit comments