void foo(int *p, double *x, int n) {
  int i;
  for (i = 0; i < n; ++i)
    *(x + *p * i) = 0.0;
}


x86 assembly (clang, -O0):
<foo>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %rsi,-0x10(%rbp)
mov    %edx,-0x14(%rbp)
movl   $0x0,-0x18(%rbp)
mov    -0x18(%rbp),%eax
cmp    -0x14(%rbp),%eax
jge    1149 <foo+0x49>
mov    -0x10(%rbp),%rax
mov    -0x8(%rbp),%rcx
mov    (%rcx),%ecx
imul   -0x18(%rbp),%ecx
movslq %ecx,%rcx
xorps  %xmm0,%xmm0
movsd  %xmm0,(%rax,%rcx,8)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1116 <foo+0x16>
pop    %rbp
ret

x86 assembly (clang, -O2):
<foo>:
push   %r15
push   %r14
push   %rbx
test   %edx,%edx
jle    1299 <foo+0x199>
mov    (%rdi),%eax
movslq %eax,%r8
mov    %edx,%r11d
xor    %r9d,%r9d
cmp    $0x4,%edx
jb     11e9 <foo+0xe9>
cmp    $0x1,%eax
jne    11e9 <foo+0xe9>
mov    %r11d,%r9d
and    $0xfffffffc,%r9d
lea    -0x4(%r9),%rax
mov    %rax,%r15
shr    $0x2,%r15
add    $0x1,%r15
mov    %r15d,%r14d
and    $0x3,%r14d
cmp    $0xc,%rax
jae    1151 <foo+0x51>
xor    %ecx,%ecx
jmp    11a7 <foo+0xa7>
and    $0xfffffffffffffffc,%r15
mov    %r8,%r10
shl    $0x7,%r10
mov    %r8,%rax
shl    $0x5,%rax
xor    %ecx,%ecx
xorps  %xmm0,%xmm0
mov    %rsi,%rbx
nopl   0x0(%rax,%rax,1)
movups %xmm0,(%rbx)
movups %xmm0,0x10(%rbx)
lea    (%rbx,%rax,1),%rdi
movups %xmm0,(%rbx,%rax,1)
movups %xmm0,0x10(%rbx,%rax,1)
lea    (%rdi,%rax,1),%rdx
movups %xmm0,(%rax,%rdi,1)
movups %xmm0,0x10(%rax,%rdi,1)
movups %xmm0,(%rax,%rdx,1)
movups %xmm0,0x10(%rax,%rdx,1)
add    $0x10,%rcx
add    %r10,%rbx
add    $0xfffffffffffffffc,%r15
jne    1170 <foo+0x70>
test   %r14,%r14
je     11e0 <foo+0xe0>
imul   %r8,%rcx
lea    (%rsi,%rcx,8),%rax
add    $0x10,%rax
mov    %r8,%rcx
shl    $0x5,%rcx
xorps  %xmm0,%xmm0
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
movups %xmm0,-0x10(%rax)
movups %xmm0,(%rax)
add    %rcx,%rax
add    $0xffffffffffffffff,%r14
jne    11d0 <foo+0xd0>
cmp    %r11,%r9
je     1299 <foo+0x199>
mov    %r9,%rcx
not    %rcx
add    %r11,%rcx
mov    %r11,%rax
and    $0x3,%rax
je     1236 <foo+0x136>
mov    %r9,%rdx
imul   %r8,%rdx
lea    (%rsi,%rdx,8),%rdx
lea    0x0(,%r8,8),%rdi
neg    %rax
xor    %ebx,%ebx
cs nopw 0x0(%rax,%rax,1)
nopl   (%rax)
movq   $0x0,(%rdx)
add    $0xffffffffffffffff,%rbx
add    %rdi,%rdx
cmp    %rbx,%rax
jne    1220 <foo+0x120>
sub    %rbx,%r9
cmp    $0x3,%rcx
jb     1299 <foo+0x199>
sub    %r9,%r11
lea    0x3(%r9),%rax
imul   %r8,%rax
mov    %r8,%rcx
shl    $0x5,%rcx
lea    0x2(%r9),%rdx
imul   %r8,%rdx
mov    %r9,%rdi
imul   %r8,%rdi
add    $0x1,%r9
imul   %r8,%r9
cs nopw 0x0(%rax,%rax,1)
nop
movq   $0x0,(%rsi,%rdi,8)
movq   $0x0,(%rsi,%r9,8)
movq   $0x0,(%rsi,%rdx,8)
movq   $0x0,(%rsi,%rax,8)
add    %rcx,%rsi
add    $0xfffffffffffffffc,%r11
jne    1270 <foo+0x170>
pop    %rbx
pop    %r14
pop    %r15
ret

LLVM IR (-O0):
define void @foo(i32* %0, double* %1, i32 %2) {
%4 = alloca i32*
%5 = alloca double*
%6 = alloca i32
%7 = alloca i32
store i32* %0, i32** %4
store double* %1, double** %5
store i32 %2, i32* %6
store i32 0, i32* %7
br label %8
8: ; preds = %20, %3
%9 = load i32, i32* %7
%10 = load i32, i32* %6
%11 = icmp slt i32 %9, %10
br i1 %11, label %12, label %23
12: ; preds = %8
%13 = load double*, double** %5
%14 = load i32*, i32** %4
%15 = load i32, i32* %14
%16 = load i32, i32* %7
%17 = mul nsw i32 %15, %16
%18 = sext i32 %17 to i64
%19 = getelementptr inbounds double, double* %13, i64 %18
store double 0.000000e+00, double* %19
br label %20
20: ; preds = %12
%21 = load i32, i32* %7
%22 = add nsw i32 %21, 1
store i32 %22, i32* %7
br label %8
23: ; preds = %8
ret void
}

