bool MachineCSE::isPhysDefTriviallyDead(unsigned Reg, MachineBasicBlock::const_iterator I, MachineBasicBlock::const_iterator E) const { unsigned LookAheadLeft = LookAheadLimit; while (LookAheadLeft) { // Skip over dbg_value's. while (I != E && I->isDebugValue()) ++I; if (I == E) // Reached end of block, register is obviously dead. return true; bool SeenDef = false; for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { const MachineOperand &MO = I->getOperand(i); if (MO.isRegMask() && MO.clobbersPhysReg(Reg)) SeenDef = true; if (!MO.isReg() || !MO.getReg()) continue; if (!TRI->regsOverlap(MO.getReg(), Reg)) continue; if (MO.isUse()) // Found a use! return false; SeenDef = true; } if (SeenDef) // See a def of Reg (or an alias) before encountering any use, it's // trivially dead. return true; --LookAheadLeft; ++I; } return false; }
/// isBlockOnlyReachableByFallthough - Return true if the basic block has /// exactly one predecessor and the control transfer mechanism between /// the predecessor and this block is a fall-through. bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* MBB) const { // The predecessor has to be immediately before this block. const MachineBasicBlock *Pred = *MBB->pred_begin(); // If the predecessor is a switch statement, assume a jump table // implementation, so it is not a fall through. if (const BasicBlock *bb = Pred->getBasicBlock()) if (isa<SwitchInst>(bb->getTerminator())) return false; // If this is a landing pad, it isn't a fall through. If it has no preds, // then nothing falls through to it. if (MBB->isLandingPad() || MBB->pred_empty()) return false; // If there isn't exactly one predecessor, it can't be a fall through. MachineBasicBlock::const_pred_iterator PI = MBB->pred_begin(), PI2 = PI; ++PI2; if (PI2 != MBB->pred_end()) return false; // The predecessor has to be immediately before this block. if (!Pred->isLayoutSuccessor(MBB)) return false; // If the block is completely empty, then it definitely does fall through. if (Pred->empty()) return true; // Otherwise, check the last instruction. // Check if the last terminator is an unconditional branch. MachineBasicBlock::const_iterator I = Pred->end(); while (I != Pred->begin() && !(--I)->isTerminator()) ; return !I->isBarrier(); }
bool SIInsertSkips::shouldSkip(const MachineBasicBlock &From, const MachineBasicBlock &To) const { if (From.succ_empty()) return false; unsigned NumInstr = 0; const MachineFunction *MF = From.getParent(); for (MachineFunction::const_iterator MBBI(&From), ToI(&To), End = MF->end(); MBBI != End && MBBI != ToI; ++MBBI) { const MachineBasicBlock &MBB = *MBBI; for (MachineBasicBlock::const_iterator I = MBB.begin(), E = MBB.end(); NumInstr < SkipThreshold && I != E; ++I) { if (opcodeEmitsNoInsts(I->getOpcode())) continue; // FIXME: Since this is required for correctness, this should be inserted // during SILowerControlFlow. // When a uniform loop is inside non-uniform control flow, the branch // leaving the loop might be an S_CBRANCH_VCCNZ, which is never taken // when EXEC = 0. We should skip the loop lest it becomes infinite. if (I->getOpcode() == AMDGPU::S_CBRANCH_VCCNZ || I->getOpcode() == AMDGPU::S_CBRANCH_VCCZ) return true; if (TII->hasUnwantedEffectsWhenEXECEmpty(*I)) return true; ++NumInstr; if (NumInstr >= SkipThreshold) return true; } } return false; }
// isBlockOnlyReachableByFallthough - Return true if the basic block has // exactly one predecessor and the control transfer mechanism between // the predecessor and this block is a fall-through. // FIXME: could the overridden cases be handled in AnalyzeBranch? bool LanaiAsmPrinter::isBlockOnlyReachableByFallthrough( const MachineBasicBlock *MBB) const { // The predecessor has to be immediately before this block. const MachineBasicBlock *Pred = *MBB->pred_begin(); // If the predecessor is a switch statement, assume a jump table // implementation, so it is not a fall through. if (const BasicBlock *B = Pred->getBasicBlock()) if (isa<SwitchInst>(B->getTerminator())) return false; // Check default implementation if (!AsmPrinter::isBlockOnlyReachableByFallthrough(MBB)) return false; // Otherwise, check the last instruction. // Check if the last terminator is an unconditional branch. MachineBasicBlock::const_iterator I = Pred->end(); while (I != Pred->begin() && !(--I)->isTerminator()) { } return !I->isBarrier(); }
SlotIndex SplitAnalysis::computeLastSplitPoint(unsigned Num) { const MachineBasicBlock *MBB = MF.getBlockNumbered(Num); const MachineBasicBlock *LPad = MBB->getLandingPadSuccessor(); std::pair<SlotIndex, SlotIndex> &LSP = LastSplitPoint[Num]; // Compute split points on the first call. The pair is independent of the // current live interval. if (!LSP.first.isValid()) { MachineBasicBlock::const_iterator FirstTerm = MBB->getFirstTerminator(); if (FirstTerm == MBB->end()) LSP.first = LIS.getMBBEndIdx(MBB); else LSP.first = LIS.getInstructionIndex(FirstTerm); // If there is a landing pad successor, also find the call instruction. if (!LPad) return LSP.first; // There may not be a call instruction (?) in which case we ignore LPad. LSP.second = LSP.first; for (MachineBasicBlock::const_iterator I = MBB->end(), E = MBB->begin(); I != E;) { --I; if (I->getDesc().isCall()) { LSP.second = LIS.getInstructionIndex(I); break; } } } // If CurLI is live into a landing pad successor, move the last split point // back to the call that may throw. if (LPad && LSP.second.isValid() && LIS.isLiveInToMBB(*CurLI, LPad)) return LSP.second; else return LSP.first; }
DenseMap<const MachineBasicBlock *, int> llvm::getFuncletMembership(const MachineFunction &MF) { DenseMap<const MachineBasicBlock *, int> FuncletMembership; // We don't have anything to do if there aren't any EH pads. if (!MF.getMMI().hasEHFunclets()) return FuncletMembership; int EntryBBNumber = MF.front().getNumber(); bool IsSEH = isAsynchronousEHPersonality( classifyEHPersonality(MF.getFunction()->getPersonalityFn())); const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); SmallVector<const MachineBasicBlock *, 16> FuncletBlocks; SmallVector<const MachineBasicBlock *, 16> UnreachableBlocks; SmallVector<const MachineBasicBlock *, 16> SEHCatchPads; SmallVector<std::pair<const MachineBasicBlock *, int>, 16> CatchRetSuccessors; for (const MachineBasicBlock &MBB : MF) { if (MBB.isEHFuncletEntry()) { FuncletBlocks.push_back(&MBB); } else if (IsSEH && MBB.isEHPad()) { SEHCatchPads.push_back(&MBB); } else if (MBB.pred_empty()) { UnreachableBlocks.push_back(&MBB); } MachineBasicBlock::const_iterator MBBI = MBB.getFirstTerminator(); // CatchPads are not funclets for SEH so do not consider CatchRet to // transfer control to another funclet. if (MBBI->getOpcode() != TII->getCatchReturnOpcode()) continue; // FIXME: SEH CatchPads are not necessarily in the parent function: // they could be inside a finally block. const MachineBasicBlock *Successor = MBBI->getOperand(0).getMBB(); const MachineBasicBlock *SuccessorColor = MBBI->getOperand(1).getMBB(); CatchRetSuccessors.push_back( {Successor, IsSEH ? EntryBBNumber : SuccessorColor->getNumber()}); } // We don't have anything to do if there aren't any EH pads. if (FuncletBlocks.empty()) return FuncletMembership; // Identify all the basic blocks reachable from the function entry. collectFuncletMembers(FuncletMembership, EntryBBNumber, &MF.front()); // All blocks not part of a funclet are in the parent function. for (const MachineBasicBlock *MBB : UnreachableBlocks) collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); // Next, identify all the blocks inside the funclets. for (const MachineBasicBlock *MBB : FuncletBlocks) collectFuncletMembers(FuncletMembership, MBB->getNumber(), MBB); // SEH CatchPads aren't really funclets, handle them separately. for (const MachineBasicBlock *MBB : SEHCatchPads) collectFuncletMembers(FuncletMembership, EntryBBNumber, MBB); // Finally, identify all the targets of a catchret. for (std::pair<const MachineBasicBlock *, int> CatchRetPair : CatchRetSuccessors) collectFuncletMembers(FuncletMembership, CatchRetPair.second, CatchRetPair.first); return FuncletMembership; }
/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke /// has a try-range containing the call, a non-zero landing pad, and an /// appropriate action. The entry for an ordinary call has a try-range /// containing the call and zero for the landing pad and the action. Calls /// marked 'nounwind' have no entry and must not be contained in the try-range /// of any entry - they form gaps in the table. Entries must be ordered by /// try-range address. void DwarfException:: ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, const RangeMapType &PadMap, const SmallVectorImpl<const LandingPadInfo *> &LandingPads, const SmallVectorImpl<unsigned> &FirstActions) { // The end label of the previous invoke or nounwind try-range. MCSymbol *LastLabel = 0; // Whether there is a potentially throwing instruction (currently this means // an ordinary call) between the end of the previous try-range and now. bool SawPotentiallyThrowing = false; // Whether the last CallSite entry was for an invoke. bool PreviousIsInvoke = false; // Visit all instructions in order of address. for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (!MI->isLabel()) { if (MI->isCall()) SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); continue; } // End of the previous try-range? MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); if (BeginLabel == LastLabel) SawPotentiallyThrowing = false; // Beginning of a new try-range? RangeMapType::const_iterator L = PadMap.find(BeginLabel); if (L == PadMap.end()) // Nope, it was just some random label. continue; const PadRange &P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); // For Dwarf exception handling (SjLj handling doesn't use this). If some // instruction between the previous try-range and this one may throw, // create a call-site entry with no landing pad for the region between the // try-ranges. if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; CallSites.push_back(Site); PreviousIsInvoke = false; } LastLabel = LandingPad->EndLabels[P.RangeIndex]; assert(BeginLabel && LastLabel && "Invalid landing pad!"); if (!LandingPad->LandingPadLabel) { // Create a gap. PreviousIsInvoke = false; } else { // This try-range is for an invoke. CallSiteEntry Site = { BeginLabel, LastLabel, LandingPad->LandingPadLabel, FirstActions[P.PadIndex] }; // Try to merge with the previous call-site. SJLJ doesn't do this if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; continue; } } // Otherwise, create a new call-site. if (Asm->MAI->isExceptionHandlingDwarf()) CallSites.push_back(Site); else { // SjLj EH must maintain the call sites in the order assigned // to them by the SjLjPrepare pass. unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); if (CallSites.size() < SiteNo) CallSites.resize(SiteNo); CallSites[SiteNo - 1] = Site; } PreviousIsInvoke = true; } } } // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { CallSiteEntry Site = { LastLabel, 0, 0, 0 }; CallSites.push_back(Site); } }
void BT::run() { reset(); assert(FlowQ.empty()); typedef GraphTraits<const MachineFunction*> MachineFlowGraphTraits; const MachineBasicBlock *Entry = MachineFlowGraphTraits::getEntryNode(&MF); unsigned MaxBN = 0; for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { assert(I->getNumber() >= 0 && "Disconnected block"); unsigned BN = I->getNumber(); if (BN > MaxBN) MaxBN = BN; } // Keep track of visited blocks. BitVector BlockScanned(MaxBN+1); int EntryN = Entry->getNumber(); // Generate a fake edge to get something to start with. FlowQ.push(CFGEdge(-1, EntryN)); while (!FlowQ.empty()) { CFGEdge Edge = FlowQ.front(); FlowQ.pop(); if (EdgeExec.count(Edge)) continue; EdgeExec.insert(Edge); const MachineBasicBlock &B = *MF.getBlockNumbered(Edge.second); MachineBasicBlock::const_iterator It = B.begin(), End = B.end(); // Visit PHI nodes first. while (It != End && It->isPHI()) { const MachineInstr &PI = *It++; InstrExec.insert(&PI); visitPHI(PI); } // If this block has already been visited through a flow graph edge, // then the instructions have already been processed. Any updates to // the cells would now only happen through visitUsesOf... if (BlockScanned[Edge.second]) continue; BlockScanned[Edge.second] = true; // Visit non-branch instructions. while (It != End && !It->isBranch()) { const MachineInstr &MI = *It++; InstrExec.insert(&MI); visitNonBranch(MI); } // If block end has been reached, add the fall-through edge to the queue. if (It == End) { MachineFunction::const_iterator BIt = B.getIterator(); MachineFunction::const_iterator Next = std::next(BIt); if (Next != MF.end() && B.isSuccessor(&*Next)) { int ThisN = B.getNumber(); int NextN = Next->getNumber(); FlowQ.push(CFGEdge(ThisN, NextN)); } } else { // Handle the remaining sequence of branches. This function will update // the work queue. visitBranchesFrom(*It); } } // while (!FlowQ->empty()) if (Trace) print_cells(dbgs() << "Cells after propagation:\n"); }
unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF, unsigned char* StartFunction, unsigned char* EndFunction) const { assert(MMI && "MachineModuleInfo not registered!"); // Map all labels and get rid of any dead landing pads. MMI->TidyLandingPads(JCE->getLabelLocations()); const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); if (PadInfos.empty()) return 0; // Sort the landing pads in order of their type ids. This is used to fold // duplicate actions. SmallVector<const LandingPadInfo *, 64> LandingPads; LandingPads.reserve(PadInfos.size()); for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) LandingPads.push_back(&PadInfos[i]); std::sort(LandingPads.begin(), LandingPads.end(), PadLT); // Negative type ids index into FilterIds, positive type ids index into // TypeInfos. The value written for a positive type id is just the type // id itself. For a negative type id, however, the value written is the // (negative) byte offset of the corresponding FilterIds entry. The byte // offset is usually equal to the type id, because the FilterIds entries // are written using a variable width encoding which outputs one byte per // entry as long as the value written is not too large, but can differ. // This kind of complication does not occur for positive type ids because // type infos are output using a fixed width encoding. // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i]. SmallVector<int, 16> FilterOffsets; FilterOffsets.reserve(FilterIds.size()); int Offset = -1; for(std::vector<unsigned>::const_iterator I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { FilterOffsets.push_back(Offset); Offset -= MCAsmInfo::getULEB128Size(*I); } // Compute the actions table and gather the first action index for each // landing pad site. SmallVector<ActionEntry, 32> Actions; SmallVector<unsigned, 64> FirstActions; FirstActions.reserve(LandingPads.size()); int FirstAction = 0; unsigned SizeActions = 0; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LP = LandingPads[i]; const std::vector<int> &TypeIds = LP->TypeIds; const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0; unsigned SizeSiteActions = 0; if (NumShared < TypeIds.size()) { unsigned SizeAction = 0; ActionEntry *PrevAction = 0; if (NumShared) { const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size(); assert(Actions.size()); PrevAction = &Actions.back(); SizeAction = MCAsmInfo::getSLEB128Size(PrevAction->NextAction) + MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); for (unsigned j = NumShared; j != SizePrevIds; ++j) { SizeAction -= MCAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); SizeAction += -PrevAction->NextAction; PrevAction = PrevAction->Previous; } } // Compute the actions. for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) { int TypeID = TypeIds[I]; assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); SizeSiteActions += SizeAction; ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; Actions.push_back(Action); PrevAction = &Actions.back(); } // Record the first action of the landing pad site. FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; } // else identical - re-use previous FirstAction FirstActions.push_back(FirstAction); // Compute this sites contribution to size. SizeActions += SizeSiteActions; } // Compute the call-site table. Entries must be ordered by address. SmallVector<CallSiteEntry, 64> CallSites; RangeMapType PadMap; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) { MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; PadMap[BeginLabel] = P; } } bool MayThrow = false; MCSymbol *LastLabel = 0; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (!MI->isLabel()) { MayThrow |= MI->getDesc().isCall(); continue; } MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); assert(BeginLabel && "Invalid label!"); if (BeginLabel == LastLabel) MayThrow = false; RangeMapType::iterator L = PadMap.find(BeginLabel); if (L == PadMap.end()) continue; PadRange P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); // If some instruction between the previous try-range and this one may // throw, create a call-site entry with no landing pad for the region // between the try-ranges. if (MayThrow) { CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; CallSites.push_back(Site); } LastLabel = LandingPad->EndLabels[P.RangeIndex]; CallSiteEntry Site = {BeginLabel, LastLabel, LandingPad->LandingPadLabel, FirstActions[P.PadIndex]}; assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && "Invalid landing pad!"); // Try to merge with the previous call-site. if (CallSites.size()) { CallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; continue; } } // Otherwise, create a new call-site. CallSites.push_back(Site); } } // If some instruction between the previous try-range and the end of the // function may throw, create a call-site entry with no landing pad for the // region following the try-range. if (MayThrow) { CallSiteEntry Site = {LastLabel, 0, 0, 0}; CallSites.push_back(Site); } // Final tallies. unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start. sizeof(int32_t) + // Site length. sizeof(int32_t)); // Landing pad. for (unsigned i = 0, e = CallSites.size(); i < e; ++i) SizeSites += MCAsmInfo::getULEB128Size(CallSites[i].Action); unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize(); unsigned TypeOffset = sizeof(int8_t) + // Call site format // Call-site table length MCAsmInfo::getULEB128Size(SizeSites) + SizeSites + SizeActions + SizeTypes; // Begin the exception table. JCE->emitAlignmentWithFill(4, 0); // Asm->EOL("Padding"); unsigned char* DwarfExceptionTable = (unsigned char*)JCE->getCurrentPCValue(); // Emit the header. JCE->emitByte(dwarf::DW_EH_PE_omit); // Asm->EOL("LPStart format (DW_EH_PE_omit)"); JCE->emitByte(dwarf::DW_EH_PE_absptr); // Asm->EOL("TType format (DW_EH_PE_absptr)"); JCE->emitULEB128Bytes(TypeOffset); // Asm->EOL("TType base offset"); JCE->emitByte(dwarf::DW_EH_PE_udata4); // Asm->EOL("Call site format (DW_EH_PE_udata4)"); JCE->emitULEB128Bytes(SizeSites); // Asm->EOL("Call-site table length"); // Emit the landing pad site information. for (unsigned i = 0; i < CallSites.size(); ++i) { CallSiteEntry &S = CallSites[i]; intptr_t BeginLabelPtr = 0; intptr_t EndLabelPtr = 0; if (!S.BeginLabel) { BeginLabelPtr = (intptr_t)StartFunction; JCE->emitInt32(0); } else { BeginLabelPtr = JCE->getLabelAddress(S.BeginLabel); JCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction); } // Asm->EOL("Region start"); if (!S.EndLabel) EndLabelPtr = (intptr_t)EndFunction; else EndLabelPtr = JCE->getLabelAddress(S.EndLabel); JCE->emitInt32(EndLabelPtr - BeginLabelPtr); //Asm->EOL("Region length"); if (!S.PadLabel) { JCE->emitInt32(0); } else { unsigned PadLabelPtr = JCE->getLabelAddress(S.PadLabel); JCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction); } // Asm->EOL("Landing pad"); JCE->emitULEB128Bytes(S.Action); // Asm->EOL("Action"); } // Emit the actions. for (unsigned I = 0, N = Actions.size(); I != N; ++I) { ActionEntry &Action = Actions[I]; JCE->emitSLEB128Bytes(Action.ValueForTypeID); //Asm->EOL("TypeInfo index"); JCE->emitSLEB128Bytes(Action.NextAction); //Asm->EOL("Next action"); } // Emit the type ids. for (unsigned M = TypeInfos.size(); M; --M) { const GlobalVariable *GV = TypeInfos[M - 1]; if (GV) { if (TD->getPointerSize() == sizeof(int32_t)) JCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV)); else JCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV)); } else { if (TD->getPointerSize() == sizeof(int32_t)) JCE->emitInt32(0); else JCE->emitInt64(0); } // Asm->EOL("TypeInfo"); } // Emit the filter typeids. for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) { unsigned TypeID = FilterIds[j]; JCE->emitULEB128Bytes(TypeID); //Asm->EOL("Filter TypeInfo index"); } JCE->emitAlignmentWithFill(4, 0); return DwarfExceptionTable; }
bool VirtRegReduction::runOnMachineFunction(MachineFunction &MF) { bool Changed = false; #if VRRPROF const Function *F = MF.getFunction(); std::string FN = F->getName().str(); llog("starting vrr... %s (%d)\n", FN.c_str(), (int)time(NULL)); llog("starting immRegs finder... (%d)\n", (int)time(NULL)); #endif std::auto_ptr<std::unordered_set<unsigned> > immRegsHolder; std::unordered_set<unsigned> *immRegs = NULL; // single-def regs defined by a MoveImm shouldn't coalesce as we may be // able to fold them later { std::unordered_map<unsigned, const MachineInstr *> singleDef; MachineFunction::const_iterator I = MF.begin(), E = MF.end(); // find all registers w/ a single def for(; I != E; I++) { MachineBasicBlock::const_iterator BI = I->begin(), BE = I->end(); for(; BI != BE; BI++) { MachineInstr::const_mop_iterator II, IE; II = BI->operands_begin(); IE = BI->operands_end(); for(; II != IE; II++) if(II->isReg() && II->isDef()) { unsigned R = II->getReg(); std::unordered_map<unsigned, const MachineInstr *>::iterator SI = singleDef.find(R); if(SI == singleDef.end()) singleDef[R] = BI; // first seen! insert else SI->second = NULL; // second seen -- replace w/ NULL } } } std::unordered_map<unsigned, const MachineInstr *>::const_iterator SI = singleDef.begin(), SE = singleDef.end(); for(; SI != SE; SI++) { if(SI->second && SI->second->getDesc().isMoveImmediate()) // single def imm? { if(!immRegs) immRegsHolder.reset(immRegs = new std::unordered_set<unsigned>); immRegs->insert(SI->first); // don't coalesce } } } #if VRRPROF llog("starting tdkRegs finder... (%d)\n", (int)time(NULL)); #endif std::auto_ptr<std::unordered_set<unsigned> > tdkRegsHolder; std::unordered_set<unsigned> *tdkRegs = NULL; bool setjmpSafe = !MF.callsSetJmp() && MF.getFunction()->doesNotThrow(); { tdkRegsHolder.reset(tdkRegs = new std::unordered_set<unsigned>); std::unordered_map<unsigned, unsigned> trivialDefKills; MachineFunction::const_iterator I = MF.begin(), E = MF.end(); // find all registers defed and killed in the same block w/ no intervening // unsafe (due to setjmp) calls + side-effecty operations for(; I != E; I++) { std::unordered_set<unsigned> defs; MachineBasicBlock::const_iterator BI = I->begin(), BE = I->end(); for(; BI != BE; BI++) { // TODO need to add || BI->getDesc().isInlineAsm() here to help stackification? if((!setjmpSafe && BI->getDesc().isCall()) || BI->getDesc().hasUnmodeledSideEffects()) { // invalidate on a call instruction if setjmp present, or instr with side effects regardless defs.clear(); } MachineInstr::const_mop_iterator II, IE; // uses when we're not tracking a reg it make it unsafe II = BI->operands_begin(); IE = BI->operands_end(); for(; II != IE; II++) if(II->isReg() && II->isUse()) { unsigned R = II->getReg(); std::unordered_set<unsigned>::const_iterator DI = defs.find(R); if(DI == defs.end()) trivialDefKills[R] = 100; } // kills of tracked defs are trivial def/kills II = BI->operands_begin(); IE = BI->operands_end(); for(; II != IE; II++) if(II->isReg() && II->isKill()) { unsigned R = II->getReg(); std::unordered_set<unsigned>::const_iterator DI = defs.find(R); if(DI != defs.end()) { defs.erase(DI); trivialDefKills[R]++; } else trivialDefKills[R] = 100; // don't use } // record all defs in this instruction II = BI->operands_begin(); IE = BI->operands_end(); for(; II != IE; II++) if(II->isReg() && II->isDef()) defs.insert(II->getReg()); } } std::unordered_map<unsigned, unsigned>::const_iterator DKI = trivialDefKills.begin(), DKE = trivialDefKills.end(); for(; DKI != DKE; DKI++) if(DKI->second == 1) tdkRegs->insert(DKI->first); } #if VRRPROF llog("starting conflict graph construction... (%d)\n", (int)time(NULL)); #endif std::unordered_set<unsigned>::const_iterator tdkE = tdkRegs->end(); std::unordered_set<unsigned> *okRegs = NULL; if(!setjmpSafe) okRegs = tdkRegs; MachineRegisterInfo *RI = &(MF.getRegInfo()); // will eventually hold a virt register coloring for this function ConflictGraph::Coloring coloring; { ConflictGraph cg; LiveIntervals &LIS = getAnalysis<LiveIntervals>(); LiveIntervals::const_iterator I = LIS.begin(), E = LIS.end(); // check every possible LiveInterval, LiveInterval pair of the same // register class for overlap and add overlaps to the conflict graph // also, treat trivially def-kill-ed regs and not trivially def-kill-ed // regs as conflicting so they end up using different VRs -- this makes // stackification easier later in the toolchain for(; I != E; I++) { unsigned R = I->first; if(TargetRegisterInfo::isPhysicalRegister(R)) continue; if(okRegs && okRegs->find(R) == okRegs->end()) continue; // leave singly-defined MoveImm regs for later coalescing if(immRegs && immRegs->find(R) != immRegs->end()) continue; // const TargetRegisterClass *RC = RI->getRegClass(R); const LiveInterval *LI = I->second; if(LI->empty()) continue; cg.addVertex(R); bool notTDK = tdkRegs->find(R) == tdkE; LiveIntervals::const_iterator I1 = I; I1++; for(; I1 != E; I1++) { unsigned R1 = I1->first; if(TargetRegisterInfo::isPhysicalRegister(R1)) continue; if(okRegs && okRegs->find(R1) == okRegs->end()) continue; // leave singly-defined MoveImm regs for later coalescing if(immRegs && immRegs->find(R1) != immRegs->end()) continue; /* Don't bother checked RC -- even though it sounds like an opt, it doesn't speed us up in practice const TargetRegisterClass *RC1 = RI->getRegClass(R1); if(RC != RC1) continue; // different reg class... won't conflict */ const LiveInterval *LI1 = I1->second; // conflict if intervals overlap OR they're not both TDK or both NOT TDK if(LI->overlaps(*LI1) || notTDK != (tdkRegs->find(R1) == tdkE)) cg.addEdge(R, R1); } } #if VRRPROF llog("starting coloring... (%d)\n", (int)time(NULL)); #endif cg.color(&coloring); #if VRRPROF llog("starting vreg=>vreg construction... (%d)\n", (int)time(NULL)); #endif typedef std::unordered_map<unsigned, unsigned> VRegMap; VRegMap Regs; // build up map of vreg=>vreg { std::unordered_map<const TargetRegisterClass *, std::unordered_map<unsigned, unsigned> > RCColor2VReg; ConflictGraph::Coloring::const_iterator I = coloring.begin(), E = coloring.end(); for(; I != E; I++) { unsigned R = I->first; unsigned Color = I->second; const TargetRegisterClass *RC = RI->getRegClass(R); std::unordered_map<unsigned, unsigned> &Color2VReg = RCColor2VReg[RC]; VRegMap::const_iterator CI = Color2VReg.find(Color); if(CI != Color2VReg.end()) Regs[R] = CI->second; // seen this color; map it else Regs[R] = Color2VReg[Color] = R; // first sighting of color; bind to this reg } } #if VRRPROF llog("starting remap... (%d)\n", (int)time(NULL)); #endif // remap regs { VRegMap::const_iterator I = Regs.begin(), E = Regs.end(); for(; I != E; I++) if(I->first != I->second) { RI->replaceRegWith(I->first, I->second); Changed = true; } } } #if VRRPROF llog("done... (%d)\n", (int)time(NULL)); #endif return Changed; }
/// runOnMachineFunction - This emits the frame section, autos section and /// assembly for each instruction. Also takes care of function begin debug /// directive and file begin debug directive (if required) for the function. /// bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { this->MF = &MF; // This calls the base class function required to be called at beginning // of runOnMachineFunction. SetupMachineFunction(MF); // Get the mangled name. const Function *F = MF.getFunction(); CurrentFnName = Mang->getMangledName(F); // Emit the function frame (args and temps). EmitFunctionFrame(MF); DbgInfo.BeginFunction(MF); // Emit the autos section of function. EmitAutos(CurrentFnName); // Now emit the instructions of function in its code section. const MCSection *fCodeSection = getObjFileLowering().getSectionForFunction(CurrentFnName); // Start the Code Section. O << "\n"; OutStreamer.SwitchSection(fCodeSection); // Emit the frame address of the function at the beginning of code. O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; // Emit function start label. O << CurrentFnName << ":\n"; DebugLoc CurDL; O << "\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block. if (I != MF.begin()) { printBasicBlockLabel(I, true); O << '\n'; } // Print a basic block. for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Emit the line directive if source line changed. const DebugLoc DL = II->getDebugLoc(); if (!DL.isUnknown() && DL != CurDL) { DbgInfo.ChangeDebugLoc(MF, DL); CurDL = DL; } // Print the assembly for the instruction. printMachineInstruction(II); } } // Emit function end debug directives. DbgInfo.EndFunction(MF); return false; // we didn't modify anything. }
/// PrepareMonoLSDA - Collect information needed by EmitMonoLSDA /// /// This function collects information available only during EndFunction which is needed /// by EmitMonoLSDA and stores it into EHFrameInfo. It is the same as the /// beginning of EmitExceptionTable. /// void DwarfMonoException::PrepareMonoLSDA(FunctionEHFrameInfo *EHFrameInfo) { const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); const MachineFunction *MF = Asm->MF; // Sort the landing pads in order of their type ids. This is used to fold // duplicate actions. SmallVector<const LandingPadInfo *, 64> LandingPads; LandingPads.reserve(PadInfos.size()); for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) LandingPads.push_back(&PadInfos[i]); std::sort(LandingPads.begin(), LandingPads.end(), [](const LandingPadInfo *L, const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; }); // Invokes and nounwind calls have entries in PadMap (due to being bracketed // by try-range labels when lowered). Ordinary calls do not, so appropriate // try-ranges for them need be deduced when using DWARF exception handling. RangeMapType PadMap; for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { const LandingPadInfo *LandingPad = LandingPads[i]; for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); PadRange P = { i, j }; PadMap[BeginLabel] = P; } } // Compute the call-site table. SmallVector<MonoCallSiteEntry, 64> CallSites; MCSymbol *LastLabel = 0; for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); I != E; ++I) { for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); MI != E; ++MI) { if (!MI->isLabel()) { continue; } MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); assert(BeginLabel && "Invalid label!"); RangeMapType::iterator L = PadMap.find(BeginLabel); if (L == PadMap.end()) continue; PadRange P = L->second; const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && "Inconsistent landing pad map!"); // Mono emits one landing pad for each CLR exception clause, // and the type info contains the clause index assert (LandingPad->TypeIds.size() == 1); assert (LandingPad->LandingPadLabel); LastLabel = LandingPad->EndLabels[P.RangeIndex]; MonoCallSiteEntry Site = {BeginLabel, LastLabel, LandingPad->LandingPadLabel, LandingPad->TypeIds [0]}; assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel && "Invalid landing pad!"); // FIXME: This doesn't work because it includes ranges outside clauses #if 0 // Try to merge with the previous call-site. if (CallSites.size()) { MonoCallSiteEntry &Prev = CallSites.back(); if (Site.PadLabel == Prev.PadLabel && Site.TypeID == Prev.TypeID) { // Extend the range of the previous entry. Prev.EndLabel = Site.EndLabel; continue; } } #endif // Otherwise, create a new call-site. CallSites.push_back(Site); } } // // Compute a mapping from method names to their AOT method index // if (FuncIndexes.size () == 0) { const Module *m = MMI->getModule (); NamedMDNode *indexes = m->getNamedMetadata ("mono.function_indexes"); if (indexes) { for (unsigned int i = 0; i < indexes->getNumOperands (); ++i) { MDNode *n = indexes->getOperand (i); MDString *s = (MDString*)n->getOperand (0); ConstantInt *idx = (ConstantInt*)n->getOperand (1); FuncIndexes.GetOrCreateValue (s->getString (), (int)idx->getLimitedValue () + 1); } } } MonoEHFrameInfo *MonoEH = &EHFrameInfo->MonoEH; // Save information for EmitMonoLSDA MonoEH->MF = Asm->MF; MonoEH->FunctionNumber = Asm->getFunctionNumber(); MonoEH->CallSites.insert(MonoEH->CallSites.begin(), CallSites.begin(), CallSites.end()); MonoEH->TypeInfos = TypeInfos; MonoEH->PadInfos = PadInfos; MonoEH->MonoMethodIdx = FuncIndexes.lookup (Asm->MF->getFunction ()->getName ()) - 1; //outs()<<"A:"<<Asm->MF->getFunction()->getName() << " " << MonoEH->MonoMethodIdx << "\n"; int ThisSlot = Asm->MF->getMonoInfo()->getThisStackSlot(); if (ThisSlot != -1) { unsigned FrameReg; MonoEH->ThisOffset = Asm->MF->getTarget ().getSubtargetImpl ()->getFrameLowering ()->getFrameIndexReference (*Asm->MF, ThisSlot, FrameReg); MonoEH->FrameReg = Asm->MF->getTarget ().getSubtargetImpl ()->getRegisterInfo ()->getDwarfRegNum (FrameReg, true); } else { MonoEH->FrameReg = -1; } }
/// runOnMachineFunction - This uses the printInstruction() /// method to print assembly for each instruction. /// bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) { this->MF = &MF; // This calls the base class function required to be called at beginning // of runOnMachineFunction. SetupMachineFunction(MF); // Get the mangled name. const Function *F = MF.getFunction(); CurrentFnName = Mang->getValueName(F); // Emit the function variables. EmitFunctionFrame(MF); // Emit function begin debug directives DbgInfo.EmitFunctBeginDI(F); EmitAutos(CurrentFnName); const char *codeSection = PAN::getCodeSectionName(CurrentFnName).c_str(); const Section *fCodeSection = TAI->getNamedSection(codeSection, SectionFlags::Code); O << "\n"; // Start the Code Section. SwitchToSection (fCodeSection); // Emit the frame address of the function at the beginning of code. O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; // Emit function start label. O << CurrentFnName << ":\n"; // For emitting line directives, we need to keep track of the current // source line. When it changes then only emit the line directive. unsigned CurLine = 0; O << "\n"; // Print out code for the function. for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); I != E; ++I) { // Print a label for the basic block. if (I != MF.begin()) { printBasicBlockLabel(I, true); O << '\n'; } for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); II != E; ++II) { // Emit the line directive if source line changed. const DebugLoc DL = II->getDebugLoc(); if (!DL.isUnknown()) { unsigned line = MF.getDebugLocTuple(DL).Line; if (line != CurLine) { O << "\t.line " << line << "\n"; CurLine = line; } } // Print the assembly for the instruction. printMachineInstruction(II); } } // Emit function end debug directives. DbgInfo.EmitFunctEndDI(F, CurLine); return false; // we didn't modify anything. }
bool MachineVerifier::runOnMachineFunction(MachineFunction &MF) { raw_ostream *OutFile = 0; if (OutFileName) { std::string ErrorInfo; OutFile = new raw_fd_ostream(OutFileName, ErrorInfo, raw_fd_ostream::F_Append); if (!ErrorInfo.empty()) { errs() << "Error opening '" << OutFileName << "': " << ErrorInfo << '\n'; exit(1); } OS = OutFile; } else { OS = &errs(); } foundErrors = 0; this->MF = &MF; TM = &MF.getTarget(); TII = TM->getInstrInfo(); TRI = TM->getRegisterInfo(); MRI = &MF.getRegInfo(); LiveVars = NULL; LiveInts = NULL; LiveStks = NULL; Indexes = NULL; if (PASS) { LiveInts = PASS->getAnalysisIfAvailable<LiveIntervals>(); // We don't want to verify LiveVariables if LiveIntervals is available. if (!LiveInts) LiveVars = PASS->getAnalysisIfAvailable<LiveVariables>(); LiveStks = PASS->getAnalysisIfAvailable<LiveStacks>(); Indexes = PASS->getAnalysisIfAvailable<SlotIndexes>(); } visitMachineFunctionBefore(); for (MachineFunction::const_iterator MFI = MF.begin(), MFE = MF.end(); MFI!=MFE; ++MFI) { visitMachineBasicBlockBefore(MFI); for (MachineBasicBlock::const_iterator MBBI = MFI->begin(), MBBE = MFI->end(); MBBI != MBBE; ++MBBI) { if (MBBI->getParent() != MFI) { report("Bad instruction parent pointer", MFI); *OS << "Instruction: " << *MBBI; continue; } visitMachineInstrBefore(MBBI); for (unsigned I = 0, E = MBBI->getNumOperands(); I != E; ++I) visitMachineOperand(&MBBI->getOperand(I), I); visitMachineInstrAfter(MBBI); } visitMachineBasicBlockAfter(MFI); } visitMachineFunctionAfter(); if (OutFile) delete OutFile; else if (foundErrors) report_fatal_error("Found "+Twine(foundErrors)+" machine code errors."); // Clean up. regsLive.clear(); regsDefined.clear(); regsDead.clear(); regsKilled.clear(); regsLiveInButUnused.clear(); MBBInfoMap.clear(); return false; // no changes }
bool MachineCSE::PhysRegDefsReach(MachineInstr *CSMI, MachineInstr *MI, SmallSet<unsigned,8> &PhysRefs, SmallVector<unsigned,2> &PhysDefs, bool &NonLocal) const { // For now conservatively returns false if the common subexpression is // not in the same basic block as the given instruction. The only exception // is if the common subexpression is in the sole predecessor block. const MachineBasicBlock *MBB = MI->getParent(); const MachineBasicBlock *CSMBB = CSMI->getParent(); bool CrossMBB = false; if (CSMBB != MBB) { if (MBB->pred_size() != 1 || *MBB->pred_begin() != CSMBB) return false; for (unsigned i = 0, e = PhysDefs.size(); i != e; ++i) { if (MRI->isAllocatable(PhysDefs[i]) || MRI->isReserved(PhysDefs[i])) // Avoid extending live range of physical registers if they are //allocatable or reserved. return false; } CrossMBB = true; } MachineBasicBlock::const_iterator I = CSMI; I = llvm::next(I); MachineBasicBlock::const_iterator E = MI; MachineBasicBlock::const_iterator EE = CSMBB->end(); unsigned LookAheadLeft = LookAheadLimit; while (LookAheadLeft) { // Skip over dbg_value's. while (I != E && I != EE && I->isDebugValue()) ++I; if (I == EE) { assert(CrossMBB && "Reaching end-of-MBB without finding MI?"); (void)CrossMBB; CrossMBB = false; NonLocal = true; I = MBB->begin(); EE = MBB->end(); continue; } if (I == E) return true; for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) { const MachineOperand &MO = I->getOperand(i); // RegMasks go on instructions like calls that clobber lots of physregs. // Don't attempt to CSE across such an instruction. if (MO.isRegMask()) return false; if (!MO.isReg() || !MO.isDef()) continue; unsigned MOReg = MO.getReg(); if (TargetRegisterInfo::isVirtualRegister(MOReg)) continue; if (PhysRefs.count(MOReg)) return false; } --LookAheadLeft; ++I; } return false; }
/// shouldTailDuplicate - Determine if it is profitable to duplicate this block. bool TailDuplicatePass::shouldTailDuplicate(const MachineFunction &MF, MachineBasicBlock &TailBB) { // Only duplicate blocks that end with unconditional branches. if (TailBB.canFallThrough()) return false; // Don't try to tail-duplicate single-block loops. if (TailBB.isSuccessor(&TailBB)) return false; // Set the limit on the cost to duplicate. When optimizing for size, // duplicate only one, because one branch instruction can be eliminated to // compensate for the duplication. unsigned MaxDuplicateCount; if (TailDuplicateSize.getNumOccurrences() == 0 && MF.getFunction()->hasFnAttr(Attribute::OptimizeForSize)) MaxDuplicateCount = 1; else MaxDuplicateCount = TailDuplicateSize; // If the target has hardware branch prediction that can handle indirect // branches, duplicating them can often make them predictable when there // are common paths through the code. The limit needs to be high enough // to allow undoing the effects of tail merging and other optimizations // that rearrange the predecessors of the indirect branch. if (PreRegAlloc && !TailBB.empty()) { const TargetInstrDesc &TID = TailBB.back().getDesc(); if (TID.isIndirectBranch()) MaxDuplicateCount = 20; } // Check the instructions in the block to determine whether tail-duplication // is invalid or unlikely to be profitable. unsigned InstrCount = 0; for (MachineBasicBlock::const_iterator I = TailBB.begin(); I != TailBB.end(); ++I) { // Non-duplicable things shouldn't be tail-duplicated. if (I->getDesc().isNotDuplicable()) return false; // Do not duplicate 'return' instructions if this is a pre-regalloc run. // A return may expand into a lot more instructions (e.g. reload of callee // saved registers) after PEI. if (PreRegAlloc && I->getDesc().isReturn()) return false; // Avoid duplicating calls before register allocation. Calls presents a // barrier to register allocation so duplicating them may end up increasing // spills. if (PreRegAlloc && I->getDesc().isCall()) return false; if (!I->isPHI() && !I->isDebugValue()) InstrCount += 1; if (InstrCount > MaxDuplicateCount) return false; } return true; }
bool AccessFrequency::runOnMachineFunction(MachineFunction &mf) { MF = &mf; MRI = &mf.getRegInfo(); TRI = MF->getTarget().getRegisterInfo(); m_nVars = 0; const llvm::Function *fn = mf.getFunction(); std::string szMain = "main"; if(fn->getName() != szMain && g_hFuncCall[szMain].find(fn->getName()) == g_hFuncCall[szMain].end() ) { errs() << "--------qali:--------Skip function " << fn->getName() << " in AccessFrequency !\n"; return true; } for (MachineFunction::const_iterator FI = MF->begin(), FE = MF->end(); FI != FE; ++FI) { double dFactor = 0.0; const BasicBlock *bb = FI->getBasicBlock(); if( bb != NULL ) { //const std::map<const Function *, std::map<const BasicBlock *, double> > &hF2B2Acc =(SP->BlockInformation); std::map<const Function *, std::map<const BasicBlock *, double> >::const_iterator f2b2acc_p, E = g_hF2B2Acc->end(); if( (f2b2acc_p = g_hF2B2Acc->find(fn) ) != E ) { std::map<const BasicBlock *, double>::const_iterator b2acc_p, EE = f2b2acc_p->second.end(); if( (b2acc_p = f2b2acc_p->second.find(bb) ) != EE ) dFactor = b2acc_p->second; } } if( dFactor == 0.0 ) dFactor = 1.0; for (MachineBasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); BBI != BBE; ++BBI) { DEBUG(BBI->print(dbgs(), NULL )); //MachineInstr *MI = BBI; for (unsigned i = 0, e = BBI->getNumOperands(); i != e; ++ i) { const MachineOperand &MO = BBI->getOperand(i); // TODO (qali#1#): To hack other kinds of MachineOperands switch (MO.getType() ) { case MachineOperand::MO_Register: if( MO.getReg() != 0 && TargetRegisterInfo::isVirtualRegister(MO.getReg()) ) { unsigned MOReg = MO.getReg(); unsigned int nSize = getRegSize(MOReg); if( MO.isUse() ) { int nAcc = ROUND(dFactor); m_RegReadMap[MOReg] = m_RegReadMap[MOReg] + dFactor; //if( nAcc >= 1) m_SimTrace.push_back(llvm::TraceRecord(MOReg, nAcc)); } else if( MO.isDef()) { int nAcc = ROUND(dFactor); m_RegWriteMap[MOReg] = m_RegWriteMap[MOReg] + dFactor; //if( nAcc >= 1) m_SimTrace.push_back(llvm::TraceRecord(MOReg, nAcc, false)); } else assert("Unrecoganized operation in AccessFrequency::runOnMachineFunction!\n"); } break; default: break; } } // Analyze the memoperations if(!BBI->memoperands_empty() ) { for( MachineInstr::mmo_iterator i = BBI->memoperands_begin(), e = BBI->memoperands_end(); i != e; ++ i) { if( (*i)->isLoad() ) { const char *tmp = (**i).getValue()->getName().data(); m_StackReadMap[tmp] ++; } else if( (*i)->isStore()) { const char *tmp = (**i).getValue()->getName().data(); m_StackWriteMap[tmp] ++; } else { assert(false); dbgs() << __FILE__ << __LINE__; } } } } } m_nVars = m_RegReadMap.size(); //print(afout); //printInt(afout); //reset(); std::string szInfo; std::string szSrcFile = mf.getMMI().getModule()->getModuleIdentifier(); std::string szFile = szSrcFile + ".accInt"; raw_fd_ostream accIfout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); printInt(accIfout); accIfout.close(); szFile = szSrcFile + ".acc"; raw_fd_ostream accfout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); print(accfout); accfout.close(); szFile = szSrcFile + "." + "var"; raw_fd_ostream varfout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); printVars(varfout); varfout.close(); szFile = szSrcFile + ".read"; raw_fd_ostream readfout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); printRead(readfout); readfout.close(); szFile = szSrcFile + ".write"; raw_fd_ostream writefout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); printWrite(writefout); writefout.close(); szFile = szSrcFile + ".size"; raw_fd_ostream sizefout(szFile.c_str(), szInfo, raw_fd_ostream::F_Append ); printSize(sizefout); sizefout.close(); return true; }