/// ApplyQAOverride - Apply a list of edits to the input argument lists. /// /// The input string is a space separate list of edits to perform, /// they are applied in order to the input argument lists. Edits /// should be one of the following forms: /// /// '#': Silence information about the changes to the command line arguments. /// /// '^': Add FOO as a new argument at the beginning of the command line. /// /// '+': Add FOO as a new argument at the end of the command line. /// /// 's/XXX/YYY/': Substitute the regular expression XXX with YYY in the command /// line. /// /// 'xOPTION': Removes all instances of the literal argument OPTION. /// /// 'XOPTION': Removes all instances of the literal argument OPTION, /// and the following argument. /// /// 'Ox': Removes all flags matching 'O' or 'O[sz0-9]' and adds 'Ox' /// at the end of the command line. /// /// \param OS - The stream to write edit information to. /// \param Args - The vector of command line arguments. /// \param Edit - The override command to perform. /// \param SavedStrings - Set to use for storing string representations. static void ApplyOneQAOverride(llvm::raw_ostream &OS, llvm::SmallVectorImpl<const char*> &Args, llvm::StringRef Edit, std::set<std::string> &SavedStrings) { // This does not need to be efficient. if (Edit[0] == '^') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at beginning\n"; Args.insert(Args.begin() + 1, Str); } else if (Edit[0] == '+') { const char *Str = SaveStringInSet(SavedStrings, Edit.substr(1)); OS << "### Adding argument " << Str << " at end\n"; Args.push_back(Str); } else if (Edit[0] == 's' && Edit[1] == '/' && Edit.endswith("/") && Edit.slice(2, Edit.size()-1).find('/') != llvm::StringRef::npos) { llvm::StringRef MatchPattern = Edit.substr(2).split('/').first; llvm::StringRef ReplPattern = Edit.substr(2).split('/').second; ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); if (Repl != Args[i]) { OS << "### Replacing '" << Args[i] << "' with '" << Repl << "'\n"; Args[i] = SaveStringInSet(SavedStrings, Repl); } } } else if (Edit[0] == 'x' || Edit[0] == 'X') { std::string Option = Edit.substr(1, std::string::npos); for (unsigned i = 1; i < Args.size();) { if (Option == Args[i]) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); if (Edit[0] == 'X') { if (i < Args.size()) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else OS << "### Invalid X edit, end of command line!\n"; } } else ++i; } } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { const char *A = Args[i]; if (A[0] == '-' && A[1] == 'O' && (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || ('0' <= A[2] && A[2] <= '9'))))) { OS << "### Deleting argument " << Args[i] << '\n'; Args.erase(Args.begin() + i); } else ++i; } OS << "### Adding argument " << Edit << " at end\n"; Args.push_back(SaveStringInSet(SavedStrings, '-' + Edit.str())); } else { OS << "### Unrecognized edit: " << Edit << "\n"; } }
/// \brief Attempt to inline all calls smaller than our threshold. /// returns True if a function was inlined. bool SILPerformanceInliner::inlineCallsIntoFunction(SILFunction *Caller, DominanceAnalysis *DA, SILLoopAnalysis *LA, llvm::SmallVectorImpl<FullApplySite> &NewApplies) { // Don't optimize functions that are marked with the opt.never attribute. if (!Caller->shouldOptimize()) return false; // Construct a log of all of the names of the functions that we've inlined // in the current iteration. SmallVector<StringRef, 16> InlinedFunctionNames; StringRef CallerName = Caller->getName(); DEBUG(llvm::dbgs() << "Visiting Function: " << CallerName << "\n"); assert(NewApplies.empty() && "Expected empty vector to store results in!"); // First step: collect all the functions we want to inline. We // don't change anything yet so that the dominator information // remains valid. SmallVector<FullApplySite, 8> AppliesToInline; collectAppliesToInline(Caller, AppliesToInline, DA, LA); if (AppliesToInline.empty()) return false; // Second step: do the actual inlining. for (auto AI : AppliesToInline) { SILFunction *Callee = AI.getCalleeFunction(); assert(Callee && "apply_inst does not have a direct callee anymore"); DEBUG(llvm::dbgs() << " Inline:" << *AI.getInstruction()); if (!Callee->shouldOptimize()) { DEBUG(llvm::dbgs() << " Cannot inline function " << Callee->getName() << " marked to be excluded from optimizations.\n"); continue; } SmallVector<SILValue, 8> Args; for (const auto &Arg : AI.getArguments()) Args.push_back(Arg); // As we inline and clone we need to collect new applies. auto Filter = [](SILInstruction *I) -> bool { return bool(FullApplySite::isa(I)); }; CloneCollector Collector(Filter); // Notice that we will skip all of the newly inlined ApplyInsts. That's // okay because we will visit them in our next invocation of the inliner. TypeSubstitutionMap ContextSubs; SILInliner Inliner(*Caller, *Callee, SILInliner::InlineKind::PerformanceInline, ContextSubs, AI.getSubstitutions(), Collector.getCallback()); // Record the name of the inlined function (for cycle detection). InlinedFunctionNames.push_back(Callee->getName()); auto Success = Inliner.inlineFunction(AI, Args); (void) Success; // We've already determined we should be able to inline this, so // we expect it to have happened. assert(Success && "Expected inliner to inline this function!"); llvm::SmallVector<FullApplySite, 4> AppliesFromInlinee; for (auto &P : Collector.getInstructionPairs()) AppliesFromInlinee.push_back(FullApplySite(P.first)); recursivelyDeleteTriviallyDeadInstructions(AI.getInstruction(), true); NewApplies.insert(NewApplies.end(), AppliesFromInlinee.begin(), AppliesFromInlinee.end()); DA->invalidate(Caller, SILAnalysis::InvalidationKind::Everything); NumFunctionsInlined++; } // Record the names of the functions that we inlined. // We'll use this list to detect cycles in future iterations of // the inliner. for (auto CalleeName : InlinedFunctionNames) { InlinedFunctions.insert(std::make_pair(CallerName, CalleeName)); } DEBUG(llvm::dbgs() << "\n"); return true; }
static void ParseProgName(llvm::SmallVectorImpl<const char *> &ArgVector, std::set<std::string> &SavedStrings, Driver &TheDriver) { // Try to infer frontend type and default target from the program name. // suffixes[] contains the list of known driver suffixes. // Suffixes are compared against the program name in order. // If there is a match, the frontend type is updated as necessary (CPP/C++). // If there is no match, a second round is done after stripping the last // hyphen and everything following it. This allows using something like // "mlang++-2.9". // If there is a match in either the first or second round, // the function tries to identify a target as prefix. E.g. // "x86_64-linux-mlang" as interpreted as suffix "mlang" with // target prefix "x86_64-linux". If such a target prefix is found, // is gets added via -ccc-host-triple as implicit first argument. static const struct { const char *Suffix; bool IsCXX; bool IsCPP; } suffixes [] = { { "mlang", false, false }, { "mlang++", true, false }, { "mlang-c++", true, false }, { "mlang-cc", false, false }, { "mlang-cpp", false, true }, { "mlang-g++", true, false }, { "mlang-gcc", false, false }, { "cc", false, false }, { "cpp", false, true }, { "++", true, false }, }; std::string ProgName(llvm::sys::path::stem(ArgVector[0])); llvm::StringRef ProgNameRef(ProgName); llvm::StringRef Prefix; for (int Components = 2; Components; --Components) { bool FoundMatch = false; size_t i; for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) { if (ProgNameRef.endswith(suffixes[i].Suffix)) { FoundMatch = true; if (suffixes[i].IsCXX) TheDriver.CCCIsCXX = true; if (suffixes[i].IsCPP) TheDriver.CCCIsCPP = true; break; } } if (FoundMatch) { llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-', ProgNameRef.size() - strlen(suffixes[i].Suffix)); if (LastComponent != llvm::StringRef::npos) Prefix = ProgNameRef.slice(0, LastComponent); break; } llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-'); if (LastComponent == llvm::StringRef::npos) break; ProgNameRef = ProgNameRef.slice(0, LastComponent); } if (Prefix.empty()) return; std::string IgnoredError; if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) { ArgVector.insert(&ArgVector[1], SaveStringInSet(SavedStrings, Prefix)); ArgVector.insert(&ArgVector[1], SaveStringInSet(SavedStrings, std::string("-ccc-host-triple"))); } }