dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.47k stars 4.76k forks source link

JIT: eliminate tests for completely determined expressions #10828

Open scalablecory opened 6 years ago

scalablecory commented 6 years ago

I'd like the JIT to detect when one branch leads to another branch, and fold them into a single branch.

I'm sure this optimization has a specific name in compiler theory, but I don't know it. If you'll excuse a dumb example:

int InitialBranching(string x)
{
    if (x == "foo") return 0;
    if (x == "bar") return 0;
    if (x == "baz") return 1;
    return -1;
}

string SubsequentBranching(string x)
{
    int y = InitialBranching(x);

    if (y == 0) return x + "0";
    if (y == 1) return x + "1";
    return "other";
}

Here, a sufficiently advanced compiler should be able to transform this into something like:

string Folded(string x)
{
    if (x == "foo") goto zero;
    if (x == "bar") goto zero;
    if (x == "baz") goto one;
    goto other;

    zero:
    return x + "0";

    one:
    return x + "1";

    other:
    return "other";
}

Why?

Obviously, the dumb example is not what I'm actually doing. For performance purposes I'm updating a text parser from depending on char to be encoding-agnostic. In some places, it needs to allow injecting inlineable sub-parsers that handles encoding-specific things:

// returns length of newline if matched, 0 if not matched, -1 if more data is needed.
int IsNewLine<T>(ReadOnlySpan<T> data);

This sits right in a hotspot in my code: optimizing this bit makes a huge difference. I've found the extra tests needed to check the return value are causing the code to perform at about 1/4th the speed when compared to a non-agnostic version with IsNewLine manually inlined. Having the compiler optimize away these tests would make a huge difference to me.

category:cq theme:optimization skill-level:expert cost:large

RussKeldorph commented 6 years ago

@dotnet/jit-contrib

AndyAyersMS commented 6 years ago

There are actually two optimizations here.

BruceForstall commented 4 years ago

Another tail merge issue: https://github.com/dotnet/runtime/issues/8795

AndyAyersMS commented 2 years ago

@scalablecory realize it's been a while, but do you have example code we can try?

The jit may be getting close to doing what you expect...