void test_memcpy_warn(char *d, unsigned n) {
  for (unsigned i = n; i < 30; ++i)
    if (i > 10)
      __builtin_memcpy(d, d + 2, i);
}


x86 assembly (clang, -O0):
<test_memcpy_warn>:
push   %rbp
mov    %rsp,%rbp
sub    $0x10,%rsp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
mov    -0xc(%rbp),%eax
mov    %eax,-0x10(%rbp)
cmpl   $0x1e,-0x10(%rbp)
jae    1162 <test_memcpy_warn+0x52>
cmpl   $0xa,-0x10(%rbp)
jbe    114f <test_memcpy_warn+0x3f>
mov    -0x8(%rbp),%rdi
mov    -0x8(%rbp),%rsi
add    $0x2,%rsi
mov    -0x10(%rbp),%eax
mov    %eax,%edx
call   1030 <memcpy@plt>
jmp    1154 <test_memcpy_warn+0x44>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    1125 <test_memcpy_warn+0x15>
add    $0x10,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<test_memcpy_warn>:
push   %rbp
push   %r15
push   %r14
push   %rbx
push   %rax
cmp    $0x1d,%esi
ja     1149 <test_memcpy_warn+0x39>
mov    %esi,%ebp
mov    %rdi,%r15
lea    0x2(%rdi),%r14
mov    %esi,%ebx
test   $0x1,%bpl
je     1144 <test_memcpy_warn+0x34>
cmp    $0xb,%ebp
jb     1140 <test_memcpy_warn+0x30>
mov    %r15,%rdi
mov    %r14,%rsi
mov    %rbx,%rdx
call   1030 <memcpy@plt>
add    $0x1,%rbx
cmp    $0x1d,%ebp
jne    1169 <test_memcpy_warn+0x59>
add    $0x8,%rsp
pop    %rbx
pop    %r14
pop    %r15
pop    %rbp
ret
cs nopw 0x0(%rax,%rax,1)
xchg   %ax,%ax
add    $0x2,%rbx
cmp    $0x1e,%ebx
je     1149 <test_memcpy_warn+0x39>
cmp    $0xb,%rbx
jb     117d <test_memcpy_warn+0x6d>
mov    %r15,%rdi
mov    %r14,%rsi
mov    %rbx,%rdx
call   1030 <memcpy@plt>
cmp    $0xa,%rbx
jb     1160 <test_memcpy_warn+0x50>
lea    0x1(%rbx),%rdx
mov    %r15,%rdi
mov    %r14,%rsi
call   1030 <memcpy@plt>
jmp    1160 <test_memcpy_warn+0x50>

LLVM IR (-O0):
define void @test_memcpy_warn(i8* %0, i32 %1) {
%3 = alloca i8*
%4 = alloca i32
%5 = alloca i32
store i8* %0, i8** %3
store i32 %1, i32* %4
%6 = load i32, i32* %4
store i32 %6, i32* %5
br label %7
7: ; preds = %20, %2
%8 = load i32, i32* %5
%9 = icmp ult i32 %8, 30
br i1 %9, label %10, label %23
10: ; preds = %7
%11 = load i32, i32* %5
%12 = icmp ugt i32 %11, 10
br i1 %12, label %13, label %19
13: ; preds = %10
%14 = load i8*, i8** %3
%15 = load i8*, i8** %3
%16 = getelementptr inbounds i8, i8* %15, i64 2
%17 = load i32, i32* %5
%18 = zext i32 %17 to i64
br label %19
19: ; preds = %13, %10
br label %20
20: ; preds = %19
%21 = load i32, i32* %5
%22 = add i32 %21, 1
store i32 %22, i32* %5
br label %7
23: ; preds = %7
ret void
}

LLVM IR (-O2):
define void @test_memcpy_warn(i8* nocapture %0, i32 %1) {
%3 = icmp ult i32 %1, 30
br i1 %3, label %4, label %17
4: ; preds = %2
%5 = getelementptr inbounds i8, i8* %0, i64 2
%6 = zext i32 %1 to i64
%7 = and i32 %1, 1
%8 = icmp eq i32 %7, 0
br i1 %8, label %14, label %9
9: ; preds = %4
%10 = icmp ugt i32 %1, 10
br i1 %10, label %11, label %12
11: ; preds = %9
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 %5, i64 %6, i1 false)
br label %12
12: ; preds = %11, %9
%13 = add nuw nsw i64 %6, 1
br label %14
14: ; preds = %12, %4
%15 = phi i64 [ %6, %4 ], [ %13, %12 ]
%16 = icmp eq i32 %1, 29
br i1 %16, label %17, label %18
17: ; preds = %14, %26, %2
ret void
18: ; preds = %14, %26
%19 = phi i64 [ %27, %26 ], [ %15, %14 ]
%20 = icmp ugt i64 %19, 10
br i1 %20, label %21, label %22
21: ; preds = %18
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 %5, i64 %19, i1 false)
br label %22
22: ; preds = %18, %21
%23 = icmp ugt i64 %19, 9
br i1 %23, label %24, label %26
24: ; preds = %22
%25 = add nuw nsw i64 %19, 1
tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %0, i8* align 1 %5, i64 %25, i1 false)
br label %26
26: ; preds = %24, %22
%27 = add nuw nsw i64 %19, 2
%28 = trunc i64 %27 to i32
%29 = icmp eq i32 %28, 30
br i1 %29, label %17, label %18
}