@@ -307,21 +307,21 @@ void BinaryFunction::computeBlockHashes(HashFunction HashFunction) const {
307307 BB->setHash (BlendedHashes[I].combine ());
308308 }
309309}
310-
310+ // TODO: mediate the difference between flow function construction here in BOLT
311+ // and in the compiler by splitting blocks with exception throwing calls at the
312+ // call and adding the landing pad as the successor.
311313// / Create a wrapper flow function to use with the profile inference algorithm,
312314// / and initialize its jumps and metadata.
313315FlowFunction
314316createFlowFunction (const BinaryFunction::BasicBlockOrderType &BlockOrder) {
315317 FlowFunction Func;
316318
317319 // Add a special "dummy" source so that there is always a unique entry point.
318- // Because of the extra source, for all other blocks in FlowFunction it holds
319- // that Block.Index == BB->getIndex() + 1
320320 FlowBlock EntryBlock;
321321 EntryBlock.Index = 0 ;
322322 Func.Blocks .push_back (EntryBlock);
323323
324- // Create FlowBlock for every basic block in the binary function
324+ // Create FlowBlock for every basic block in the binary function.
325325 for (const BinaryBasicBlock *BB : BlockOrder) {
326326 Func.Blocks .emplace_back ();
327327 FlowBlock &Block = Func.Blocks .back ();
@@ -331,7 +331,12 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
331331 " incorrectly assigned basic block index" );
332332 }
333333
334- // Create FlowJump for each jump between basic blocks in the binary function
334+ // Add a special "dummy" sink block so there is always a unique sink.
335+ FlowBlock SinkBlock;
336+ SinkBlock.Index = Func.Blocks .size ();
337+ Func.Blocks .push_back (SinkBlock);
338+
339+ // Create FlowJump for each jump between basic blocks in the binary function.
335340 std::vector<uint64_t > InDegree (Func.Blocks .size (), 0 );
336341 for (const BinaryBasicBlock *SrcBB : BlockOrder) {
337342 std::unordered_set<const BinaryBasicBlock *> UniqueSuccs;
@@ -348,6 +353,16 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
348353 InDegree[Jump.Target ]++;
349354 UniqueSuccs.insert (DstBB);
350355 }
356+ // TODO: set jump from exit block to landing pad to Unlikely.
357+ // If the block is an exit, add a dummy edge from it to the sink block.
358+ if (UniqueSuccs.empty ()) {
359+ Func.Jumps .emplace_back ();
360+ FlowJump &Jump = Func.Jumps .back ();
361+ Jump.Source = SrcBB->getIndex () + 1 ;
362+ Jump.Target = Func.Blocks .size () - 1 ;
363+ InDegree[Jump.Target ]++;
364+ }
365+
351366 // Collect jumps to landing pads
352367 for (const BinaryBasicBlock *DstBB : SrcBB->landing_pads ()) {
353368 // Ignoring parallel edges
@@ -364,9 +379,9 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
364379 }
365380
366381 // Add dummy edges to the extra sources. If there are multiple entry blocks,
367- // add an unlikely edge from 0 to the subsequent ones
382+ // add an unlikely edge from 0 to the subsequent ones. Skips the sink block.
368383 assert (InDegree[0 ] == 0 && " dummy entry blocks shouldn't have predecessors" );
369- for (uint64_t I = 1 ; I < Func.Blocks .size (); I++) {
384+ for (uint64_t I = 1 ; I < Func.Blocks .size () - 1 ; I++) {
370385 const BinaryBasicBlock *BB = BlockOrder[I - 1 ];
371386 if (BB->isEntryPoint () || InDegree[I] == 0 ) {
372387 Func.Jumps .emplace_back ();
@@ -400,7 +415,7 @@ createFlowFunction(const BinaryFunction::BasicBlockOrderType &BlockOrder) {
400415size_t matchWeightsByHashes (
401416 BinaryContext &BC, const BinaryFunction::BasicBlockOrderType &BlockOrder,
402417 const yaml::bolt::BinaryFunctionProfile &YamlBF, FlowFunction &Func) {
403- assert (Func.Blocks .size () == BlockOrder.size () + 1 );
418+ assert (Func.Blocks .size () == BlockOrder.size () + 2 );
404419
405420 std::vector<FlowBlock *> Blocks;
406421 std::vector<BlendedBlockHash> BlendedHashes;
@@ -592,9 +607,9 @@ bool canApplyInference(const FlowFunction &Func,
592607 opts::StaleMatchingMinMatchedBlock * YamlBF.Blocks .size ())
593608 return false ;
594609
595- bool HasExitBlocks = llvm::any_of (
596- Func. Blocks , [&]( const FlowBlock &Block) { return Block. isExit (); });
597- if (!HasExitBlocks )
610+ // Returns false if the artificial sink block has no predecessors meaning
611+ // there are no exit blocks.
612+ if (Func. Blocks [Func. Blocks . size () - 1 ]. isEntry () )
598613 return false ;
599614
600615 return true ;
@@ -631,7 +646,7 @@ void assignProfile(BinaryFunction &BF,
631646 FlowFunction &Func) {
632647 BinaryContext &BC = BF.getBinaryContext ();
633648
634- assert (Func.Blocks .size () == BlockOrder.size () + 1 );
649+ assert (Func.Blocks .size () == BlockOrder.size () + 2 );
635650 for (uint64_t I = 0 ; I < BlockOrder.size (); I++) {
636651 FlowBlock &Block = Func.Blocks [I + 1 ];
637652 BinaryBasicBlock *BB = BlockOrder[I];
@@ -653,6 +668,9 @@ void assignProfile(BinaryFunction &BF,
653668 if (Jump->Flow == 0 )
654669 continue ;
655670
671+ // Skips the artificial sink block.
672+ if (Jump->Target == Func.Blocks .size () - 1 )
673+ continue ;
656674 BinaryBasicBlock &SuccBB = *BlockOrder[Jump->Target - 1 ];
657675 // Check if the edge corresponds to a regular jump or a landing pad
658676 if (BB->getSuccessor (SuccBB.getLabel ())) {
0 commit comments