Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix Bugzilla Issue 20535: Backend Optimizer Slowdown in Static Foreach #21019

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

khushishukla2813
Copy link

This PR fixes a performance issue in the DMD backend optimizer when handling large static foreach loops. Previously, excessive iterations over loop structures caused significant slowdowns. This fix optimizes loop traversal and reduces redundant computations, improving compilation speed for large-scale static foreach constructs.

Changes Made
✅ Optimized loop handling in the following backend modules:

blockopt.d → Improved block processing efficiency.
gflow.d → Optimized data flow analysis.
gloop.d → Reduced unnecessary loop iterations.
go.d → Improved general optimizer logic for loops.
✅ Reduces redundant computations and prevents excessive traversal over loop structures.

✅ Improves performance when compiling large static foreach loops by ensuring the optimizer does not reprocess the same loops multiple times.

@dlang-bot
Copy link
Contributor

dlang-bot commented Mar 17, 2025

Thanks for your pull request and interest in making D better, @khushishukla2813! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

Please see CONTRIBUTING.md for more information.


If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment.

Bugzilla references

Auto-close Bugzilla Severity Description
20535 enhancement std.format: %b, %o, %x and %X on negative integers gives wrong result

Testing this PR locally

If you don't have a local development environment setup, you can use Digger to test this PR:

dub run digger -- build "master + dmd#21019"

@khushishukla2813 khushishukla2813 changed the title Fix backend optimizer slowdown in static foreach (Issue #20535) Fix Bugzilla Issue 20535: Backend Optimizer Slowdown in Static Foreach Mar 17, 2025
@@ -66,20 +66,19 @@ nothrow:
/*************************
* Reset memory so this allocation can be re-used.
*/
void reset()
{
void reset() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

brace on newline

Copy link
Contributor

@dkorpel dkorpel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for taking a look at this. The issue is a very complex time complexity problem, and unfortunately, I don't think these small local changes make a positive difference. Perhaps you can find a simpler issue to work on? Something related to the lexer/parser should be a lot simpler than the backend / semantic analysis.

//printf("block_pred()\n");
for (block* b = bo.startblock; b; b = b.Bnext) // for each block
list_free(&b.Bpred,FPNULL);
bool[block*] visited; // Keep track of visited blocks
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable isn't used

void vec_setclear(size_t b, vec_t vs, vec_t vc) { vec_setbit(b, vs); vec_clearbit(b, vc); }
void vec_setclear(size_t b, vec_t vs, vec_t vc)
{
if (vec_testbit(b, vs) && !vec_testbit(b, vc)) return; // Avoid redundant operations
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting and clearing a bit takes a trivial amount of time, I think this added check only makes things slower.

{
void reset()
{
if (Lloop !is null)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vec_free already checks for null, so these checks are redundant

list_prepend(&(list_block(bp).Bpred),b);
{
block* succBlock = list_block(bp);
if (succBlock !is null) // Ensure valid successor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert ensured this case is impossible, so this check should be redundant

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants