1f49f1a87SChandler Carruth //===- ForceFunctionAttrs.cpp - Force function attrs for debugging --------===//
2f49f1a87SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f49f1a87SChandler Carruth //
7f49f1a87SChandler Carruth //===----------------------------------------------------------------------===//
8f49f1a87SChandler Carruth
9f49f1a87SChandler Carruth #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
10f49f1a87SChandler Carruth #include "llvm/IR/Function.h"
11f49f1a87SChandler Carruth #include "llvm/IR/Module.h"
1205da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
13*f1985a3fSserge-sans-paille #include "llvm/Pass.h"
144c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
15f49f1a87SChandler Carruth #include "llvm/Support/Debug.h"
16f49f1a87SChandler Carruth #include "llvm/Support/raw_ostream.h"
17f49f1a87SChandler Carruth using namespace llvm;
18f49f1a87SChandler Carruth
19f49f1a87SChandler Carruth #define DEBUG_TYPE "forceattrs"
20f49f1a87SChandler Carruth
21f49f1a87SChandler Carruth static cl::list<std::string>
22f49f1a87SChandler Carruth ForceAttributes("force-attribute", cl::Hidden,
23f49f1a87SChandler Carruth cl::desc("Add an attribute to a function. This should be a "
24f49f1a87SChandler Carruth "pair of 'function-name:attribute-name', for "
25c7c18d6dSWeiming Zhao "example -force-attribute=foo:noinline. This "
26f49f1a87SChandler Carruth "option can be specified multiple times."));
27f49f1a87SChandler Carruth
287a028fe7SKyungwoo Lee static cl::list<std::string> ForceRemoveAttributes(
297a028fe7SKyungwoo Lee "force-remove-attribute", cl::Hidden,
307a028fe7SKyungwoo Lee cl::desc("Remove an attribute from a function. This should be a "
317a028fe7SKyungwoo Lee "pair of 'function-name:attribute-name', for "
327a028fe7SKyungwoo Lee "example -force-remove-attribute=foo:noinline. This "
337a028fe7SKyungwoo Lee "option can be specified multiple times."));
347a028fe7SKyungwoo Lee
35f49f1a87SChandler Carruth /// If F has any forced attributes given on the command line, add them.
367a028fe7SKyungwoo Lee /// If F has any forced remove attributes given on the command line, remove
377a028fe7SKyungwoo Lee /// them. When both force and force-remove are given to a function, the latter
387a028fe7SKyungwoo Lee /// takes precedence.
forceAttributes(Function & F)397a028fe7SKyungwoo Lee static void forceAttributes(Function &F) {
407a028fe7SKyungwoo Lee auto ParseFunctionAndAttr = [&](StringRef S) {
417a028fe7SKyungwoo Lee auto Kind = Attribute::None;
42f49f1a87SChandler Carruth auto KV = StringRef(S).split(':');
43f49f1a87SChandler Carruth if (KV.first != F.getName())
447a028fe7SKyungwoo Lee return Kind;
457ed3e878SNikita Popov Kind = Attribute::getAttrKindFromName(KV.second);
467ed3e878SNikita Popov if (Kind == Attribute::None || !Attribute::canUseAsFnAttr(Kind)) {
47d34e60caSNicola Zaghen LLVM_DEBUG(dbgs() << "ForcedAttribute: " << KV.second
487ed3e878SNikita Popov << " unknown or not a function attribute!\n");
49f49f1a87SChandler Carruth }
507a028fe7SKyungwoo Lee return Kind;
517a028fe7SKyungwoo Lee };
527a028fe7SKyungwoo Lee
53bb51f76fSKazu Hirata for (const auto &S : ForceAttributes) {
547a028fe7SKyungwoo Lee auto Kind = ParseFunctionAndAttr(S);
557a028fe7SKyungwoo Lee if (Kind == Attribute::None || F.hasFnAttribute(Kind))
56f49f1a87SChandler Carruth continue;
57f49f1a87SChandler Carruth F.addFnAttr(Kind);
58f49f1a87SChandler Carruth }
597a028fe7SKyungwoo Lee
60bb51f76fSKazu Hirata for (const auto &S : ForceRemoveAttributes) {
617a028fe7SKyungwoo Lee auto Kind = ParseFunctionAndAttr(S);
627a028fe7SKyungwoo Lee if (Kind == Attribute::None || !F.hasFnAttribute(Kind))
637a028fe7SKyungwoo Lee continue;
647a028fe7SKyungwoo Lee F.removeFnAttr(Kind);
657a028fe7SKyungwoo Lee }
66f49f1a87SChandler Carruth }
67f49f1a87SChandler Carruth
hasForceAttributes()687a028fe7SKyungwoo Lee static bool hasForceAttributes() {
697a028fe7SKyungwoo Lee return !ForceAttributes.empty() || !ForceRemoveAttributes.empty();
707a028fe7SKyungwoo Lee }
71d73be5afSKyungwoo Lee
run(Module & M,ModuleAnalysisManager &)72164a2aa6SChandler Carruth PreservedAnalyses ForceFunctionAttrsPass::run(Module &M,
73164a2aa6SChandler Carruth ModuleAnalysisManager &) {
74d73be5afSKyungwoo Lee if (!hasForceAttributes())
75f49f1a87SChandler Carruth return PreservedAnalyses::all();
76f49f1a87SChandler Carruth
77f49f1a87SChandler Carruth for (Function &F : M.functions())
787a028fe7SKyungwoo Lee forceAttributes(F);
79f49f1a87SChandler Carruth
80f49f1a87SChandler Carruth // Just conservatively invalidate analyses, this isn't likely to be important.
81f49f1a87SChandler Carruth return PreservedAnalyses::none();
82f49f1a87SChandler Carruth }
83f49f1a87SChandler Carruth
84f49f1a87SChandler Carruth namespace {
85f49f1a87SChandler Carruth struct ForceFunctionAttrsLegacyPass : public ModulePass {
86f49f1a87SChandler Carruth static char ID; // Pass identification, replacement for typeid
ForceFunctionAttrsLegacyPass__anon33c2d5580211::ForceFunctionAttrsLegacyPass87f49f1a87SChandler Carruth ForceFunctionAttrsLegacyPass() : ModulePass(ID) {
88f49f1a87SChandler Carruth initializeForceFunctionAttrsLegacyPassPass(
89f49f1a87SChandler Carruth *PassRegistry::getPassRegistry());
90f49f1a87SChandler Carruth }
91f49f1a87SChandler Carruth
runOnModule__anon33c2d5580211::ForceFunctionAttrsLegacyPass92f49f1a87SChandler Carruth bool runOnModule(Module &M) override {
937a028fe7SKyungwoo Lee if (!hasForceAttributes())
94f49f1a87SChandler Carruth return false;
95f49f1a87SChandler Carruth
96f49f1a87SChandler Carruth for (Function &F : M.functions())
977a028fe7SKyungwoo Lee forceAttributes(F);
98f49f1a87SChandler Carruth
99f49f1a87SChandler Carruth // Conservatively assume we changed something.
100f49f1a87SChandler Carruth return true;
101f49f1a87SChandler Carruth }
102f49f1a87SChandler Carruth };
103f49f1a87SChandler Carruth }
104f49f1a87SChandler Carruth
105f49f1a87SChandler Carruth char ForceFunctionAttrsLegacyPass::ID = 0;
106f49f1a87SChandler Carruth INITIALIZE_PASS(ForceFunctionAttrsLegacyPass, "forceattrs",
107f49f1a87SChandler Carruth "Force set function attributes", false, false)
108f49f1a87SChandler Carruth
createForceFunctionAttrsLegacyPass()109f49f1a87SChandler Carruth Pass *llvm::createForceFunctionAttrsLegacyPass() {
110f49f1a87SChandler Carruth return new ForceFunctionAttrsLegacyPass();
111f49f1a87SChandler Carruth }
112