LLVM IR (-O2):
define void @foo(i32* nocapture %0, double* nocapture writeonly %1, i32 %2) {
%4 = icmp sgt i32 %2, 0
br i1 %4, label %5, label %98
5: ; preds = %3
%6 = load i32, i32* %0
%7 = sext i32 %6 to i64
%8 = zext i32 %2 to i64
%9 = icmp ugt i32 %2, 3
%10 = icmp eq i32 %6, 1
%11 = select i1 %9, i1 %10, i1 false
br i1 %11, label %12, label %66
12: ; preds = %5
%13 = and i64 %8, 4294967292
%14 = add nsw i64 %13, -4
%15 = lshr exact i64 %14, 2
%16 = add nuw nsw i64 %15, 1
%17 = and i64 %16, 3
%18 = icmp ult i64 %14, 12
br i1 %18, label %50, label %19
19: ; preds = %12
%20 = and i64 %16, 9223372036854775804
br label %21
21: ; preds = %21, %19
%22 = phi i64 [ 0, %19 ], [ %47, %21 ]
%23 = phi i64 [ 0, %19 ], [ %48, %21 ]
%24 = mul nsw i64 %22, %7
%25 = getelementptr inbounds double, double* %1, i64 %24
%26 = bitcast double* %25 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %26
%27 = getelementptr inbounds double, double* %25, i64 2
%28 = bitcast double* %27 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %28
%29 = or i64 %22, 4
%30 = mul nsw i64 %29, %7
%31 = getelementptr inbounds double, double* %1, i64 %30
%32 = bitcast double* %31 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %32
%33 = getelementptr inbounds double, double* %31, i64 2
%34 = bitcast double* %33 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %34
%35 = or i64 %22, 8
%36 = mul nsw i64 %35, %7
%37 = getelementptr inbounds double, double* %1, i64 %36
%38 = bitcast double* %37 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %38
%39 = getelementptr inbounds double, double* %37, i64 2
%40 = bitcast double* %39 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %40
%41 = or i64 %22, 12
%42 = mul nsw i64 %41, %7
%43 = getelementptr inbounds double, double* %1, i64 %42
%44 = bitcast double* %43 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %44
%45 = getelementptr inbounds double, double* %43, i64 2
%46 = bitcast double* %45 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %46
%47 = add nuw i64 %22, 16
%48 = add nuw i64 %23, 4
%49 = icmp eq i64 %48, %20
br i1 %49, label %50, label %21
50: ; preds = %21, %12
%51 = phi i64 [ 0, %12 ], [ %47, %21 ]
%52 = icmp eq i64 %17, 0
br i1 %52, label %64, label %53
53: ; preds = %50, %53
%54 = phi i64 [ %61, %53 ], [ %51, %50 ]
%55 = phi i64 [ %62, %53 ], [ 0, %50 ]
%56 = mul nsw i64 %54, %7
%57 = getelementptr inbounds double, double* %1, i64 %56
%58 = bitcast double* %57 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %58
%59 = getelementptr inbounds double, double* %57, i64 2
%60 = bitcast double* %59 to <2 x double>*
store <2 x double> zeroinitializer, <2 x double>* %60
%61 = add nuw i64 %54, 4
%62 = add i64 %55, 1
%63 = icmp eq i64 %62, %17
br i1 %63, label %64, label %53
64: ; preds = %53, %50
%65 = icmp eq i64 %13, %8
br i1 %65, label %98, label %66
66: ; preds = %5, %64
%67 = phi i64 [ 0, %5 ], [ %13, %64 ]
%68 = xor i64 %67, -1
%69 = add nsw i64 %68, %8
%70 = and i64 %8, 3
%71 = icmp eq i64 %70, 0
br i1 %71, label %80, label %72
72: ; preds = %66, %72
%73 = phi i64 [ %77, %72 ], [ %67, %66 ]
%74 = phi i64 [ %78, %72 ], [ 0, %66 ]
%75 = mul nsw i64 %73, %7
%76 = getelementptr inbounds double, double* %1, i64 %75
store double 0.000000e+00, double* %76
%77 = add nuw nsw i64 %73, 1
%78 = add i64 %74, 1
%79 = icmp eq i64 %78, %70
br i1 %79, label %80, label %72
80: ; preds = %72, %66
%81 = phi i64 [ %67, %66 ], [ %77, %72 ]
%82 = icmp ult i64 %69, 3
br i1 %82, label %98, label %83
83: ; preds = %80, %83
%84 = phi i64 [ %96, %83 ], [ %81, %80 ]
%85 = mul nsw i64 %84, %7
%86 = getelementptr inbounds double, double* %1, i64 %85
store double 0.000000e+00, double* %86
%87 = add nuw nsw i64 %84, 1
%88 = mul nsw i64 %87, %7
%89 = getelementptr inbounds double, double* %1, i64 %88
store double 0.000000e+00, double* %89
%90 = add nuw nsw i64 %84, 2
%91 = mul nsw i64 %90, %7
%92 = getelementptr inbounds double, double* %1, i64 %91
store double 0.000000e+00, double* %92
%93 = add nuw nsw i64 %84, 3
%94 = mul nsw i64 %93, %7
%95 = getelementptr inbounds double, double* %1, i64 %94
store double 0.000000e+00, double* %95
%96 = add nuw nsw i64 %84, 4
%97 = icmp eq i64 %96, %8
br i1 %97, label %98, label %83
98: ; preds = %80, %83, %64, %3
ret void
}