@@ -199,6 +199,29 @@ void FunctionPropertiesInfo::updateForBB(const BasicBlock &BB,
199199#undef CHECK_OPERAND
200200 }
201201 }
202+
203+ if (IR2VecVocab) {
204+ // We instantiate the IR2Vec embedder each time, as having an unique
205+ // pointer to the embedder as member of the class would make it
206+ // non-copyable. Instantiating the embedder in itself is not costly.
207+ auto EmbOrErr = ir2vec::Embedder::create (IR2VecKind::Symbolic,
208+ *BB.getParent (), *IR2VecVocab);
209+ if (Error Err = EmbOrErr.takeError ()) {
210+ handleAllErrors (std::move (Err), [&](const ErrorInfoBase &EI) {
211+ BB.getContext ().emitError (" Error creating IR2Vec embeddings: " +
212+ EI.message ());
213+ });
214+ return ;
215+ }
216+ auto Embedder = std::move (*EmbOrErr);
217+ const auto &BBEmbedding = Embedder->getBBVector (BB);
218+ // Subtract BBEmbedding from Function embedding if the direction is -1,
219+ // and add it if the direction is +1.
220+ if (Direction == -1 )
221+ FunctionEmbedding -= BBEmbedding;
222+ else
223+ FunctionEmbedding += BBEmbedding;
224+ }
202225}
203226
204227void FunctionPropertiesInfo::updateAggregateStats (const Function &F,
@@ -220,21 +243,91 @@ void FunctionPropertiesInfo::updateAggregateStats(const Function &F,
220243
221244FunctionPropertiesInfo FunctionPropertiesInfo::getFunctionPropertiesInfo (
222245 Function &F, FunctionAnalysisManager &FAM) {
246+ // We use the cached result of the IR2VecVocabAnalysis run by
247+ // InlineAdvisorAnalysis. If the IR2VecVocabAnalysis is not run, we don't
248+ // use IR2Vec embeddings.
249+ auto VocabResult = FAM.getResult <ModuleAnalysisManagerFunctionProxy>(F)
250+ .getCachedResult <IR2VecVocabAnalysis>(*F.getParent ());
223251 return getFunctionPropertiesInfo (F, FAM.getResult <DominatorTreeAnalysis>(F),
224- FAM.getResult <LoopAnalysis>(F));
252+ FAM.getResult <LoopAnalysis>(F), VocabResult );
225253}
226254
227255FunctionPropertiesInfo FunctionPropertiesInfo::getFunctionPropertiesInfo (
228- const Function &F, const DominatorTree &DT, const LoopInfo &LI) {
256+ const Function &F, const DominatorTree &DT, const LoopInfo &LI,
257+ const IR2VecVocabResult *VocabResult) {
229258
230259 FunctionPropertiesInfo FPI;
260+ if (VocabResult && VocabResult->isValid ()) {
261+ FPI.IR2VecVocab = VocabResult->getVocabulary ();
262+ FPI.FunctionEmbedding = ir2vec::Embedding (VocabResult->getDimension (), 0.0 );
263+ }
231264 for (const auto &BB : F)
232265 if (DT.isReachableFromEntry (&BB))
233266 FPI.reIncludeBB (BB);
234267 FPI.updateAggregateStats (F, LI);
235268 return FPI;
236269}
237270
271+ bool FunctionPropertiesInfo::operator ==(
272+ const FunctionPropertiesInfo &FPI) const {
273+ if (BasicBlockCount != FPI.BasicBlockCount ||
274+ BlocksReachedFromConditionalInstruction !=
275+ FPI.BlocksReachedFromConditionalInstruction ||
276+ Uses != FPI.Uses ||
277+ DirectCallsToDefinedFunctions != FPI.DirectCallsToDefinedFunctions ||
278+ LoadInstCount != FPI.LoadInstCount ||
279+ StoreInstCount != FPI.StoreInstCount ||
280+ MaxLoopDepth != FPI.MaxLoopDepth ||
281+ TopLevelLoopCount != FPI.TopLevelLoopCount ||
282+ TotalInstructionCount != FPI.TotalInstructionCount ||
283+ BasicBlocksWithSingleSuccessor != FPI.BasicBlocksWithSingleSuccessor ||
284+ BasicBlocksWithTwoSuccessors != FPI.BasicBlocksWithTwoSuccessors ||
285+ BasicBlocksWithMoreThanTwoSuccessors !=
286+ FPI.BasicBlocksWithMoreThanTwoSuccessors ||
287+ BasicBlocksWithSinglePredecessor !=
288+ FPI.BasicBlocksWithSinglePredecessor ||
289+ BasicBlocksWithTwoPredecessors != FPI.BasicBlocksWithTwoPredecessors ||
290+ BasicBlocksWithMoreThanTwoPredecessors !=
291+ FPI.BasicBlocksWithMoreThanTwoPredecessors ||
292+ BigBasicBlocks != FPI.BigBasicBlocks ||
293+ MediumBasicBlocks != FPI.MediumBasicBlocks ||
294+ SmallBasicBlocks != FPI.SmallBasicBlocks ||
295+ CastInstructionCount != FPI.CastInstructionCount ||
296+ FloatingPointInstructionCount != FPI.FloatingPointInstructionCount ||
297+ IntegerInstructionCount != FPI.IntegerInstructionCount ||
298+ ConstantIntOperandCount != FPI.ConstantIntOperandCount ||
299+ ConstantFPOperandCount != FPI.ConstantFPOperandCount ||
300+ ConstantOperandCount != FPI.ConstantOperandCount ||
301+ InstructionOperandCount != FPI.InstructionOperandCount ||
302+ BasicBlockOperandCount != FPI.BasicBlockOperandCount ||
303+ GlobalValueOperandCount != FPI.GlobalValueOperandCount ||
304+ InlineAsmOperandCount != FPI.InlineAsmOperandCount ||
305+ ArgumentOperandCount != FPI.ArgumentOperandCount ||
306+ UnknownOperandCount != FPI.UnknownOperandCount ||
307+ CriticalEdgeCount != FPI.CriticalEdgeCount ||
308+ ControlFlowEdgeCount != FPI.ControlFlowEdgeCount ||
309+ UnconditionalBranchCount != FPI.UnconditionalBranchCount ||
310+ IntrinsicCount != FPI.IntrinsicCount ||
311+ DirectCallCount != FPI.DirectCallCount ||
312+ IndirectCallCount != FPI.IndirectCallCount ||
313+ CallReturnsIntegerCount != FPI.CallReturnsIntegerCount ||
314+ CallReturnsFloatCount != FPI.CallReturnsFloatCount ||
315+ CallReturnsPointerCount != FPI.CallReturnsPointerCount ||
316+ CallReturnsVectorIntCount != FPI.CallReturnsVectorIntCount ||
317+ CallReturnsVectorFloatCount != FPI.CallReturnsVectorFloatCount ||
318+ CallReturnsVectorPointerCount != FPI.CallReturnsVectorPointerCount ||
319+ CallWithManyArgumentsCount != FPI.CallWithManyArgumentsCount ||
320+ CallWithPointerArgumentCount != FPI.CallWithPointerArgumentCount ) {
321+ return false ;
322+ }
323+ // Check the equality of the function embeddings. We don't check the equality
324+ // of Vocabulary as it remains the same.
325+ if (!FunctionEmbedding.approximatelyEquals (FPI.FunctionEmbedding ))
326+ return false ;
327+
328+ return true ;
329+ }
330+
238331void FunctionPropertiesInfo::print (raw_ostream &OS) const {
239332#define PRINT_PROPERTY (PROP_NAME ) OS << #PROP_NAME " : " << PROP_NAME << " \n " ;
240333
@@ -322,6 +415,16 @@ FunctionPropertiesUpdater::FunctionPropertiesUpdater(
322415 // The caller's entry BB may change due to new alloca instructions.
323416 LikelyToChangeBBs.insert (&*Caller.begin ());
324417
418+ // The users of the value returned by call instruction can change
419+ // leading to the change in embeddings being computed, when used.
420+ // We conservatively add the BBs with such uses to LikelyToChangeBBs.
421+ for (const auto *User : CB.users ())
422+ CallUsers.insert (dyn_cast<Instruction>(User)->getParent ());
423+ // CallSiteBB can be removed from CallUsers if present, it's taken care
424+ // separately.
425+ CallUsers.erase (&CallSiteBB);
426+ LikelyToChangeBBs.insert_range (CallUsers);
427+
325428 // The successors may become unreachable in the case of `invoke` inlining.
326429 // We track successors separately, too, because they form a boundary, together
327430 // with the CB BB ('Entry') between which the inlined callee will be pasted.
@@ -435,6 +538,9 @@ void FunctionPropertiesUpdater::finish(FunctionAnalysisManager &FAM) const {
435538 if (&CallSiteBB != &*Caller.begin ())
436539 Reinclude.insert (&*Caller.begin ());
437540
541+ // Reinclude the BBs which use the values returned by call instruction
542+ Reinclude.insert_range (CallUsers);
543+
438544 // Distribute the successors to the 2 buckets.
439545 for (const auto *Succ : Successors)
440546 if (DT.isReachableFromEntry (Succ))
@@ -486,6 +592,9 @@ bool FunctionPropertiesUpdater::isUpdateValid(Function &F,
486592 return false ;
487593 DominatorTree DT (F);
488594 LoopInfo LI (DT);
489- auto Fresh = FunctionPropertiesInfo::getFunctionPropertiesInfo (F, DT, LI);
595+ auto VocabResult = FAM.getResult <ModuleAnalysisManagerFunctionProxy>(F)
596+ .getCachedResult <IR2VecVocabAnalysis>(*F.getParent ());
597+ auto Fresh =
598+ FunctionPropertiesInfo::getFunctionPropertiesInfo (F, DT, LI, VocabResult);
490599 return FPI == Fresh;
491600}
0 commit comments