/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. /// void PEI::replaceFrameIndices(MachineFunction &Fn) { if (!Fn.getFrameInfo()->hasStackObjects()) return; // Nothing to do? // Store SPAdj at exit of a basic block. SmallVector<int, 8> SPState; SPState.resize(Fn.getNumBlockIDs()); SmallPtrSet<MachineBasicBlock*, 8> Reachable; // Iterate over the reachable blocks in DFS order. for (df_ext_iterator<MachineFunction*, SmallPtrSet<MachineBasicBlock*, 8> > DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); DFI != DFE; ++DFI) { int SPAdj = 0; // Check the exit state of the DFS stack predecessor. if (DFI.getPathLength() >= 2) { MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); assert(Reachable.count(StackPred) && "DFS stack predecessor is already visited.\n"); SPAdj = SPState[StackPred->getNumber()]; } MachineBasicBlock *BB = *DFI; replaceFrameIndices(BB, Fn, SPAdj); SPState[BB->getNumber()] = SPAdj; } // Handle the unreachable blocks. for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { if (Reachable.count(BB)) // Already handled in DFS traversal. continue; int SPAdj = 0; replaceFrameIndices(BB, Fn, SPAdj); } }
/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. void PEI::replaceFrameIndices(MachineFunction &MF) { const TargetFrameLowering &TFI = *MF.getSubtarget().getFrameLowering(); if (!TFI.needsFrameIndexResolution(MF)) return; // Store SPAdj at exit of a basic block. SmallVector<int, 8> SPState; SPState.resize(MF.getNumBlockIDs()); df_iterator_default_set<MachineBasicBlock*> Reachable; // Iterate over the reachable blocks in DFS order. for (auto DFI = df_ext_begin(&MF, Reachable), DFE = df_ext_end(&MF, Reachable); DFI != DFE; ++DFI) { int SPAdj = 0; // Check the exit state of the DFS stack predecessor. if (DFI.getPathLength() >= 2) { MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); assert(Reachable.count(StackPred) && "DFS stack predecessor is already visited.\n"); SPAdj = SPState[StackPred->getNumber()]; } MachineBasicBlock *BB = *DFI; replaceFrameIndices(BB, MF, SPAdj); SPState[BB->getNumber()] = SPAdj; } // Handle the unreachable blocks. for (auto &BB : MF) { if (Reachable.count(&BB)) // Already handled in DFS traversal. continue; int SPAdj = 0; replaceFrameIndices(&BB, MF, SPAdj); } }
/// Insert BLOCK markers at appropriate places. static void PlaceBlockMarkers(MachineBasicBlock &MBB, MachineBasicBlock &Succ, MachineFunction &MF, const MachineLoopInfo &MLI, const WebAssemblyInstrInfo &TII) { // Backward branches are loop backedges, and we place the LOOP markers // separately. So only consider forward branches here. if (Succ.getNumber() <= MBB.getNumber()) return; // Place the BLOCK for a forward branch. For simplicity, we just insert // blocks immediately inside loop boundaries. MachineLoop *Loop = MLI.getLoopFor(&Succ); MachineBasicBlock &Header = *(Loop ? Loop->getHeader() : &MF.front()); MachineBasicBlock::iterator InsertPos = Header.begin(), End = Header.end(); if (InsertPos != End) { if (InsertPos->getOpcode() == WebAssembly::LOOP) ++InsertPos; int SuccNumber = Succ.getNumber(); // Position the BLOCK in nesting order. for (; InsertPos != End && InsertPos->getOpcode() == WebAssembly::BLOCK; ++InsertPos) { int N = InsertPos->getOperand(0).getMBB()->getNumber(); if (N < SuccNumber) break; // If there's already a BLOCK for Succ, we don't need another. if (N == SuccNumber) return; } } BuildMI(Header, InsertPos, DebugLoc(), TII.get(WebAssembly::BLOCK)) .addMBB(&Succ); }
/// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). static void PlaceLoopMarker(MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl<MachineBasicBlock *> &ScopeTops, const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) { MachineLoop *Loop = MLI.getLoopFor(&MBB); if (!Loop || Loop->getHeader() != &MBB) return; // The operand of a LOOP is the first block after the loop. If the loop is the // bottom of the function, insert a dummy block at the end. MachineBasicBlock *Bottom = LoopBottom(Loop); auto Iter = next(MachineFunction::iterator(Bottom)); if (Iter == MF.end()) { MachineBasicBlock *Label = MF.CreateMachineBasicBlock(); // Give it a fake predecessor so that AsmPrinter prints its label. Label->addSuccessor(Label); MF.push_back(Label); Iter = next(MachineFunction::iterator(Bottom)); } MachineBasicBlock *AfterLoop = &*Iter; BuildMI(MBB, MBB.begin(), DebugLoc(), TII.get(WebAssembly::LOOP)) .addMBB(AfterLoop); // Emit a special no-op telling the asm printer that we need a label to close // the loop scope, even though the destination is only reachable by // fallthrough. if (!Bottom->back().isBarrier()) BuildMI(*Bottom, Bottom->end(), DebugLoc(), TII.get(WebAssembly::LOOP_END)); assert((!ScopeTops[AfterLoop->getNumber()] || ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && "With RPO we should visit the outer-most loop for a block first."); if (!ScopeTops[AfterLoop->getNumber()]) ScopeTops[AfterLoop->getNumber()] = &MBB; }
void MIRPrinter::convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB) { assert(MBB.getNumber() >= 0 && "Invalid MBB number"); YamlMBB.ID = (unsigned)MBB.getNumber(); // TODO: Serialize unnamed BB references. if (const auto *BB = MBB.getBasicBlock()) YamlMBB.Name.Value = BB->hasName() ? BB->getName() : "<unnamed bb>"; else YamlMBB.Name.Value = ""; YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); for (const auto *SuccMBB : MBB.successors()) { std::string Str; raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds).printMBBReference(*SuccMBB); YamlMBB.Successors.push_back(StrOS.str()); } // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); std::string Str; for (const auto &MI : MBB) { raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds).print(MI); YamlMBB.Instructions.push_back(StrOS.str()); Str.clear(); } }
/// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. /// void PEI::replaceFrameIndices(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); if (!TFI.needsFrameIndexResolution(Fn)) return; MachineModuleInfo &MMI = Fn.getMMI(); const Function *F = Fn.getFunction(); const Function *ParentF = MMI.getWinEHParent(F); unsigned FrameReg; if (F == ParentF) { WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(Fn.getFunction()); // FIXME: This should be unconditional but we have bugs in the preparation // pass. if (FuncInfo.UnwindHelpFrameIdx != INT_MAX) FuncInfo.UnwindHelpFrameOffset = TFI.getFrameIndexReferenceFromSP( Fn, FuncInfo.UnwindHelpFrameIdx, FrameReg); for (WinEHTryBlockMapEntry &TBME : FuncInfo.TryBlockMap) { for (WinEHHandlerType &H : TBME.HandlerArray) { unsigned UnusedReg; if (H.CatchObj.FrameIndex == INT_MAX) H.CatchObj.FrameOffset = INT_MAX; else H.CatchObj.FrameOffset = TFI.getFrameIndexReference(Fn, H.CatchObj.FrameIndex, UnusedReg); } } } // Store SPAdj at exit of a basic block. SmallVector<int, 8> SPState; SPState.resize(Fn.getNumBlockIDs()); SmallPtrSet<MachineBasicBlock*, 8> Reachable; // Iterate over the reachable blocks in DFS order. for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); DFI != DFE; ++DFI) { int SPAdj = 0; // Check the exit state of the DFS stack predecessor. if (DFI.getPathLength() >= 2) { MachineBasicBlock *StackPred = DFI.getPath(DFI.getPathLength() - 2); assert(Reachable.count(StackPred) && "DFS stack predecessor is already visited.\n"); SPAdj = SPState[StackPred->getNumber()]; } MachineBasicBlock *BB = *DFI; replaceFrameIndices(BB, Fn, SPAdj); SPState[BB->getNumber()] = SPAdj; } // Handle the unreachable blocks. for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) { if (Reachable.count(BB)) // Already handled in DFS traversal. continue; int SPAdj = 0; replaceFrameIndices(BB, Fn, SPAdj); } }
/// Split the basic block containing MI into two blocks, which are joined by /// an unconditional branch. Update data structures and renumber blocks to /// account for this change and returns the newly created block. MachineBasicBlock *BranchRelaxation::splitBlockBeforeInstr(MachineInstr &MI, MachineBasicBlock *DestBB) { MachineBasicBlock *OrigBB = MI.getParent(); // Create a new MBB for the code after the OrigBB. MachineBasicBlock *NewBB = MF->CreateMachineBasicBlock(OrigBB->getBasicBlock()); MF->insert(++OrigBB->getIterator(), NewBB); // Splice the instructions starting with MI over to NewBB. NewBB->splice(NewBB->end(), OrigBB, MI.getIterator(), OrigBB->end()); // Add an unconditional branch from OrigBB to NewBB. // Note the new unconditional branch is not being recorded. // There doesn't seem to be meaningful DebugInfo available; this doesn't // correspond to anything in the source. TII->insertUnconditionalBranch(*OrigBB, NewBB, DebugLoc()); // Insert an entry into BlockInfo to align it properly with the block numbers. BlockInfo.insert(BlockInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); NewBB->transferSuccessors(OrigBB); OrigBB->addSuccessor(NewBB); OrigBB->addSuccessor(DestBB); // Cleanup potential unconditional branch to successor block. // Note that updateTerminator may change the size of the blocks. NewBB->updateTerminator(); OrigBB->updateTerminator(); // Figure out how large the OrigBB is. As the first half of the original // block, it cannot contain a tablejump. The size includes // the new jump we added. (It should be possible to do this without // recounting everything, but it's very confusing, and this is rarely // executed.) BlockInfo[OrigBB->getNumber()].Size = computeBlockSize(*OrigBB); // Figure out how large the NewMBB is. As the second half of the original // block, it may contain a tablejump. BlockInfo[NewBB->getNumber()].Size = computeBlockSize(*NewBB); // All BBOffsets following these blocks must be modified. adjustBlockOffsets(*OrigBB); // Need to fix live-in lists if we track liveness. if (TRI->trackLivenessAfterRegAlloc(*MF)) computeLiveIns(LiveRegs, *TRI, *NewBB); ++NumSplit; return NewBB; }
void MIRPrinter::convert(ModuleSlotTracker &MST, yaml::MachineBasicBlock &YamlMBB, const MachineBasicBlock &MBB) { assert(MBB.getNumber() >= 0 && "Invalid MBB number"); YamlMBB.ID = (unsigned)MBB.getNumber(); if (const auto *BB = MBB.getBasicBlock()) { if (BB->hasName()) { YamlMBB.Name.Value = BB->getName(); } else { int Slot = MST.getLocalSlot(BB); if (Slot == -1) YamlMBB.IRBlock.Value = "<badref>"; else YamlMBB.IRBlock.Value = (Twine("%ir-block.") + Twine(Slot)).str(); } } YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); for (const auto *SuccMBB : MBB.successors()) { std::string Str; raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping) .printMBBReference(*SuccMBB); YamlMBB.Successors.push_back(StrOS.str()); } if (MBB.hasSuccessorWeights()) { for (auto I = MBB.succ_begin(), E = MBB.succ_end(); I != E; ++I) YamlMBB.SuccessorWeights.push_back( yaml::UnsignedValue(MBB.getSuccWeight(I))); } // Print the live in registers. const auto *TRI = MBB.getParent()->getSubtarget().getRegisterInfo(); assert(TRI && "Expected target register info"); for (auto I = MBB.livein_begin(), E = MBB.livein_end(); I != E; ++I) { std::string Str; raw_string_ostream StrOS(Str); printReg(*I, StrOS, TRI); YamlMBB.LiveIns.push_back(StrOS.str()); } // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); std::string Str; for (const auto &MI : MBB) { raw_string_ostream StrOS(Str); MIPrinter(StrOS, MST, RegisterMaskIds, StackObjectOperandMapping).print(MI); YamlMBB.Instructions.push_back(StrOS.str()); Str.clear(); } }
/// enterIntvAtEnd - Enter openli at the end of MBB. /// PhiMBB is a successor inside openli where a PHI value is created. /// Currently, all entries must share the same PhiMBB. void SplitEditor::enterIntvAtEnd(MachineBasicBlock &A, MachineBasicBlock &B) { assert(openli_ && "openIntv not called before enterIntvAtEnd"); SlotIndex EndA = lis_.getMBBEndIdx(&A); VNInfo *CurVNIA = curli_->getVNInfoAt(EndA.getPrevIndex()); if (!CurVNIA) { DEBUG(dbgs() << " enterIntvAtEnd, curli not live out of BB#" << A.getNumber() << ".\n"); return; } // Add a phi kill value and live range out of A. VNInfo *VNIA = insertCopy(*openli_, A, A.getFirstTerminator()); openli_->addRange(LiveRange(VNIA->def, EndA, VNIA)); // FIXME: If this is the only entry edge, we don't need the extra PHI value. // FIXME: If there are multiple entry blocks (so not a loop), we need proper // SSA update. // Now look at the start of B. SlotIndex StartB = lis_.getMBBStartIdx(&B); SlotIndex EndB = lis_.getMBBEndIdx(&B); const LiveRange *CurB = curli_->getLiveRangeContaining(StartB); if (!CurB) { DEBUG(dbgs() << " enterIntvAtEnd: curli not live in to BB#" << B.getNumber() << ".\n"); return; } VNInfo *VNIB = openli_->getVNInfoAt(StartB); if (!VNIB) { // Create a phi value. VNIB = openli_->getNextValue(SlotIndex(StartB, true), 0, false, lis_.getVNInfoAllocator()); VNIB->setIsPHIDef(true); VNInfo *&mapVNI = valueMap_[CurB->valno]; if (mapVNI) { // Multiple copies - must create PHI value. abort(); } else { // This is the first copy of dupLR. Mark the mapping. mapVNI = VNIB; } } DEBUG(dbgs() << " enterIntvAtEnd: " << *openli_ << '\n'); }
// Transfer information from the LiveIn vector to the live ranges. void LiveRangeCalc::updateLiveIns() { LiveRangeUpdater Updater; for (SmallVectorImpl<LiveInBlock>::iterator I = LiveIn.begin(), E = LiveIn.end(); I != E; ++I) { if (!I->DomNode) continue; MachineBasicBlock *MBB = I->DomNode->getBlock(); assert(I->Value && "No live-in value found"); SlotIndex Start, End; std::tie(Start, End) = Indexes->getMBBRange(MBB); if (I->Kill.isValid()) // Value is killed inside this block. End = I->Kill; else { // The value is live-through, update LiveOut as well. // Defer the Domtree lookup until it is needed. assert(Seen.test(MBB->getNumber())); LiveOut[MBB] = LiveOutPair(I->Value, (MachineDomTreeNode *)0); } Updater.setDest(&I->LR); Updater.add(Start, End, I->Value); } LiveIn.clear(); }
void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) { OS << "%bb." << MBB.getNumber(); if (const auto *BB = MBB.getBasicBlock()) { if (BB->hasName()) OS << '.' << BB->getName(); } }
// Transfer information from the LiveIn vector to the live ranges. void LiveRangeCalc::updateLiveIns(VNInfo *OverrideVNI) { for (SmallVectorImpl<LiveInBlock>::iterator I = LiveIn.begin(), E = LiveIn.end(); I != E; ++I) { if (!I->DomNode) continue; MachineBasicBlock *MBB = I->DomNode->getBlock(); VNInfo *VNI = OverrideVNI ? OverrideVNI : I->Value; assert(VNI && "No live-in value found"); SlotIndex Start, End; tie(Start, End) = Indexes->getMBBRange(MBB); if (I->Kill.isValid()) I->LI->addRange(LiveRange(Start, I->Kill, VNI)); else { I->LI->addRange(LiveRange(Start, End, VNI)); // The value is live-through, update LiveOut as well. Defer the Domtree // lookup until it is needed. assert(Seen.test(MBB->getNumber())); LiveOut[MBB] = LiveOutPair(VNI, (MachineDomTreeNode *)0); } } LiveIn.clear(); }
/// Return the "bottom" block of a loop. This differs from /// MachineLoop::getBottomBlock in that it works even if the loop is /// discontiguous. static MachineBasicBlock *LoopBottom(const MachineLoop *Loop) { MachineBasicBlock *Bottom = Loop->getHeader(); for (MachineBasicBlock *MBB : Loop->blocks()) if (MBB->getNumber() > Bottom->getNumber()) Bottom = MBB; return Bottom; }
/// isBlockInRange - Returns true if the distance between specific MI and /// specific BB can fit in MI's displacement field. bool AArch64BranchRelaxation::isBlockInRange( const MachineInstr &MI, const MachineBasicBlock &DestBB) const { unsigned BrOffset = getInstrOffset(MI); unsigned DestOffset = BlockInfo[DestBB.getNumber()].Offset; if (TII->isBranchInRange(MI.getOpcode(), BrOffset, DestOffset)) return true; DEBUG( dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber() << " from BB#" << MI.getParent()->getNumber() << " to " << DestOffset << " offset " << static_cast<int>(DestOffset - BrOffset) << '\t' << MI ); return false; }
/// isBlockInRange - Returns true if the distance between specific MI and /// specific BB can fit in MI's displacement field. bool BranchRelaxation::isBlockInRange( const MachineInstr &MI, const MachineBasicBlock &DestBB) const { int64_t BrOffset = getInstrOffset(MI); int64_t DestOffset = BlockInfo[DestBB.getNumber()].Offset; if (TII->isBranchOffsetInRange(MI.getOpcode(), DestOffset - BrOffset)) return true; DEBUG( dbgs() << "Out of range branch to destination BB#" << DestBB.getNumber() << " from BB#" << MI.getParent()->getNumber() << " to " << DestOffset << " offset " << DestOffset - BrOffset << '\t' << MI ); return false; }
/// check BBOffsets void AArch64BranchFixup::verify() { #ifndef NDEBUG for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; unsigned MBBId = MBB->getNumber(); assert(!MBBId || BBInfo[MBBId - 1].postOffset() <= BBInfo[MBBId].Offset); } #endif }
void MCGSite::print(raw_ostream &OS) const { if (MI) { MachineBasicBlock *MBB = MI->getParent(); OS << "BB#" << MBB->getNumber() << ":" << std::distance(MBB->instr_begin(), MachineBasicBlock::instr_iterator(MI)) << ":"; } OS << *Caller << (IsInSCC ? " *--> " : " --> ") << *Callee; }
/// Insert a new empty basic block and insert it after \BB MachineBasicBlock *BranchRelaxation::createNewBlockAfter(MachineBasicBlock &BB) { // Create a new MBB for the code after the OrigBB. MachineBasicBlock *NewBB = MF->CreateMachineBasicBlock(BB.getBasicBlock()); MF->insert(++BB.getIterator(), NewBB); // Insert an entry into BlockInfo to align it properly with the block numbers. BlockInfo.insert(BlockInfo.begin() + NewBB->getNumber(), BasicBlockInfo()); return NewBB; }
/// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). static void PlaceLoopMarker( MachineBasicBlock &MBB, MachineFunction &MF, SmallVectorImpl<MachineBasicBlock *> &ScopeTops, DenseMap<const MachineInstr *, const MachineBasicBlock *> &LoopTops, const WebAssemblyInstrInfo &TII, const MachineLoopInfo &MLI) { MachineLoop *Loop = MLI.getLoopFor(&MBB); if (!Loop || Loop->getHeader() != &MBB) return; // The operand of a LOOP is the first block after the loop. If the loop is the // bottom of the function, insert a dummy block at the end. MachineBasicBlock *Bottom = LoopBottom(Loop); auto Iter = next(MachineFunction::iterator(Bottom)); if (Iter == MF.end()) { MachineBasicBlock *Label = MF.CreateMachineBasicBlock(); // Give it a fake predecessor so that AsmPrinter prints its label. Label->addSuccessor(Label); MF.push_back(Label); Iter = next(MachineFunction::iterator(Bottom)); } MachineBasicBlock *AfterLoop = &*Iter; // Mark the beginning of the loop (after the end of any existing loop that // ends here). auto InsertPos = MBB.begin(); while (InsertPos != MBB.end() && InsertPos->getOpcode() == WebAssembly::END_LOOP) ++InsertPos; BuildMI(MBB, InsertPos, DebugLoc(), TII.get(WebAssembly::LOOP)); // Mark the end of the loop. MachineInstr *End = BuildMI(*AfterLoop, AfterLoop->begin(), DebugLoc(), TII.get(WebAssembly::END_LOOP)); LoopTops[End] = &MBB; assert((!ScopeTops[AfterLoop->getNumber()] || ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && "With block sorting the outermost loop for a block should be first."); if (!ScopeTops[AfterLoop->getNumber()]) ScopeTops[AfterLoop->getNumber()] = &MBB; }
void AMDGPUAsmPrinter::EmitBasicBlockStart(const MachineBasicBlock &MBB) const { const GCNSubtarget &STI = MBB.getParent()->getSubtarget<GCNSubtarget>(); if (STI.dumpCode() && !isBlockOnlyReachableByFallthrough(&MBB)) { // Write a line for the basic block label if it is not only fallthrough. DisasmLines.push_back( (Twine("BB") + Twine(getFunctionNumber()) + "_" + Twine(MBB.getNumber()) + ":").str()); DisasmLineMaxLen = std::max(DisasmLineMaxLen, DisasmLines.back().size()); HexLines.push_back(""); } AsmPrinter::EmitBasicBlockStart(MBB); }
void AArch64BranchRelaxation::adjustBlockOffsets(MachineBasicBlock &Start) { unsigned PrevNum = Start.getNumber(); for (auto &MBB : make_range(MachineFunction::iterator(Start), MF->end())) { unsigned Num = MBB.getNumber(); if (!Num) // block zero is never changed from offset zero. continue; // Get the offset and known bits at the end of the layout predecessor. // Include the alignment of the current block. unsigned LogAlign = MBB.getAlignment(); BlockInfo[Num].Offset = BlockInfo[PrevNum].postOffset(LogAlign); PrevNum = Num; } }
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; }
/// verify - check BBOffsets, BBSizes, alignment of islands void ARM64BranchRelaxation::verify() { #ifndef NDEBUG unsigned PrevNum = MF->begin()->getNumber(); for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end(); MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; unsigned Align = MBB->getAlignment(); unsigned Num = MBB->getNumber(); assert(BlockInfo[Num].Offset % (1u << Align) == 0); assert(!Num || BlockInfo[PrevNum].postOffset() <= BlockInfo[Num].Offset); PrevNum = Num; } #endif }
/// getInstrOffset - Return the current offset of the specified machine /// instruction from the start of the function. This offset changes as stuff is /// moved around inside the function. unsigned AArch64BranchRelaxation::getInstrOffset(MachineInstr *MI) const { MachineBasicBlock *MBB = MI->getParent(); // The offset is composed of two things: the sum of the sizes of all MBB's // before this instruction's block, and the offset from the start of the block // it is in. unsigned Offset = BlockInfo[MBB->getNumber()].Offset; // Sum instructions before MI in MBB. for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { assert(I != MBB->end() && "Didn't find MI in its own basic block?"); Offset += TII->GetInstSizeInBytes(I); } return Offset; }
void LoopSplitter::dumpOddTerminators() { for (MachineFunction::iterator bbItr = mf->begin(), bbEnd = mf->end(); bbItr != bbEnd; ++bbItr) { MachineBasicBlock *mbb = &*bbItr; MachineBasicBlock *a = 0, *b = 0; SmallVector<MachineOperand, 4> c; if (tii->AnalyzeBranch(*mbb, a, b, c)) { dbgs() << "MBB#" << mbb->getNumber() << " has multiway terminator.\n"; dbgs() << " Terminators:\n"; for (MachineBasicBlock::iterator iItr = mbb->begin(), iEnd = mbb->end(); iItr != iEnd; ++iItr) { MachineInstr *instr= &*iItr; dbgs() << " " << *instr << ""; } dbgs() << "\n Listed successors: [ "; for (MachineBasicBlock::succ_iterator sItr = mbb->succ_begin(), sEnd = mbb->succ_end(); sItr != sEnd; ++sItr) { MachineBasicBlock *succMBB = *sItr; dbgs() << succMBB->getNumber() << " "; } dbgs() << "]\n\n"; } } }
void ARM64BranchRelaxation::adjustBlockOffsets(MachineBasicBlock *Start) { unsigned PrevNum = Start->getNumber(); MachineFunction::iterator MBBI = Start, E = MF->end(); for (++MBBI; MBBI != E; ++MBBI) { MachineBasicBlock *MBB = MBBI; unsigned Num = MBB->getNumber(); if (!Num) // block zero is never changed from offset zero. continue; // Get the offset and known bits at the end of the layout predecessor. // Include the alignment of the current block. unsigned LogAlign = MBBI->getAlignment(); BlockInfo[Num].Offset = BlockInfo[PrevNum].postOffset(LogAlign); PrevNum = Num; } }
MachineBasicBlock *PHIElimination::SplitCriticalEdge(MachineBasicBlock *A, MachineBasicBlock *B) { assert(A && B && "Missing MBB end point"); MachineFunction *MF = A->getParent(); // We may need to update A's terminator, but we can't do that if AnalyzeBranch // fails. If A uses a jump table, we won't touch it. const TargetInstrInfo *TII = MF->getTarget().getInstrInfo(); MachineBasicBlock *TBB = 0, *FBB = 0; SmallVector<MachineOperand, 4> Cond; if (TII->AnalyzeBranch(*A, TBB, FBB, Cond)) return NULL; ++NumSplits; MachineBasicBlock *NMBB = MF->CreateMachineBasicBlock(); MF->insert(llvm::next(MachineFunction::iterator(A)), NMBB); DEBUG(dbgs() << "PHIElimination splitting critical edge:" " BB#" << A->getNumber() << " -- BB#" << NMBB->getNumber() << " -- BB#" << B->getNumber() << '\n'); A->ReplaceUsesOfBlockWith(B, NMBB); A->updateTerminator(); // Insert unconditional "jump B" instruction in NMBB if necessary. NMBB->addSuccessor(B); if (!NMBB->isLayoutSuccessor(B)) { Cond.clear(); MF->getTarget().getInstrInfo()->InsertBranch(*NMBB, B, NULL, Cond); } // Fix PHI nodes in B so they refer to NMBB instead of A for (MachineBasicBlock::iterator i = B->begin(), e = B->end(); i != e && i->isPHI(); ++i) for (unsigned ni = 1, ne = i->getNumOperands(); ni != ne; ni += 2) if (i->getOperand(ni+1).getMBB() == A) i->getOperand(ni+1).setMBB(NMBB); if (LiveVariables *LV=getAnalysisIfAvailable<LiveVariables>()) LV->addNewBlock(NMBB, A, B); if (MachineDominatorTree *MDT=getAnalysisIfAvailable<MachineDominatorTree>()) MDT->addNewBlock(NMBB, A); return NMBB; }
static void VerifyPHIs(MachineFunction &MF, bool CheckExtra) { for (MachineFunction::iterator I = ++MF.begin(), E = MF.end(); I != E; ++I) { MachineBasicBlock *MBB = &*I; SmallSetVector<MachineBasicBlock *, 8> Preds(MBB->pred_begin(), MBB->pred_end()); MachineBasicBlock::iterator MI = MBB->begin(); while (MI != MBB->end()) { if (!MI->isPHI()) break; for (MachineBasicBlock *PredBB : Preds) { bool Found = false; for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) { MachineBasicBlock *PHIBB = MI->getOperand(i + 1).getMBB(); if (PHIBB == PredBB) { Found = true; break; } } if (!Found) { dbgs() << "Malformed PHI in " << printMBBReference(*MBB) << ": " << *MI; dbgs() << " missing input from predecessor " << printMBBReference(*PredBB) << '\n'; llvm_unreachable(nullptr); } } for (unsigned i = 1, e = MI->getNumOperands(); i != e; i += 2) { MachineBasicBlock *PHIBB = MI->getOperand(i + 1).getMBB(); if (CheckExtra && !Preds.count(PHIBB)) { dbgs() << "Warning: malformed PHI in " << printMBBReference(*MBB) << ": " << *MI; dbgs() << " extra input from predecessor " << printMBBReference(*PHIBB) << '\n'; llvm_unreachable(nullptr); } if (PHIBB->getNumber() < 0) { dbgs() << "Malformed PHI in " << printMBBReference(*MBB) << ": " << *MI; dbgs() << " non-existing " << printMBBReference(*PHIBB) << '\n'; llvm_unreachable(nullptr); } } ++MI; } } }
bool LiveVariables::VarInfo::isLiveIn(const MachineBasicBlock &MBB, unsigned Reg, MachineRegisterInfo &MRI) { unsigned Num = MBB.getNumber(); // Reg is live-through. if (AliveBlocks.test(Num)) return true; // Registers defined in MBB cannot be live in. const MachineInstr *Def = MRI.getVRegDef(Reg); if (Def && Def->getParent() == &MBB) return false; // Reg was not defined in MBB, was it killed here? return findKill(&MBB); }
SlotIndex SplitEditor::leaveIntvAtTop(MachineBasicBlock &MBB) { assert(OpenIdx && "openIntv not called before leaveIntvAtTop"); SlotIndex Start = LIS.getMBBStartIdx(&MBB); DEBUG(dbgs() << " leaveIntvAtTop BB#" << MBB.getNumber() << ", " << Start); VNInfo *ParentVNI = Edit->getParent().getVNInfoAt(Start); if (!ParentVNI) { DEBUG(dbgs() << ": not live\n"); return Start; } VNInfo *VNI = defFromParent(0, ParentVNI, Start, MBB, MBB.SkipPHIsAndLabels(MBB.begin())); RegAssign.insert(Start, VNI->def, OpenIdx); DEBUG(dump()); return VNI->def; }