llvm / llvm-project

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

function return `range` metadata not inferred from `assume`s #98946

Open Kmeakin opened 1 month ago

Kmeakin commented 1 month ago

The propagation of range information from assume is very fragile. Things that prevent it from propagating:

https://godbolt.org/z/hvdxE1xKn

#include <stdbool.h>
#include <stdint.h>

typedef uint32_t u32;

void assume(bool b) { __builtin_assume(b); }

bool is_surrogate(u32 c) { return 0xD800 <= c && c <= 0xDFFF; }

// range not inferred
u32 f1(u32 c) {
    assume(!is_surrogate(c));
    return c;
}

// range not inferred
u32 f2(u32 c) {
    __builtin_assume(!is_surrogate(c));
    return c;
}

// range not inferred
u32 f3(u32 c) {
    __builtin_assume(!(0xD800 <= c && c <= 0xDFFF));
    return c;
}

// range not inferred
u32 f4(u32 c) {
    __builtin_assume(c < 0xD800 || c > 0xDFFF);
    return c;
}

// range(i32 0, 55296) inferred
u32 f5(u32 c) {
    __builtin_assume(c < 0xD800);
    return c;
}

// range(i32 55297, 0) inferred
u32 f6(u32 c) {
    __builtin_assume(c > 0xD800);
    return c;
}

// range not inferred
u32 f7(u32 c) {
    __builtin_assume(!(0xD800 <= c));
    return c;
}

// range not inferred
u32 f8(u32 c) {
    __builtin_assume(!(c <= 0xDFFF));
    return c;
}
nikic commented 1 month ago

range attributes are currently only inferred by IPSCCP, which runs very early. We could also do it in SCCP and CVP, which should cover these cases.