@@ -5411,6 +5411,178 @@ BasicBlockVisit FlowGraphNaturalLoop::VisitRegularExitBlocks(TFunc func)
5411
5411
return BasicBlockVisit::Continue;
5412
5412
}
5413
5413
5414
+ // -----------------------------------------------------------
5415
+ // gtComplexityExceeds: Check if a tree exceeds a specified complexity limit.
5416
+ //
5417
+ // Type parameters:
5418
+ // TFunc - Callback functor type
5419
+
5420
+ // Arguments:
5421
+ // tree - The tree to check
5422
+ // limit - complexity limit
5423
+ // getTreeComplexity - Callback functor that takes a GenTree* and returns its complexity
5424
+ //
5425
+ // Return Value:
5426
+ // True if 'tree' exceeds the complexity limit, otherwise false.
5427
+ //
5428
+ template <typename TFunc>
5429
+ bool Compiler::gtComplexityExceeds (GenTree* tree, unsigned limit, TFunc getComplexity)
5430
+ {
5431
+ struct ComplexityVisitor : GenTreeVisitor<ComplexityVisitor>
5432
+ {
5433
+ enum
5434
+ {
5435
+ DoPreOrder = true ,
5436
+ };
5437
+
5438
+ ComplexityVisitor (Compiler* comp, unsigned limit, TFunc getComplexity)
5439
+ : GenTreeVisitor<ComplexityVisitor>(comp)
5440
+ , m_complexity(0 )
5441
+ , m_limit(limit)
5442
+ , m_getComplexity(getComplexity)
5443
+ {
5444
+ }
5445
+
5446
+ fgWalkResult PreOrderVisit (GenTree** use, GenTree* user)
5447
+ {
5448
+ m_complexity += m_getComplexity (*use);
5449
+ return (m_complexity > m_limit) ? WALK_ABORT : WALK_CONTINUE;
5450
+ }
5451
+
5452
+ private:
5453
+ unsigned m_complexity;
5454
+ const unsigned m_limit;
5455
+ TFunc m_getComplexity;
5456
+ };
5457
+
5458
+ assert (tree != nullptr );
5459
+
5460
+ ComplexityVisitor visitor (this , limit, getComplexity);
5461
+
5462
+ fgWalkResult result = visitor.WalkTree (&tree, nullptr );
5463
+
5464
+ return (result == WALK_ABORT);
5465
+ }
5466
+
5467
+ // ------------------------------------------------------------------------
5468
+ // ComplexityExceeds: Check if the trees in a block exceed a specified complexity limit.
5469
+ //
5470
+ // Type parameters:
5471
+ // TFunc - Callback functor type
5472
+ //
5473
+ // Arguments:
5474
+ // comp - compiler instance
5475
+ // limit - complexity limit
5476
+ // getTreeComplexity - Callback functor that takes a GenTree* and returns its complexity
5477
+ //
5478
+ // Returns:
5479
+ // True if the trees in the block exceed the complexity limit, otherwise false.
5480
+ //
5481
+ template <typename TFunc>
5482
+ bool BasicBlock::ComplexityExceeds (Compiler* comp, unsigned limit, TFunc getTreeComplexity)
5483
+ {
5484
+ assert (comp != nullptr );
5485
+
5486
+ unsigned localCount = 0 ;
5487
+ auto getComplexity = [&](GenTree* tree) -> unsigned {
5488
+ const unsigned treeComplexity = getTreeComplexity (tree);
5489
+ localCount += treeComplexity;
5490
+ return treeComplexity;
5491
+ };
5492
+
5493
+ for (Statement* const stmt : Statements ())
5494
+ {
5495
+ const unsigned slack = limit - localCount;
5496
+ if (comp->gtComplexityExceeds (stmt->GetRootNode (), slack, getComplexity))
5497
+ {
5498
+ return true ;
5499
+ }
5500
+ }
5501
+
5502
+ return false ;
5503
+ }
5504
+
5505
+ // ------------------------------------------------------------------------
5506
+ // ComplexityExceeds: Check if the trees in a range of blocks exceed a specified complexity limit.
5507
+ //
5508
+ // Type parameters:
5509
+ // TFunc - Callback functor type
5510
+ //
5511
+ // Arguments:
5512
+ // comp - compiler instance
5513
+ // limit - complexity limit
5514
+ // getTreeComplexity - Callback functor that takes a GenTree* and returns its complexity
5515
+ //
5516
+ // Returns:
5517
+ // True if the trees in the block range exceed the complexity limit, otherwise false.
5518
+ //
5519
+ template <typename TFunc>
5520
+ bool BasicBlockRangeList::ComplexityExceeds (Compiler* comp, unsigned limit, TFunc getTreeComplexity)
5521
+ {
5522
+ assert (comp != nullptr );
5523
+
5524
+ unsigned localCount = 0 ;
5525
+ auto getComplexity = [&](GenTree* tree) -> unsigned {
5526
+ const unsigned treeComplexity = getTreeComplexity (tree);
5527
+ localCount += treeComplexity;
5528
+ return treeComplexity;
5529
+ };
5530
+
5531
+ for (BasicBlock* const block : *this )
5532
+ {
5533
+ const unsigned slack = limit - localCount;
5534
+ if (block->ComplexityExceeds (comp, slack, getComplexity))
5535
+ {
5536
+ return true ;
5537
+ }
5538
+ }
5539
+
5540
+ return false ;
5541
+ }
5542
+
5543
+ // ------------------------------------------------------------------------
5544
+ // optLoopComplexityExceeds: Check if the trees in a loop exceed a specified complexity limit.
5545
+ //
5546
+ // Type parameters:
5547
+ // TFunc - Callback functor type
5548
+ //
5549
+ // Arguments:
5550
+ // comp - compiler instance
5551
+ // limit - complexity limit
5552
+ // getTreeComplexity - Callback functor that takes a GenTree* and returns its complexity
5553
+ //
5554
+ // Returns:
5555
+ // True if the trees in 'loop' exceed the complexity limit, otherwise false.
5556
+ //
5557
+ template <typename TFunc>
5558
+ bool Compiler::optLoopComplexityExceeds (FlowGraphNaturalLoop* loop, unsigned limit, TFunc getTreeComplexity)
5559
+ {
5560
+ assert (loop != nullptr );
5561
+
5562
+ unsigned loopComplexity = 0 ;
5563
+ auto getComplexity = [&](GenTree* tree) -> unsigned {
5564
+ const unsigned treeComplexity = getTreeComplexity (tree);
5565
+ loopComplexity += treeComplexity;
5566
+ return treeComplexity;
5567
+ };
5568
+
5569
+ BasicBlockVisit const result = loop->VisitLoopBlocks ([&](BasicBlock* block) {
5570
+ assert (limit >= loopComplexity);
5571
+ const unsigned slack = limit - loopComplexity;
5572
+ return block->ComplexityExceeds (this , slack, getComplexity) ? BasicBlockVisit::Abort
5573
+ : BasicBlockVisit::Continue;
5574
+ });
5575
+
5576
+ if (result == BasicBlockVisit::Abort)
5577
+ {
5578
+ JITDUMP (" Loop " FMT_LP " : exceeds complexity limit %u\n " , loop->GetIndex (), limit);
5579
+ return true ;
5580
+ }
5581
+
5582
+ JITDUMP (" Loop " FMT_LP " : complexity %u does not exceed limit %u\n " , loop->GetIndex (), loopComplexity, limit);
5583
+ return false ;
5584
+ }
5585
+
5414
5586
/* ****************************************************************************/
5415
5587
#endif // _COMPILER_HPP_
5416
5588
/* ****************************************************************************/
0 commit comments