Issue 107774
Summary `assume`s prevent deletion of dead code
Labels missed-optimization
Assignees
Reporter Kmeakin
    # Rust example
`src` contains dead branches that are not removed:
https://godbolt.org/z/MabExKqET
```rust
#[no_mangle]
pub fn src(s: &str) -> bool {
 s.chars().next().is_none()
}

#[no_mangle]
pub fn tgt(s: &str) -> bool {
    s.len() == 0
}
```

```asm
src:
        cbz x1, .LBB0_2
        ldrsb   w8, [x0]
        tbnz    w8, #31, .LBB0_3
.LBB0_2:
        cmp     x1, #0
        cset    w0, eq
 ret
.LBB0_3:
        and     w8, w8, #0xff
        cmp     w8, #224
        cmp     x1, #0
        cset    w0, eq
 ret

tgt:
        cmp     x1, #0
        cset    w0, eq
 ret
```

# C example
The same example, translated to C
https://godbolt.org/z/Yn3Esa37M
```c
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>

typedef uint8_t u8;
typedef uint32_t u32;
typedef size_t usize;

#if ASSUME == 1
#define assume(cond) __builtin_assume(cond)
#else
#define assume(cond) (cond)
#endif

const u32 NONE = -1;

inline u32 next_codepoint(u8* bytes, usize len) {
    if (len == 0) {
 return NONE;
    }

    assume(len != 0);
    u8 b0 = bytes[0];
    if (b0 < 0x80) {
        return b0;
    }

 assume(len != 1);
    u8 b1 = bytes[1];
    u32 b0_b1 = (b0 & 0x1F) << 6 | (b1 & 0x3F);
    if (b0 < 0xE0) {
        return b0_b1;
 }

    assume(len != 2);
    u8 b2 = bytes[2];
    u32 b0_b1_b2 = (b0_b1 << 6) | (b2 & 0x3F);
    if (b0 < 0xF0) {
        return b0_b1_b2;
    }

    assume(len != 3);
    u8 b3 = bytes[3];
 u32 b0_b1_b2_b3 = (b0_b1_b2 << 6) | (b3 & 0x3F);
    return b0_b1_b2_b3 & 0x1F'FF'FF;
}

bool src(u8* bytes, usize len) { return next_codepoint(bytes, len) == NONE; }

bool tgt(u8* bytes, usize len) { return len == 0; }
```

If `assume` is defined as a no-op instead as `__builtin_assume`, the dead code is able to be deleted.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to