Skip to content

Unnecessary and x,C introduced due to assume on trunc+zext #143778

Open
@dzaima

Description

@dzaima

The code:

#include<stdint.h>

uint64_t foo(uint64_t a) {
    uint32_t b = a;
    if (b >= 100) __builtin_unreachable();
    return b;
}

with -O3 compiles to:

foo:
        mov rax, rdi
        and eax, 127
        ret

but it could be:

foo:
        mov eax, edi
        ret

compiler explorer on the instcombine pass that introduces the and; namely, it transforms:

define dso_local range(i64 0, 4294967296) i64 @foo(i64 noundef %a) local_unnamed_addr {
entry:
  %conv = trunc i64 %a to i32
  %cmp = icmp uge i32 %conv, 100
  %0 = xor i1 %cmp, true
  call void @llvm.assume(i1 %0)
  %conv2 = zext i32 %conv to i64
  ret i64 %conv2
}

to:

define dso_local range(i64 0, 4294967296) i64 @foo(i64 noundef %a) local_unnamed_addr {
entry:
  %conv = trunc i64 %a to i32
  %cmp = icmp ult i32 %conv, 100
  call void @llvm.assume(i1 %cmp)
  %conv2 = and i64 %a, 127
  ret i64 %conv2
}

reduced from this Rust code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions