Skip to content

Constant fold during mem2reg pass #2445

@jfecher

Description

@jfecher

Problem

Even after being updated to handle aliases within arrays (in an experimental branch), the mem2reg pass still fails to fully remove all loads and stores from the following code:

fn main() {
    let mut var = 0;
    let ref = &mut &mut var;

    let mut array = [ref, ref];

    **array[0] = 1;
    **array[1] = 2;

    assert(var == 2);
    assert(**ref == 2);
    assert(**array[0] == 2);
    assert(**array[1] == 2);
}

This is because when optimizing out references stored in arrays, mem2reg can only do one step at a time. That is, it can optimize until it finds a v3 = array_get [v1, v2], index 1. It cannot see which reference is returned until the constant folding pass is done, so it counts v3 as opaque which prevents further optimizations on it.

The problem occurs when v3 is later loaded/stored to. We now need another mem2reg pass after the constant folding pass. Then, if there are more gets/sets to the array we'd need another constant folding pass and so on. Each time we run an entire pass, only 1 additional step of this will be optimized each time.

Happy Case

We should apply instruction simplifications while running the mem2reg pass, like we do with most other optimization passes. This would enable the pass to optimize the code in the snippet in one run without the need of another mem2reg pass or even a constant folding pass after.

Alternatives Considered

No response

Additional Context

No response

Would you like to submit a PR for this Issue?

No

Support Needs

No response

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

Status

✅ Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions