llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.34k stars 12.13k forks source link

Failure to unroll loop with unknown but small count #116119

Open Kmeakin opened 2 weeks ago

Kmeakin commented 2 weeks ago

Consider this function that calculates the number of digits in n's base-10 representation (eg as part of a formatting library):

u8 src(u8 n) {
    u8 num_digits = 0;
    do {
        num_digits++;
        n /= 10;
    } while (n != 0);
    return num_digits;
}

Since n is in the range 0-255, the loop will run exactly 1, 2 or 3 times, and the function can be optimized by unrolling the loop manually:

u8 intermediate(u8 n) {
    u8 num_digits = 0;

    // iteration 1
    num_digits++;
    n /= 10;
    if (n == 0) return num_digits;

    // iteration 2
    num_digits++;
    n /= 10;
    if (n == 0) return num_digits;

    // iteration 3
    num_digits++;
    n /= 10;

    return num_digits;
}

which then simplifies to:

u8 tgt(u8 n) {
    if (n < 10) return 1;
    if (n < 100) return 2;
    return 3;
}

LLVM is smart enough to do this optimization if the base is 16, but not for any other base

VedantParanjape commented 2 weeks ago

So do you mean this unrolling works for u16?

Kmeakin commented 1 week ago

So do you mean this unrolling works for u16?

No, I mean if n /= 16 instead of n /= 10

VedantParanjape commented 1 week ago

So do you mean this unrolling works for u16?

No, I mean if n /= 16 instead of n /= 10

That's expected, can you try after enabling epilogue vectorization? I am not sure if it is enabled by default.