|
16 | 16 |
|
17 | 17 | #include "llvm/Transforms/Coroutines/CoroAnnotationElide.h" |
18 | 18 |
|
| 19 | +#include "llvm/Analysis/CGSCCPassManager.h" |
19 | 20 | #include "llvm/Analysis/LazyCallGraph.h" |
20 | 21 | #include "llvm/Analysis/OptimizationRemarkEmitter.h" |
21 | 22 | #include "llvm/IR/Analysis.h" |
22 | 23 | #include "llvm/IR/IRBuilder.h" |
23 | 24 | #include "llvm/IR/Instruction.h" |
24 | 25 | #include "llvm/IR/Module.h" |
25 | 26 | #include "llvm/IR/PassManager.h" |
| 27 | +#include "llvm/Transforms/Utils/CallGraphUpdater.h" |
| 28 | +#include "llvm/Transforms/Utils/Cloning.h" |
26 | 29 |
|
27 | 30 | #include <cassert> |
28 | 31 |
|
@@ -90,61 +93,86 @@ static void processCall(CallBase *CB, Function *Caller, Function *NewCallee, |
90 | 93 |
|
91 | 94 | NewCB->removeFnAttr(llvm::Attribute::CoroElideSafe); |
92 | 95 | CB->replaceAllUsesWith(NewCB); |
93 | | - CB->eraseFromParent(); |
| 96 | + |
| 97 | + InlineFunctionInfo IFI; |
| 98 | + InlineResult IR = InlineFunction(*NewCB, IFI); |
| 99 | + if (IR.isSuccess()) { |
| 100 | + CB->eraseFromParent(); |
| 101 | + } else { |
| 102 | + NewCB->replaceAllUsesWith(CB); |
| 103 | + NewCB->eraseFromParent(); |
| 104 | + } |
94 | 105 | } |
95 | 106 |
|
96 | | -PreservedAnalyses CoroAnnotationElidePass::run(Function &F, |
97 | | - FunctionAnalysisManager &FAM) { |
| 107 | +PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C, |
| 108 | + CGSCCAnalysisManager &AM, |
| 109 | + LazyCallGraph &CG, |
| 110 | + CGSCCUpdateResult &UR) { |
98 | 111 | bool Changed = false; |
| 112 | + CallGraphUpdater CGUpdater; |
| 113 | + CGUpdater.initialize(CG, C, AM, UR); |
99 | 114 |
|
100 | | - Function *NewCallee = |
101 | | - F.getParent()->getFunction((F.getName() + ".noalloc").str()); |
102 | | - |
103 | | - if (!NewCallee) |
104 | | - return PreservedAnalyses::all(); |
105 | | - |
106 | | - auto FramePtrArgPosition = NewCallee->arg_size() - 1; |
107 | | - auto FrameSize = NewCallee->getParamDereferenceableBytes(FramePtrArgPosition); |
108 | | - auto FrameAlign = NewCallee->getParamAlign(FramePtrArgPosition).valueOrOne(); |
| 115 | + auto &FAM = |
| 116 | + AM.getResult<FunctionAnalysisManagerCGSCCProxy>(C, CG).getManager(); |
109 | 117 |
|
110 | | - SmallVector<CallBase *, 4> Users; |
111 | | - for (auto *U : F.users()) { |
112 | | - if (auto *CB = dyn_cast<CallBase>(U)) { |
113 | | - if (CB->getCalledFunction() == &F) |
114 | | - Users.push_back(CB); |
115 | | - } |
116 | | - } |
117 | | - |
118 | | - auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F); |
119 | | - |
120 | | - for (auto *CB : Users) { |
121 | | - auto *Caller = CB->getFunction(); |
122 | | - if (!Caller) |
| 118 | + for (LazyCallGraph::Node &N : C) { |
| 119 | + Function *Callee = &N.getFunction(); |
| 120 | + Function *NewCallee = Callee->getParent()->getFunction( |
| 121 | + (Callee->getName() + ".noalloc").str()); |
| 122 | + if (!NewCallee) |
123 | 123 | continue; |
124 | 124 |
|
125 | | - bool IsCallerPresplitCoroutine = Caller->isPresplitCoroutine(); |
126 | | - bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe); |
127 | | - if (IsCallerPresplitCoroutine && HasAttr) { |
128 | | - processCall(CB, Caller, NewCallee, FrameSize, FrameAlign); |
129 | | - |
130 | | - ORE.emit([&]() { |
131 | | - return OptimizationRemark(DEBUG_TYPE, "CoroAnnotationElide", Caller) |
132 | | - << "'" << ore::NV("callee", F.getName()) << "' elided in '" |
133 | | - << ore::NV("caller", Caller->getName()) << "'"; |
134 | | - }); |
135 | | - |
136 | | - FAM.invalidate(*Caller, PreservedAnalyses::none()); |
137 | | - Changed = true; |
138 | | - } else { |
139 | | - ORE.emit([&]() { |
140 | | - return OptimizationRemarkMissed(DEBUG_TYPE, "CoroAnnotationElide", |
141 | | - Caller) |
142 | | - << "'" << ore::NV("callee", F.getName()) << "' not elided in '" |
143 | | - << ore::NV("caller", Caller->getName()) << "' (caller_presplit=" |
144 | | - << ore::NV("caller_presplit", IsCallerPresplitCoroutine) |
145 | | - << ", elide_safe_attr=" << ore::NV("elide_safe_attr", HasAttr) |
146 | | - << ")"; |
147 | | - }); |
| 125 | + SmallVector<CallBase *, 4> Users; |
| 126 | + for (auto *U : Callee->users()) { |
| 127 | + if (auto *CB = dyn_cast<CallBase>(U)) { |
| 128 | + if (CB->getCalledFunction() == Callee) |
| 129 | + Users.push_back(CB); |
| 130 | + } |
| 131 | + } |
| 132 | + auto FramePtrArgPosition = NewCallee->arg_size() - 1; |
| 133 | + auto FrameSize = |
| 134 | + NewCallee->getParamDereferenceableBytes(FramePtrArgPosition); |
| 135 | + auto FrameAlign = |
| 136 | + NewCallee->getParamAlign(FramePtrArgPosition).valueOrOne(); |
| 137 | + |
| 138 | + auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(*Callee); |
| 139 | + |
| 140 | + for (auto *CB : Users) { |
| 141 | + auto *Caller = CB->getFunction(); |
| 142 | + if (!Caller) |
| 143 | + continue; |
| 144 | + |
| 145 | + bool IsCallerPresplitCoroutine = Caller->isPresplitCoroutine(); |
| 146 | + bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe); |
| 147 | + if (IsCallerPresplitCoroutine && HasAttr) { |
| 148 | + auto *CallerN = CG.lookup(*Caller); |
| 149 | + auto *CallerC = CG.lookupSCC(*CallerN); |
| 150 | + processCall(CB, Caller, NewCallee, FrameSize, FrameAlign); |
| 151 | + |
| 152 | + ORE.emit([&]() { |
| 153 | + return OptimizationRemark(DEBUG_TYPE, "CoroAnnotationElide", Caller) |
| 154 | + << "'" << ore::NV("callee", Callee->getName()) |
| 155 | + << "' elided in '" << ore::NV("caller", Caller->getName()) |
| 156 | + << "'"; |
| 157 | + }); |
| 158 | + |
| 159 | + FAM.invalidate(*Caller, PreservedAnalyses::none()); |
| 160 | + Changed = true; |
| 161 | + updateCGAndAnalysisManagerForCGSCCPass(CG, *CallerC, *CallerN, AM, UR, |
| 162 | + FAM); |
| 163 | + |
| 164 | + } else { |
| 165 | + ORE.emit([&]() { |
| 166 | + return OptimizationRemarkMissed(DEBUG_TYPE, "CoroAnnotationElide", |
| 167 | + Caller) |
| 168 | + << "'" << ore::NV("callee", Callee->getName()) |
| 169 | + << "' not elided in '" << ore::NV("caller", Caller->getName()) |
| 170 | + << "' (caller_presplit=" |
| 171 | + << ore::NV("caller_presplit", IsCallerPresplitCoroutine) |
| 172 | + << ", elide_safe_attr=" << ore::NV("elide_safe_attr", HasAttr) |
| 173 | + << ")"; |
| 174 | + }); |
| 175 | + } |
148 | 176 | } |
149 | 177 | } |
150 | 178 |
|
|
0 commit comments