#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
double **malloc(int);
double **allocate2d(int x, int y) {
  int i;
  double **array = malloc(sizeof(double *) * x + sizeof(double) * x * y);
  for (i = 0; i < x; i++) {
    array[i] = ((double *)(array + x)) + y * i;
  }
  return array;
}


x86 assembly (clang, -O0):
<allocate2d>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
movslq -0x4(%rbp),%rax
shl    $0x3,%rax
movslq -0x4(%rbp),%rcx
shl    $0x3,%rcx
movslq -0x8(%rbp),%rdx
imul   %rdx,%rcx
add    %rcx,%rax
mov    %eax,%edi
call   1030 <malloc@plt>
mov    %rax,-0x18(%rbp)
movl   $0x0,-0xc(%rbp)
mov    -0xc(%rbp),%eax
cmp    -0x4(%rbp),%eax
jge    1190 <allocate2d+0x80>
mov    -0x18(%rbp),%rdx
movslq -0x4(%rbp),%rax
shl    $0x3,%rax
add    %rax,%rdx
mov    -0x8(%rbp),%eax
imul   -0xc(%rbp),%eax
cltq
shl    $0x3,%rax
add    %rax,%rdx
mov    -0x18(%rbp),%rax
movslq -0xc(%rbp),%rcx
mov    %rdx,(%rax,%rcx,8)
mov    -0xc(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0xc(%rbp)
jmp    114b <allocate2d+0x3b>
mov    -0x18(%rbp),%rax
add    $0x20,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<allocate2d>:
push   %rbp
push   %rbx
push   %rax
mov    %esi,%ebp
mov    %edi,%ebx
lea    0x0(,%rbx,8),%eax
imul   %esi,%eax
lea    (%rax,%rbx,8),%edi
call   1030 <malloc@plt>
test   %ebx,%ebx
jle    11f0 <allocate2d+0xe0>
movslq %ebx,%r8
movslq %ebp,%r9
mov    %ebx,%edi
lea    -0x1(%rdi),%rcx
mov    %edi,%r10d
and    $0x7,%r10d
cmp    $0x7,%rcx
jae    114e <allocate2d+0x3e>
xor    %ebp,%ebp
jmp    11bc <allocate2d+0xac>
and    $0xfffffff8,%edi
lea    0x0(,%r8,8),%rbx
mov    %r9,%rcx
shl    $0x6,%rcx
lea    0x0(,%r9,8),%rsi
xor    %ebp,%ebp
nopw   0x0(%rax,%rax,1)
lea    (%rax,%rbx,1),%rdx
mov    %rdx,(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x8(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x10(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x18(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x20(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x28(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x30(%rax,%rbp,8)
add    %rsi,%rdx
mov    %rdx,0x38(%rax,%rbp,8)
add    $0x8,%rbp
add    %rcx,%rbx
cmp    %rbp,%rdi
jne    1170 <allocate2d+0x60>
test   %r10,%r10
je     11f0 <allocate2d+0xe0>
lea    (%rax,%rbp,8),%rcx
imul   %r9,%rbp
add    %r8,%rbp
lea    (%rax,%rbp,8),%rsi
shl    $0x3,%r9
xor    %edi,%edi
cs nopw 0x0(%rax,%rax,1)
mov    %rsi,(%rcx,%rdi,8)
add    $0x1,%rdi
add    %r9,%rsi
cmp    %rdi,%r10
jne    11e0 <allocate2d+0xd0>
add    $0x8,%rsp
pop    %rbx
pop    %rbp
ret

LLVM IR (-O0):
define double** @allocate2d(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
%6 = alloca double**
store i32 %0, i32* %3
store i32 %1, i32* %4
%7 = load i32, i32* %3
%8 = sext i32 %7 to i64
%9 = mul i64 8, %8
%10 = load i32, i32* %3
%11 = sext i32 %10 to i64
%12 = mul i64 8, %11
%13 = load i32, i32* %4
%14 = sext i32 %13 to i64
%15 = mul i64 %12, %14
%16 = add i64 %9, %15
%17 = trunc i64 %16 to i32
%18 = call double** @malloc(i32 %17)
store double** %18, double*** %6
store i32 0, i32* %5
br label %19
19: ; preds = %38, %2
%20 = load i32, i32* %5
%21 = load i32, i32* %3
%22 = icmp slt i32 %20, %21
br i1 %22, label %23, label %41
23: ; preds = %19
%24 = load double**, double*** %6
%25 = load i32, i32* %3
%26 = sext i32 %25 to i64
%27 = getelementptr inbounds double*, double** %24, i64 %26
%28 = bitcast double** %27 to double*
%29 = load i32, i32* %4
%30 = load i32, i32* %5
%31 = mul nsw i32 %29, %30
%32 = sext i32 %31 to i64
%33 = getelementptr inbounds double, double* %28, i64 %32
%34 = load double**, double*** %6
%35 = load i32, i32* %5
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds double*, double** %34, i64 %36
store double* %33, double** %37
br label %38
38: ; preds = %23
%39 = load i32, i32* %5
%40 = add nsw i32 %39, 1
store i32 %40, i32* %5
br label %19
41: ; preds = %19
%42 = load double**, double*** %6
ret double** %42
}

LLVM IR (-O2):
define double** @allocate2d(i32 %0, i32 %1) {
%3 = sext i32 %0 to i64
%4 = shl nsw i64 %3, 3
%5 = sext i32 %1 to i64
%6 = mul i64 %4, %5
%7 = add i64 %6, %4
%8 = trunc i64 %7 to i32
%9 = tail call double** @malloc(i32 %8)
%10 = icmp sgt i32 %0, 0
br i1 %10, label %11, label %77
11: ; preds = %2
%12 = getelementptr inbounds double*, double** %9, i64 %3
%13 = zext i32 %0 to i64
%14 = add nsw i64 %13, -1
%15 = and i64 %13, 7
%16 = icmp ult i64 %14, 7
br i1 %16, label %64, label %17
17: ; preds = %11
%18 = and i64 %13, 4294967288
br label %19
19: ; preds = %19, %17
%20 = phi i64 [ 0, %17 ], [ %61, %19 ]
%21 = phi i64 [ 0, %17 ], [ %62, %19 ]
%22 = mul nsw i64 %20, %5
%23 = getelementptr inbounds double*, double** %12, i64 %22
%24 = getelementptr inbounds double*, double** %9, i64 %20
%25 = bitcast double** %24 to double***
store double** %23, double*** %25
%26 = or i64 %20, 1
%27 = mul nsw i64 %26, %5
%28 = getelementptr inbounds double*, double** %12, i64 %27
%29 = getelementptr inbounds double*, double** %9, i64 %26
%30 = bitcast double** %29 to double***
store double** %28, double*** %30
%31 = or i64 %20, 2
%32 = mul nsw i64 %31, %5
%33 = getelementptr inbounds double*, double** %12, i64 %32
%34 = getelementptr inbounds double*, double** %9, i64 %31
%35 = bitcast double** %34 to double***
store double** %33, double*** %35
%36 = or i64 %20, 3
%37 = mul nsw i64 %36, %5
%38 = getelementptr inbounds double*, double** %12, i64 %37
%39 = getelementptr inbounds double*, double** %9, i64 %36
%40 = bitcast double** %39 to double***
store double** %38, double*** %40
%41 = or i64 %20, 4
%42 = mul nsw i64 %41, %5
%43 = getelementptr inbounds double*, double** %12, i64 %42
%44 = getelementptr inbounds double*, double** %9, i64 %41
%45 = bitcast double** %44 to double***
store double** %43, double*** %45
%46 = or i64 %20, 5
%47 = mul nsw i64 %46, %5
%48 = getelementptr inbounds double*, double** %12, i64 %47
%49 = getelementptr inbounds double*, double** %9, i64 %46
%50 = bitcast double** %49 to double***
store double** %48, double*** %50
%51 = or i64 %20, 6
%52 = mul nsw i64 %51, %5
%53 = getelementptr inbounds double*, double** %12, i64 %52
%54 = getelementptr inbounds double*, double** %9, i64 %51
%55 = bitcast double** %54 to double***
store double** %53, double*** %55
%56 = or i64 %20, 7
%57 = mul nsw i64 %56, %5
%58 = getelementptr inbounds double*, double** %12, i64 %57
%59 = getelementptr inbounds double*, double** %9, i64 %56
%60 = bitcast double** %59 to double***
store double** %58, double*** %60
%61 = add nuw nsw i64 %20, 8
%62 = add i64 %21, 8
%63 = icmp eq i64 %62, %18
br i1 %63, label %64, label %19
64: ; preds = %19, %11
%65 = phi i64 [ 0, %11 ], [ %61, %19 ]
%66 = icmp eq i64 %15, 0
br i1 %66, label %77, label %67
67: ; preds = %64, %67
%68 = phi i64 [ %74, %67 ], [ %65, %64 ]
%69 = phi i64 [ %75, %67 ], [ 0, %64 ]
%70 = mul nsw i64 %68, %5
%71 = getelementptr inbounds double*, double** %12, i64 %70
%72 = getelementptr inbounds double*, double** %9, i64 %68
%73 = bitcast double** %72 to double***
store double** %71, double*** %73
%74 = add nuw nsw i64 %68, 1
%75 = add i64 %69, 1
%76 = icmp eq i64 %75, %15
br i1 %76, label %77, label %67
77: ; preds = %64, %67, %2
ret double** %9
}