bool RelativeMinMax::getMinMax(Expr Ex, Expr &Min, Expr &Max) { if (Ex.isConstant()) { Min = Ex; Max = Ex; } else if (Ex.isSymbol()) { // Bounds of induction variables have special treatment. if (PHINode *Phi = dyn_cast<PHINode>(Ex.getSymbolValue())) { if (Loop *L = LIE_->getLoopForInductionVariable(Phi)) { Expr IndvarStart, IndvarEnd, IndvarStep; LIE_->getLoopInfo(L, Phi, IndvarStart, IndvarEnd, IndvarStep); BranchInst *BI = cast<BranchInst>(L->getExitingBlock()->getTerminator()); ICmpInst *ICI = cast<ICmpInst>(BI->getCondition()); Expr MinStart, MaxStart, MinEnd, MaxEnd; if (!getMinMax(IndvarStart, MinStart, MaxStart) || !getMinMax(IndvarEnd, MinEnd, MaxEnd)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << IndvarStart << " and/or" << IndvarEnd << "\n"); return false; } // FIXME: we should wrap the loop in a conditional so that the following // min/max assumptions always hold. switch (ICI->getPredicate()) { case CmpInst::ICMP_SLT: case CmpInst::ICMP_ULT: case CmpInst::ICMP_SLE: case CmpInst::ICMP_ULE: Min = MinStart; Max = MaxEnd; break; case CmpInst::ICMP_SGT: case CmpInst::ICMP_UGT: case CmpInst::ICMP_UGE: case CmpInst::ICMP_SGE: Min = MaxStart; Max = MinEnd; break; default: llvm_unreachable("Invalid comparison predicate"); } RMM_DEBUG(dbgs() << "RelativeMinMax: min/max for induction variable " << *Phi << ": " << Min << ", " << Max << "\n"); return true; } } Min = Ex; Max = Ex; } else if (Ex.isAdd()) { for (auto SubEx : Ex) { Expr TmpMin, TmpMax; if (!getMinMax(SubEx, TmpMin, TmpMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << SubEx << "\n"); return false; } addMinMax(TmpMin, TmpMax, Min, Max, Min, Max); } } else if (Ex.isMul()) { Min = Expr::InvalidExpr(); for (auto SubEx : Ex) { Expr TmpMin, TmpMax; if (!getMinMax(SubEx, TmpMin, TmpMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << SubEx << "\n"); return false; } if (!Min.isValid()) { Min = TmpMin; Max = TmpMax; } else { mulMinMax(TmpMin, TmpMax, Min, Max, Min, Max); } } } else if (Ex.isPow()) { if (!Ex.getPowExp().isConstant()) { RMM_DEBUG(dbgs() << "RelativeMinMax: non-constant exponent\n"); return false; } Expr BaseMin, BaseMax; if (!getMinMax(Ex.getPowBase(), BaseMin, BaseMax)) { RMM_DEBUG(dbgs() << "RelativeMinMax: Could not infer min/max for " << Ex.getPowBase() << "\n"); return false; } if (Ex.getPowExp().isPositive()) { Min = BaseMin ^ Ex.getPowExp(); Max = BaseMax ^ Ex.getPowExp(); } else { Min = BaseMax ^ Ex.getPowExp(); Max = BaseMin ^ Ex.getPowExp(); } } else if (Ex.isMin()) { Expr MinFirst, MinSecond, Bogus; getMinMax(Ex.at(0), MinFirst, Bogus); getMinMax(Ex.at(1), MinSecond, Bogus); Min = Max = MinFirst.min(MinSecond); } else if (Ex.isMax()) { Expr MaxFirst, MaxSecond, Bogus; getMinMax(Ex.at(0), MaxFirst, Bogus); getMinMax(Ex.at(1), MaxSecond, Bogus); Min = Max = MaxFirst.max(MaxSecond); } else { RMM_DEBUG(dbgs() << "RelativeMinMax: unhandled expression: " << Ex << "\n"); return false; } return true; }
StepCode EliminateNakedTriplesStep::runOnHouse(House &house) { bool modified = false; if (house.size() <= 3) { return {false, modified}; } std::vector<std::pair<Mask, std::vector<const Cell *>>> found_masks; for (const Cell *cell : house) { std::size_t num_candidates = cell->candidates.count(); if (num_candidates == 0) { return {true, modified}; } if (num_candidates != 2 && num_candidates != 3) { continue; } const Mask mask = cell->candidates.to_ulong(); bool found_match = false; for (unsigned i = 0; i < found_masks.size(); ++i) { const Mask m = found_masks[i].first; // ORing the two masks together will switch on all candidates found in // both masks. If it's less than three, then we're still a triple // candidate. // TODO: If the current mask is size 2 and the OR of the two is 3, then // we should create two masks: one for the two and one for the OR. // Otherwise you could get 1/2 match with 1/2/3 and 1/2/4. // For now, only accept found masks of size 3. Easy naked triples. if (bitCount(m) == 3 && bitCount(mask | m) == 3) { found_match = true; found_masks[i].second.push_back(cell); } } if (!found_match) { std::pair<Mask, std::vector<const Cell *>> pair; pair.first = mask; pair.second.push_back(cell); found_masks.push_back(pair); } } for (auto &pair : found_masks) { if (pair.second.size() != 3) { continue; } auto &matches = pair.second; const Mask mask = pair.first; for (Cell *cell : house) { if (cell->isFixed()) { continue; } if (std::find(matches.begin(), matches.end(), cell) != matches.end()) { continue; } CandidateSet *candidates = &cell->candidates; if (candidates->to_ulong() == mask) { continue; } auto new_cands = CandidateSet(candidates->to_ulong() & ~mask); if (*candidates == new_cands) { continue; } if (DEBUG) { const Mask intersection = candidates->to_ulong() & mask; dbgs() << "Naked Triple " << printCandidateString(mask) << " removes " << printCandidateString(intersection) << " from " << cell->coord << "\n"; } modified = true; changed.insert(cell); *candidates = new_cands; } } return {false, modified}; }
static inline bool doit(const bar &Val) { dbgs() << "Classof: " << &Val << "\n"; return true; }
/// inlineFuctions - Walk all call sites in all functions supplied by /// client. Inline as many call sites as possible. Delete completely /// inlined functions. void BasicInlinerImpl::inlineFunctions() { // Scan through and identify all call sites ahead of time so that we only // inline call sites in the original functions, not call sites that result // from inlining other functions. std::vector<CallSite> CallSites; for (std::vector<Function *>::iterator FI = Functions.begin(), FE = Functions.end(); FI != FE; ++FI) { Function *F = *FI; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) { CallSite CS(cast<Value>(I)); if (CS && CS.getCalledFunction() && !CS.getCalledFunction()->isDeclaration()) CallSites.push_back(CS); } } DEBUG(dbgs() << ": " << CallSites.size() << " call sites.\n"); // Inline call sites. bool Changed = false; do { Changed = false; for (unsigned index = 0; index != CallSites.size() && !CallSites.empty(); ++index) { CallSite CS = CallSites[index]; if (Function *Callee = CS.getCalledFunction()) { // Eliminate calls that are never inlinable. if (Callee->isDeclaration() || CS.getInstruction()->getParent()->getParent() == Callee) { CallSites.erase(CallSites.begin() + index); --index; continue; } InlineCost IC = CA.getInlineCost(CS, NeverInline); if (IC.isAlways()) { DEBUG(dbgs() << " Inlining: cost=always" <<", call: " << *CS.getInstruction()); } else if (IC.isNever()) { DEBUG(dbgs() << " NOT Inlining: cost=never" <<", call: " << *CS.getInstruction()); continue; } else { int Cost = IC.getValue(); if (Cost >= (int) BasicInlineThreshold) { DEBUG(dbgs() << " NOT Inlining: cost = " << Cost << ", call: " << *CS.getInstruction()); continue; } else { DEBUG(dbgs() << " Inlining: cost = " << Cost << ", call: " << *CS.getInstruction()); } } // Inline InlineFunctionInfo IFI(0, TD); if (InlineFunction(CS, IFI)) { if (Callee->use_empty() && (Callee->hasLocalLinkage() || Callee->hasAvailableExternallyLinkage())) DeadFunctions.insert(Callee); Changed = true; CallSites.erase(CallSites.begin() + index); --index; } } } } while (Changed); // Remove completely inlined functions from module. for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(), E = DeadFunctions.end(); I != E; ++I) { Function *D = *I; Module *M = D->getParent(); M->getFunctionList().remove(D); } }
ObjectImage *RuntimeDyldImpl::loadObject(ObjectBuffer *InputBuffer) { OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer)); if (!obj) report_fatal_error("Unable to create object image from memory buffer!"); Arch = (Triple::ArchType)obj->getArch(); // Symbols found in this object StringMap<SymbolLoc> LocalSymbols; // Used sections from the object file ObjSectionToIDMap LocalSections; // Common symbols requiring allocation, with their sizes and alignments CommonSymbolMap CommonSymbols; // Maximum required total memory to allocate all common symbols uint64_t CommonSize = 0; error_code err; // Parse symbols DEBUG(dbgs() << "Parse symbols:\n"); for (symbol_iterator i = obj->begin_symbols(), e = obj->end_symbols(); i != e; i.increment(err)) { Check(err); object::SymbolRef::Type SymType; StringRef Name; Check(i->getType(SymType)); Check(i->getName(Name)); uint32_t flags; Check(i->getFlags(flags)); bool isCommon = flags & SymbolRef::SF_Common; if (isCommon) { // Add the common symbols to a list. We'll allocate them all below. uint32_t Align; Check(i->getAlignment(Align)); uint64_t Size = 0; Check(i->getSize(Size)); CommonSize += Size + Align; CommonSymbols[*i] = CommonSymbolInfo(Size, Align); } else { if (SymType == object::SymbolRef::ST_Function || SymType == object::SymbolRef::ST_Data || SymType == object::SymbolRef::ST_Unknown) { uint64_t FileOffset; StringRef SectionData; bool IsCode; section_iterator si = obj->end_sections(); Check(i->getFileOffset(FileOffset)); Check(i->getSection(si)); if (si == obj->end_sections()) continue; Check(si->getContents(SectionData)); Check(si->isText(IsCode)); const uint8_t* SymPtr = (const uint8_t*)InputBuffer->getBufferStart() + (uintptr_t)FileOffset; uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)SectionData.begin()); unsigned SectionID = findOrEmitSection(*obj, *si, IsCode, LocalSections); LocalSymbols[Name.data()] = SymbolLoc(SectionID, SectOffset); DEBUG(dbgs() << "\tFileOffset: " << format("%p", (uintptr_t)FileOffset) << " flags: " << flags << " SID: " << SectionID << " Offset: " << format("%p", SectOffset)); GlobalSymbolTable[Name] = SymbolLoc(SectionID, SectOffset); } } DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name << "\n"); } // Allocate common symbols if (CommonSize != 0) emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols); // Parse and process relocations DEBUG(dbgs() << "Parse relocations:\n"); for (section_iterator si = obj->begin_sections(), se = obj->end_sections(); si != se; si.increment(err)) { Check(err); bool isFirstRelocation = true; unsigned SectionID = 0; StubMap Stubs; for (relocation_iterator i = si->begin_relocations(), e = si->end_relocations(); i != e; i.increment(err)) { Check(err); // If it's the first relocation in this section, find its SectionID if (isFirstRelocation) { SectionID = findOrEmitSection(*obj, *si, true, LocalSections); DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n"); isFirstRelocation = false; } processRelocationRef(SectionID, *i, *obj, LocalSections, LocalSymbols, Stubs); } } return obj.take(); }
unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj, const SectionRef &Section, bool IsCode) { unsigned StubBufSize = 0, StubSize = getMaxStubSize(); error_code err; if (StubSize > 0) { for (relocation_iterator i = Section.begin_relocations(), e = Section.end_relocations(); i != e; i.increment(err), Check(err)) StubBufSize += StubSize; } StringRef data; uint64_t Alignment64; Check(Section.getContents(data)); Check(Section.getAlignment(Alignment64)); unsigned Alignment = (unsigned)Alignment64 & 0xffffffffL; bool IsRequired; bool IsVirtual; bool IsZeroInit; bool IsReadOnly; uint64_t DataSize; StringRef Name; Check(Section.isRequiredForExecution(IsRequired)); Check(Section.isVirtual(IsVirtual)); Check(Section.isZeroInit(IsZeroInit)); Check(Section.isReadOnlyData(IsReadOnly)); Check(Section.getSize(DataSize)); Check(Section.getName(Name)); if (StubSize > 0) { unsigned StubAlignment = getStubAlignment(); unsigned EndAlignment = (DataSize | Alignment) & -(DataSize | Alignment); if (StubAlignment > EndAlignment) StubBufSize += StubAlignment - EndAlignment; } unsigned Allocate; unsigned SectionID = Sections.size(); uint8_t *Addr; const char *pData = 0; // Some sections, such as debug info, don't need to be loaded for execution. // Leave those where they are. if (IsRequired) { Allocate = DataSize + StubBufSize; Addr = IsCode ? MemMgr->allocateCodeSection(Allocate, Alignment, SectionID) : MemMgr->allocateDataSection(Allocate, Alignment, SectionID, IsReadOnly); if (!Addr) report_fatal_error("Unable to allocate section memory!"); // Virtual sections have no data in the object image, so leave pData = 0 if (!IsVirtual) pData = data.data(); // Zero-initialize or copy the data from the image if (IsZeroInit || IsVirtual) memset(Addr, 0, DataSize); else memcpy(Addr, pData, DataSize); DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", pData) << " new addr: " << format("%p", Addr) << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); Obj.updateSectionAddress(Section, (uint64_t)Addr); } else { // Even if we didn't load the section, we need to record an entry for it // to handle later processing (and by 'handle' I mean don't do anything // with these sections). Allocate = 0; Addr = 0; DEBUG(dbgs() << "emitSection SectionID: " << SectionID << " Name: " << Name << " obj addr: " << format("%p", data.data()) << " new addr: 0" << " DataSize: " << DataSize << " StubBufSize: " << StubBufSize << " Allocate: " << Allocate << "\n"); } Sections.push_back(SectionEntry(Name, Addr, DataSize, (uintptr_t)pData)); return SectionID; }