Skip to content

[Docs][Intrisics] LLVM intrisics documentation use wrong llvm.memset.inline variants #163454

@niooss-ledger

Description

@niooss-ledger

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:

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:

  1. 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
  2. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions