-
Notifications
You must be signed in to change notification settings - Fork 14.9k
Description
Hello,
Since llvm.memset.inline
was introduced (commit 38637ee), its documentation on https://llvm.org/docs/LangRef.html#llvm-memset-inline-intrinsic contains:
declare void @llvm.memset.inline.p0.p0i8.i32(ptr <dest>, i8 <val>,
i32 <len>, i1 <isvolatile>)
declare void @llvm.memset.inline.p0.p0.i64(ptr <dest>, i8 <val>,
i64 <len>, i1 <isvolatile>)
Using p0i8
and p0.p0
in the names seems strange. Actually, this is not what clang
generates. Indeed, when clang
compiles __builtin_memset_inline
, it produces @llvm.memset.inline.p0.i64
. There already is a test for this:
llvm-project/clang/test/CodeGen/builtins-memset-inline.c
Lines 6 to 9 in 20bcf12
void test_memset_inline_0(void *dst, char value) { | |
// CHECK: call void @llvm.memset.inline.p0.i64(ptr align 1 %0, i8 %2, i64 0, i1 false) | |
__builtin_memset_inline(dst, value, 0); | |
} |
Moreover, even when compiling in 32-bit mode (using clang -target i686-unknown-linux -S -emit-llvm clang/test/CodeGen/builtins-memset-inline.c -o -
) produces calls to @llvm.memset.inline.p0.i64
, not ....p0.i32
. The 32-bit variant seems to be accepted by the LLVM IR compiler anyway:
$ cat builtins-memset-inline.ll
target triple = "i686-unknown-linux"
; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @test_memset_inline_4(ptr noundef %0, i8 noundef signext %1) #0 {
call void @llvm.memset.inline.p0.i32(ptr align 1 %0, i8 %1, i32 4, i1 false)
ret void
}
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.inline.p0.i32(ptr nocapture writeonly, i8, i32, i1 immarg) #1
$ clang -O2 -target i686-unknown-linux -S builtins-memset-inline.ll -o -
.file "builtins-memset-inline.ll"
.text
.globl test_memset_inline_4 # -- Begin function test_memset_inline_4
.p2align 4
.type test_memset_inline_4,@function
test_memset_inline_4: # @test_memset_inline_4
# %bb.0:
movzbl 8(%esp), %ecx
movl 4(%esp), %eax
imull $16843009, %ecx, %ecx # imm = 0x1010101
movl %ecx, (%eax)
retl
.Lfunc_end0:
.size test_memset_inline_4, .Lfunc_end0-test_memset_inline_4
# -- End function
.section ".note.GNU-stack","",@progbits
.addrsig
(The call to @llvm.memset.inline.p0.i32
was correctly inlined to imull $16843009, %ecx, %ecx
and movl %ecx, (%eax)
)
In short, I believe there are 2 possible issues:
- The documentation of
llvm.memset.inline
' intrinsics contain functions with the wrong names: https://github.com/llvm/llvm-project/blob/20bcf123e2db033f208462f34f63e292efbe0946/llvm/docs/LangRef.rst#L16013-L16016 - When compiling a C program in 32-bit mode,
@llvm.memset.inline.p0.i64
is generated instead of@llvm.memset.inline.p0.i32
.
What do you think?
In case it is useful, I used several released versions of clang
to reproduce the tests, including clang 20.1.8 (0ubuntu4) on Ubuntu 25.10 and clang 21.1.3 (Fedora 21.1.3-1.fc44) on Fedora 44.