bool BranchRelaxation::fixupUnconditionalBranch(MachineInstr &MI) { MachineBasicBlock *MBB = MI.getParent(); unsigned OldBrSize = TII->getInstSizeInBytes(MI); MachineBasicBlock *DestBB = TII->getBranchDestBlock(MI); int64_t DestOffset = BlockInfo[DestBB->getNumber()].Offset; int64_t SrcOffset = getInstrOffset(MI); assert(!TII->isBranchOffsetInRange(MI.getOpcode(), DestOffset - SrcOffset)); BlockInfo[MBB->getNumber()].Size -= OldBrSize; MachineBasicBlock *BranchBB = MBB; // If this was an expanded conditional branch, there is already a single // unconditional branch in a block. if (!MBB->empty()) { BranchBB = createNewBlockAfter(*MBB); // Add live outs. for (const MachineBasicBlock *Succ : MBB->successors()) { for (const MachineBasicBlock::RegisterMaskPair &LiveIn : Succ->liveins()) BranchBB->addLiveIn(LiveIn); } BranchBB->sortUniqueLiveIns(); BranchBB->addSuccessor(DestBB); MBB->replaceSuccessor(DestBB, BranchBB); } DebugLoc DL = MI.getDebugLoc(); MI.eraseFromParent(); BlockInfo[BranchBB->getNumber()].Size += TII->insertIndirectBranch( *BranchBB, *DestBB, DL, DestOffset - SrcOffset, RS.get()); adjustBlockOffsets(*MBB); return true; }
/// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr *MI) { MachineBasicBlock *DestBB = getDestBlock(MI); // Add an unconditional branch to the destination and invert the branch // condition to jump over it: // tbz L1 // => // tbnz L2 // b L1 // L2: // If the branch is at the end of its MBB and that has a fall-through block, // direct the updated conditional branch to the fall-through block. Otherwise, // split the MBB before the next instruction. MachineBasicBlock *MBB = MI->getParent(); MachineInstr *BMI = &MBB->back(); bool NeedSplit = (BMI != MI) || !BBHasFallthrough(MBB); if (BMI != MI) { if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->getLastNonDebugInstr()) && BMI->getOpcode() == AArch64::B) { // Last MI in the BB is an unconditional branch. Can we simply invert the // condition and swap destinations: // beq L1 // b L2 // => // bne L2 // b L1 MachineBasicBlock *NewDest = BMI->getOperand(0).getMBB(); if (isBlockInRange(MI, NewDest, getBranchDisplacementBits(MI->getOpcode()))) { DEBUG(dbgs() << " Invert condition and swap its destination with " << *BMI); BMI->getOperand(0).setMBB(DestBB); unsigned OpNum = (MI->getOpcode() == AArch64::TBZW || MI->getOpcode() == AArch64::TBNZW || MI->getOpcode() == AArch64::TBZX || MI->getOpcode() == AArch64::TBNZX) ? 2 : 1; MI->getOperand(OpNum).setMBB(NewDest); MI->setDesc(TII->get(getOppositeConditionOpcode(MI->getOpcode()))); if (MI->getOpcode() == AArch64::Bcc) invertBccCondition(MI); return true; } } } if (NeedSplit) { // Analyze the branch so we know how to update the successor lists. MachineBasicBlock *TBB, *FBB; SmallVector<MachineOperand, 2> Cond; TII->AnalyzeBranch(*MBB, TBB, FBB, Cond, false); MachineBasicBlock *NewBB = splitBlockBeforeInstr(MI); // No need for the branch to the next block. We're adding an unconditional // branch to the destination. int delta = TII->GetInstSizeInBytes(&MBB->back()); BlockInfo[MBB->getNumber()].Size -= delta; MBB->back().eraseFromParent(); // BlockInfo[SplitBB].Offset is wrong temporarily, fixed below // Update the successor lists according to the transformation to follow. // Do it here since if there's no split, no update is needed. MBB->replaceSuccessor(FBB, NewBB); NewBB->addSuccessor(FBB); } MachineBasicBlock *NextBB = std::next(MachineFunction::iterator(MBB)); DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber() << ", invert condition and change dest. to BB#" << NextBB->getNumber() << "\n"); // Insert a new conditional branch and a new unconditional branch. MachineInstrBuilder MIB = BuildMI( MBB, DebugLoc(), TII->get(getOppositeConditionOpcode(MI->getOpcode()))) .addOperand(MI->getOperand(0)); if (MI->getOpcode() == AArch64::TBZW || MI->getOpcode() == AArch64::TBNZW || MI->getOpcode() == AArch64::TBZX || MI->getOpcode() == AArch64::TBNZX) MIB.addOperand(MI->getOperand(1)); if (MI->getOpcode() == AArch64::Bcc) invertBccCondition(MIB); MIB.addMBB(NextBB); BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); BuildMI(MBB, DebugLoc(), TII->get(AArch64::B)).addMBB(DestBB); BlockInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); // Remove the old conditional branch. It may or may not still be in MBB. BlockInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI); MI->eraseFromParent(); // Finally, keep the block offsets up to date. adjustBlockOffsets(*MBB); return true; }
/// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. bool BranchRelaxation::fixupConditionalBranch(MachineInstr &MI) { DebugLoc DL = MI.getDebugLoc(); MachineBasicBlock *MBB = MI.getParent(); MachineBasicBlock *TBB = nullptr, *FBB = nullptr; MachineBasicBlock *NewBB = nullptr; SmallVector<MachineOperand, 4> Cond; auto insertUncondBranch = [&](MachineBasicBlock *MBB, MachineBasicBlock *DestBB) { unsigned &BBSize = BlockInfo[MBB->getNumber()].Size; int NewBrSize = 0; TII->insertUnconditionalBranch(*MBB, DestBB, DL, &NewBrSize); BBSize += NewBrSize; }; auto insertBranch = [&](MachineBasicBlock *MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, SmallVectorImpl<MachineOperand>& Cond) { unsigned &BBSize = BlockInfo[MBB->getNumber()].Size; int NewBrSize = 0; TII->insertBranch(*MBB, TBB, FBB, Cond, DL, &NewBrSize); BBSize += NewBrSize; }; auto removeBranch = [&](MachineBasicBlock *MBB) { unsigned &BBSize = BlockInfo[MBB->getNumber()].Size; int RemovedSize = 0; TII->removeBranch(*MBB, &RemovedSize); BBSize -= RemovedSize; }; auto finalizeBlockChanges = [&](MachineBasicBlock *MBB, MachineBasicBlock *NewBB) { // Keep the block offsets up to date. adjustBlockOffsets(*MBB); // Need to fix live-in lists if we track liveness. if (NewBB && TRI->trackLivenessAfterRegAlloc(*MF)) computeAndAddLiveIns(LiveRegs, *NewBB); }; bool Fail = TII->analyzeBranch(*MBB, TBB, FBB, Cond); assert(!Fail && "branches to be relaxed must be analyzable"); (void)Fail; // Add an unconditional branch to the destination and invert the branch // condition to jump over it: // tbz L1 // => // tbnz L2 // b L1 // L2: bool ReversedCond = !TII->reverseBranchCondition(Cond); if (ReversedCond) { if (FBB && isBlockInRange(MI, *FBB)) { // Last MI in the BB is an unconditional branch. We can simply invert the // condition and swap destinations: // beq L1 // b L2 // => // bne L2 // b L1 LLVM_DEBUG(dbgs() << " Invert condition and swap " "its destination with " << MBB->back()); removeBranch(MBB); insertBranch(MBB, FBB, TBB, Cond); finalizeBlockChanges(MBB, nullptr); return true; } if (FBB) { // We need to split the basic block here to obtain two long-range // unconditional branches. NewBB = createNewBlockAfter(*MBB); insertUncondBranch(NewBB, FBB); // Update the succesor lists according to the transformation to follow. // Do it here since if there's no split, no update is needed. MBB->replaceSuccessor(FBB, NewBB); NewBB->addSuccessor(FBB); } // We now have an appropriate fall-through block in place (either naturally or // just created), so we can use the inverted the condition. MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB)); LLVM_DEBUG(dbgs() << " Insert B to " << printMBBReference(*TBB) << ", invert condition and change dest. to " << printMBBReference(NextBB) << '\n'); removeBranch(MBB); // Insert a new conditional branch and a new unconditional branch. insertBranch(MBB, &NextBB, TBB, Cond); finalizeBlockChanges(MBB, NewBB); return true; } // Branch cond can't be inverted. // In this case we always add a block after the MBB. LLVM_DEBUG(dbgs() << " The branch condition can't be inverted. " << " Insert a new BB after " << MBB->back()); if (!FBB) FBB = &(*std::next(MachineFunction::iterator(MBB))); // This is the block with cond. branch and the distance to TBB is too long. // beq L1 // L2: // We do the following transformation: // beq NewBB // b L2 // NewBB: // b L1 // L2: NewBB = createNewBlockAfter(*MBB); insertUncondBranch(NewBB, TBB); LLVM_DEBUG(dbgs() << " Insert cond B to the new BB " << printMBBReference(*NewBB) << " Keep the exiting condition.\n" << " Insert B to " << printMBBReference(*FBB) << ".\n" << " In the new BB: Insert B to " << printMBBReference(*TBB) << ".\n"); // Update the successor lists according to the transformation to follow. MBB->replaceSuccessor(TBB, NewBB); NewBB->addSuccessor(TBB); // Replace branch in the current (MBB) block. removeBranch(MBB); insertBranch(MBB, NewBB, FBB, Cond); finalizeBlockChanges(MBB, NewBB); return true; }
// Expand branch instructions to long branches. // TODO: This function has to be fixed for beqz16 and bnez16, because it // currently assumes that all branches have 16-bit offsets, and will produce // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] // are present. void MipsLongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>(MF->getSubtarget()); const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->replaceSuccessor(TgtMBB, LongBrMBB); if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); // We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an // pseudo-instruction wrapping BGEZAL). unsigned BalOp = Subtarget.hasMips32r6() ? Mips::BAL : Mips::BAL_BR; if (!ABI.IsN64()) { // $longbr: // addiu $sp, $sp, -8 // sw $ra, 0($sp) // lui $at, %hi($tgt - $baltgt) // bal $baltgt // addiu $at, $at, %lo($tgt - $baltgt) // $baltgt: // addu $at, $ra, $at // lw $ra, 0($sp) // jr $at // addiu $sp, $sp, 8 // $fallthrough: // Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(-8); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA) .addReg(Mips::SP).addImm(0); // LUi and ADDiu instructions create 32-bit offset of the target basic // block from the target of BAL instruction. We cannot use immediate // value for this offset because it cannot be determined accurately when // the program has inline assembly statements. We therefore use the // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which // are resolved during the fixup, so the values will always be correct. // // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) // expressions at this point (it is possible only at the MC layer), // we replace LUi and ADDiu with pseudo instructions // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic // blocks as operands to these instructions. When lowering these pseudo // instructions to LUi and ADDiu in the MC layer, we will create // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as // operands to lowered instructions. BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT) .addMBB(TgtMBB).addMBB(BalTgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) .addReg(Mips::AT) .addMBB(TgtMBB) .addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) .addReg(Mips::RA).addReg(Mips::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); if (!Subtarget.isTargetNaCl()) { MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8)); } else { // In NaCl, modifying the sp is not allowed in branch delay slot. BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); // Bundle-align the target of indirect branch JR. TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); } } else { // $longbr: // daddiu $sp, $sp, -16 // sd $ra, 0($sp) // daddiu $at, $zero, %hi($tgt - $baltgt) // dsll $at, $at, 16 // bal $baltgt // daddiu $at, $at, %lo($tgt - $baltgt) // $baltgt: // daddu $at, $ra, $at // ld $ra, 0($sp) // jr64 $at // daddiu $sp, $sp, 16 // $fallthrough: // // We assume the branch is within-function, and that offset is within // +/- 2GB. High 32 bits will therefore always be zero. // Note that this will work even if the offset is negative, because // of the +1 modification that's added in that case. For example, if the // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is // // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000 // // and the bits [47:32] are zero. For %highest // // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000 // // and the bits [63:48] are zero. Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(-16); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64) .addReg(Mips::SP_64).addImm(0); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64).addReg(Mips::ZERO_64) .addMBB(TgtMBB, MipsII::MO_ABS_HI).addMBB(BalTgtMBB); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) .addReg(Mips::AT_64).addImm(16); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)) .append( BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) .addReg(Mips::AT_64) .addMBB(TgtMBB, MipsII::MO_ABS_LO) .addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) .addReg(Mips::RA_64).addReg(Mips::AT_64); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) .addReg(Mips::SP_64).addImm(0); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64)) .append(BuildMI(*MF, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64).addImm(16)); } assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize); } else { // $longbr: // j $tgt // nop // $fallthrough: // Pos = LongBrMBB->begin(); LongBrMBB->addSuccessor(TgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::J)).addMBB(TgtMBB)) .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); assert(LongBrMBB->size() == LongBranchSeqSize); } if (I.Br->isUnconditionalBranch()) { // Change branch destination. assert(I.Br->getDesc().getNumOperands() == 1); I.Br->RemoveOperand(0); I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); } else // Change branch destination and reverse condition. replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); }
/// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr &MI) { MachineBasicBlock *DestBB = getDestBlock(MI); // Add an unconditional branch to the destination and invert the branch // condition to jump over it: // tbz L1 // => // tbnz L2 // b L1 // L2: // If the branch is at the end of its MBB and that has a fall-through block, // direct the updated conditional branch to the fall-through block. Otherwise, // split the MBB before the next instruction. MachineBasicBlock *MBB = MI.getParent(); MachineInstr *BMI = &MBB->back(); bool NeedSplit = (BMI != &MI) || !hasFallthrough(*MBB); if (BMI != &MI) { if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->getLastNonDebugInstr()) && BMI->isUnconditionalBranch()) { // Last MI in the BB is an unconditional branch. We can simply invert the // condition and swap destinations: // beq L1 // b L2 // => // bne L2 // b L1 MachineBasicBlock *NewDest = getDestBlock(*BMI); if (isBlockInRange(MI, *NewDest)) { DEBUG(dbgs() << " Invert condition and swap its destination with " << *BMI); changeBranchDestBlock(*BMI, *DestBB); int NewSize = insertInvertedConditionalBranch(*MBB, MI.getIterator(), MI.getDebugLoc(), MI, *NewDest); int OldSize = TII->getInstSizeInBytes(MI); BlockInfo[MBB->getNumber()].Size += (NewSize - OldSize); MI.eraseFromParent(); return true; } } } if (NeedSplit) { // Analyze the branch so we know how to update the successor lists. MachineBasicBlock *TBB = nullptr, *FBB = nullptr; SmallVector<MachineOperand, 2> Cond; bool Fail = TII->analyzeBranch(*MBB, TBB, FBB, Cond, false); assert(!Fail && "branches to relax should be analyzable"); (void)Fail; MachineBasicBlock *NewBB = splitBlockBeforeInstr(MI); // No need for the branch to the next block. We're adding an unconditional // branch to the destination. int delta = TII->getInstSizeInBytes(MBB->back()); BlockInfo[MBB->getNumber()].Size -= delta; MBB->back().eraseFromParent(); // BlockInfo[SplitBB].Offset is wrong temporarily, fixed below // Update the successor lists according to the transformation to follow. // Do it here since if there's no split, no update is needed. MBB->replaceSuccessor(FBB, NewBB); NewBB->addSuccessor(FBB); } MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB)); DEBUG(dbgs() << " Insert B to BB#" << DestBB->getNumber() << ", invert condition and change dest. to BB#" << NextBB.getNumber() << '\n'); unsigned &MBBSize = BlockInfo[MBB->getNumber()].Size; // Insert a new conditional branch and a new unconditional branch. MBBSize += insertInvertedConditionalBranch(*MBB, MBB->end(), MI.getDebugLoc(), MI, NextBB); MBBSize += insertUnconditionalBranch(*MBB, *DestBB, MI.getDebugLoc()); // Remove the old conditional branch. It may or may not still be in MBB. MBBSize -= TII->getInstSizeInBytes(MI); MI.eraseFromParent(); // Finally, keep the block offsets up to date. adjustBlockOffsets(*MBB); return true; }
// Expand branch instructions to long branches. // TODO: This function has to be fixed for beqz16 and bnez16, because it // currently assumes that all branches have 16-bit offsets, and will produce // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] // are present. void Cpu0LongBranch::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); const Cpu0Subtarget &Subtarget = static_cast<const Cpu0Subtarget &>(MF->getSubtarget()); const Cpu0InstrInfo *TII = static_cast<const Cpu0InstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->replaceSuccessor(TgtMBB, LongBrMBB); if (IsPIC) { MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); MF->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); unsigned BalOp = Cpu0::BAL; // $longbr: // addiu $sp, $sp, -8 // st $lr, 0($sp) // lui $at, %hi($tgt - $baltgt) // addiu $lr, $lr, %lo($tgt - $baltgt) // bal $baltgt // nop // $baltgt: // addu $at, $lr, $at // addiu $sp, $sp, 8 // ld $lr, 0($sp) // jr $at // nop // $fallthrough: // Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::ADDiu), Cpu0::SP) .addReg(Cpu0::SP).addImm(-8); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::ST)).addReg(Cpu0::LR) .addReg(Cpu0::SP).addImm(0); // LUi and ADDiu instructions create 32-bit offset of the target basic // block from the target of BAL instruction. We cannot use immediate // value for this offset because it cannot be determined accurately when // the program has inline assembly statements. We therefore use the // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which // are resolved during the fixup, so the values will always be correct. // // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt) // expressions at this point (it is possible only at the MC layer), // we replace LUi and ADDiu with pseudo instructions // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic // blocks as operands to these instructions. When lowering these pseudo // instructions to LUi and ADDiu in the MC layer, we will create // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as // operands to lowered instructions. BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::LONG_BRANCH_LUi), Cpu0::AT) .addMBB(TgtMBB).addMBB(BalTgtMBB); BuildMI(*LongBrMBB, Pos, DL, TII->get(Cpu0::LONG_BRANCH_ADDiu), Cpu0::AT) .addReg(Cpu0::AT).addMBB(TgtMBB).addMBB(BalTgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB)); Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::ADDu), Cpu0::AT) .addReg(Cpu0::LR).addReg(Cpu0::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::LD), Cpu0::LR) .addReg(Cpu0::SP).addImm(0); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Cpu0::ADDiu), Cpu0::SP) .addReg(Cpu0::SP).addImm(8); MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Cpu0::JR)).addReg(Cpu0::AT)) .append(BuildMI(*MF, DL, TII->get(Cpu0::NOP))); assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize); } else { // $longbr: // jmp $tgt // nop // $fallthrough: // Pos = LongBrMBB->begin(); LongBrMBB->addSuccessor(TgtMBB); MIBundleBuilder(*LongBrMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Cpu0::JMP)).addMBB(TgtMBB)) .append(BuildMI(*MF, DL, TII->get(Cpu0::NOP))); assert(LongBrMBB->size() == LongBranchSeqSize); } if (I.Br->isUnconditionalBranch()) { // Change branch destination. assert(I.Br->getDesc().getNumOperands() == 1); I.Br->RemoveOperand(0); I.Br->addOperand(MachineOperand::CreateMBB(LongBrMBB)); } else // Change branch destination and reverse condition. replaceBranch(*MBB, I.Br, DL, &*FallThroughMBB); }
/// fixupConditionalBranch - Fix up a conditional branch whose destination is /// too far away to fit in its displacement field. It is converted to an inverse /// conditional branch + an unconditional branch to the destination. bool AArch64BranchRelaxation::fixupConditionalBranch(MachineInstr &MI) { DebugLoc DL = MI.getDebugLoc(); MachineBasicBlock *MBB = MI.getParent(); MachineBasicBlock *TBB = nullptr, *FBB = nullptr; SmallVector<MachineOperand, 4> Cond; bool Fail = TII->analyzeBranch(*MBB, TBB, FBB, Cond); assert(!Fail && "branches to be relaxed must be analyzable"); (void)Fail; // Add an unconditional branch to the destination and invert the branch // condition to jump over it: // tbz L1 // => // tbnz L2 // b L1 // L2: if (FBB && isBlockInRange(MI, *FBB)) { // Last MI in the BB is an unconditional branch. We can simply invert the // condition and swap destinations: // beq L1 // b L2 // => // bne L2 // b L1 DEBUG(dbgs() << " Invert condition and swap " "its destination with " << MBB->back()); TII->reverseBranchCondition(Cond); int OldSize = 0, NewSize = 0; TII->removeBranch(*MBB, &OldSize); TII->insertBranch(*MBB, FBB, TBB, Cond, DL, &NewSize); BlockInfo[MBB->getNumber()].Size += (NewSize - OldSize); return true; } else if (FBB) { // We need to split the basic block here to obtain two long-range // unconditional branches. auto &NewBB = *MF->CreateMachineBasicBlock(MBB->getBasicBlock()); MF->insert(++MBB->getIterator(), &NewBB); // Insert an entry into BlockInfo to align it properly with the block // numbers. BlockInfo.insert(BlockInfo.begin() + NewBB.getNumber(), BasicBlockInfo()); unsigned &NewBBSize = BlockInfo[NewBB.getNumber()].Size; int NewBrSize; TII->insertUnconditionalBranch(NewBB, FBB, DL, &NewBrSize); NewBBSize += NewBrSize; // Update the successor lists according to the transformation to follow. // Do it here since if there's no split, no update is needed. MBB->replaceSuccessor(FBB, &NewBB); NewBB.addSuccessor(FBB); } // We now have an appropriate fall-through block in place (either naturally or // just created), so we can invert the condition. MachineBasicBlock &NextBB = *std::next(MachineFunction::iterator(MBB)); DEBUG(dbgs() << " Insert B to BB#" << TBB->getNumber() << ", invert condition and change dest. to BB#" << NextBB.getNumber() << '\n'); unsigned &MBBSize = BlockInfo[MBB->getNumber()].Size; // Insert a new conditional branch and a new unconditional branch. int RemovedSize = 0; TII->reverseBranchCondition(Cond); TII->removeBranch(*MBB, &RemovedSize); MBBSize -= RemovedSize; int AddedSize = 0; TII->insertBranch(*MBB, &NextBB, TBB, Cond, DL, &AddedSize); MBBSize += AddedSize; // Finally, keep the block offsets up to date. adjustBlockOffsets(*MBB); return true; }