int bottom_up(int nItems, int size, int *weights, int *values, int **matrix,
              int **picks) {
  int i, j;
  for (i = 1; i <= nItems; i++) {
    for (j = 0; j <= size; j++) {
      if (weights[i - 1] <= j) {
        matrix[i][j] =
            (matrix[i - 1][j] >
                     values[i - 1] + matrix[i - 1][j - weights[i - 1]]
                 ? matrix[i - 1][j]
                 : values[i - 1] + matrix[i - 1][j - weights[i - 1]]);
        if (values[i - 1] + matrix[i - 1][j - weights[i - 1]] >
            matrix[i - 1][j])
          picks[i][j] = 1;
        else
          picks[i][j] = -1;
      } else {
        picks[i][j] = -1;
        matrix[i][j] = matrix[i - 1][j];
      }
    }
  }
  return matrix[nItems][size];
}


x86 assembly (clang, -O0):
<bottom_up>:
push   %rbp
mov    %rsp,%rbp
mov    %edi,-0x4(%rbp)
mov    %esi,-0x8(%rbp)
mov    %rdx,-0x10(%rbp)
mov    %rcx,-0x18(%rbp)
mov    %r8,-0x20(%rbp)
mov    %r9,-0x28(%rbp)
movl   $0x1,-0x2c(%rbp)
mov    -0x2c(%rbp),%eax
cmp    -0x4(%rbp),%eax
jg     1321 <bottom_up+0x221>
movl   $0x0,-0x30(%rbp)
mov    -0x30(%rbp),%eax
cmp    -0x8(%rbp),%eax
jg     130e <bottom_up+0x20e>
mov    -0x10(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
cmp    -0x30(%rbp),%eax
jg     12b9 <bottom_up+0x1b9>
mov    -0x20(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    (%rax,%rcx,4),%eax
mov    -0x18(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
mov    (%rcx,%rdx,4),%ecx
mov    -0x20(%rbp),%rdx
mov    -0x2c(%rbp),%esi
sub    $0x1,%esi
movslq %esi,%rsi
mov    (%rdx,%rsi,8),%rdx
mov    -0x30(%rbp),%esi
mov    -0x10(%rbp),%rdi
mov    -0x2c(%rbp),%r8d
sub    $0x1,%r8d
movslq %r8d,%r8
sub    (%rdi,%r8,4),%esi
movslq %esi,%rsi
add    (%rdx,%rsi,4),%ecx
cmp    %ecx,%eax
jle    11d6 <bottom_up+0xd6>
mov    -0x20(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    (%rax,%rcx,4),%eax
mov    %eax,-0x34(%rbp)
jmp    1213 <bottom_up+0x113>
mov    -0x18(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
mov    (%rcx,%rdx,8),%rcx
mov    -0x30(%rbp),%edx
mov    -0x10(%rbp),%rsi
mov    -0x2c(%rbp),%edi
sub    $0x1,%edi
movslq %edi,%rdi
sub    (%rsi,%rdi,4),%edx
movslq %edx,%rdx
add    (%rcx,%rdx,4),%eax
mov    %eax,-0x34(%rbp)
mov    -0x34(%rbp),%edx
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
mov    -0x18(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
mov    (%rcx,%rdx,8),%rcx
mov    -0x30(%rbp),%edx
mov    -0x10(%rbp),%rsi
mov    -0x2c(%rbp),%edi
sub    $0x1,%edi
movslq %edi,%rdi
sub    (%rsi,%rdi,4),%edx
movslq %edx,%rdx
add    (%rcx,%rdx,4),%eax
mov    -0x20(%rbp),%rcx
mov    -0x2c(%rbp),%edx
sub    $0x1,%edx
movslq %edx,%rdx
mov    (%rcx,%rdx,8),%rcx
movslq -0x30(%rbp),%rdx
cmp    (%rcx,%rdx,4),%eax
jle    129d <bottom_up+0x19d>
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movl   $0x1,(%rax,%rcx,4)
jmp    12b4 <bottom_up+0x1b4>
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movl   $0xffffffff,(%rax,%rcx,4)
jmp    12fb <bottom_up+0x1fb>
mov    -0x28(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
movl   $0xffffffff,(%rax,%rcx,4)
mov    -0x20(%rbp),%rax
mov    -0x2c(%rbp),%ecx
sub    $0x1,%ecx
movslq %ecx,%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    (%rax,%rcx,4),%edx
mov    -0x20(%rbp),%rax
movslq -0x2c(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x30(%rbp),%rcx
mov    %edx,(%rax,%rcx,4)
jmp    1300 <bottom_up+0x200>
mov    -0x30(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x30(%rbp)
jmp    1134 <bottom_up+0x34>
jmp    1313 <bottom_up+0x213>
mov    -0x2c(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x2c(%rbp)
jmp    1121 <bottom_up+0x21>
mov    -0x20(%rbp),%rax
movslq -0x4(%rbp),%rcx
mov    (%rax,%rcx,8),%rax
movslq -0x8(%rbp),%rcx
mov    (%rax,%rcx,4),%eax
pop    %rbp
ret

x86 assembly (clang, -O2):
<bottom_up>:
push   %rbp
push   %r15
push   %r14
push   %r12
push   %rbx
test   %edi,%edi
jle    11d9 <bottom_up+0xd9>
lea    0x1(%rsi),%r11d
lea    0x1(%rdi),%r10d
mov    $0x1,%r14d
jmp    112d <bottom_up+0x2d>
add    $0x1,%r14
cmp    %r10,%r14
je     11d9 <bottom_up+0xd9>
test   %esi,%esi
js     1120 <bottom_up+0x20>
xor    %ebx,%ebx
jmp    1164 <bottom_up+0x64>
cs nopw 0x0(%rax,%rax,1)
nop
mov    (%r9,%r14,8),%rax
movl   $0xffffffff,(%rax,%rbx,4)
mov    -0x8(%r8,%r14,8),%rax
mov    (%r8,%r14,8),%rbp
mov    (%rax,%rbx,4),%eax
mov    %eax,0x0(%rbp,%rbx,4)
add    $0x1,%rbx
cmp    %rbx,%r11
je     1120 <bottom_up+0x20>
movslq -0x4(%rdx,%r14,4),%r12
cmp    %r12,%rbx
jl     1140 <bottom_up+0x40>
mov    -0x8(%r8,%r14,8),%r15
shl    $0x2,%r12
mov    %r15,%rax
sub    %r12,%rax
mov    (%rax,%rbx,4),%eax
add    -0x4(%rcx,%r14,4),%eax
mov    (%r15,%rbx,4),%ebp
cmp    %eax,%ebp
cmovg  %ebp,%eax
mov    (%r8,%r14,8),%rbp
mov    %eax,0x0(%rbp,%rbx,4)
movslq -0x4(%rdx,%r14,4),%rax
shl    $0x2,%rax
mov    %r15,%rbp
sub    %rax,%rbp
mov    0x0(%rbp,%rbx,4),%ebp
add    -0x4(%rcx,%r14,4),%ebp
mov    (%r9,%r14,8),%rax
cmp    (%r15,%rbx,4),%ebp
jle    11d0 <bottom_up+0xd0>
movl   $0x1,(%rax,%rbx,4)
jmp    115b <bottom_up+0x5b>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax,%rax,1)
movl   $0xffffffff,(%rax,%rbx,4)
jmp    115b <bottom_up+0x5b>
movslq %edi,%rax
mov    (%r8,%rax,8),%rax
movslq %esi,%rcx
mov    (%rax,%rcx,4),%eax
pop    %rbx
pop    %r12
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
define i32 @bottom_up(i32 %0, i32 %1, i32* %2, i32* %3, i32** %4, i32** %5) {
%7 = alloca i32
%8 = alloca i32
%9 = alloca i32*
%10 = alloca i32*
%11 = alloca i32**
%12 = alloca i32**
%13 = alloca i32
%14 = alloca i32
store i32 %0, i32* %7
store i32 %1, i32* %8
store i32* %2, i32** %9
store i32* %3, i32** %10
store i32** %4, i32*** %11
store i32** %5, i32*** %12
store i32 1, i32* %13
br label %15
15: ; preds = %201, %6
%16 = load i32, i32* %13
%17 = load i32, i32* %7
%18 = icmp sle i32 %16, %17
br i1 %18, label %19, label %204
19: ; preds = %15
store i32 0, i32* %14
br label %20
20: ; preds = %197, %19
%21 = load i32, i32* %14
%22 = load i32, i32* %8
%23 = icmp sle i32 %21, %22
br i1 %23, label %24, label %200
24: ; preds = %20
%25 = load i32*, i32** %9
%26 = load i32, i32* %13
%27 = sub nsw i32 %26, 1
%28 = sext i32 %27 to i64
%29 = getelementptr inbounds i32, i32* %25, i64 %28
%30 = load i32, i32* %29
%31 = load i32, i32* %14
%32 = icmp sle i32 %30, %31
br i1 %32, label %33, label %169
33: ; preds = %24
%34 = load i32**, i32*** %11
%35 = load i32, i32* %13
%36 = sub nsw i32 %35, 1
%37 = sext i32 %36 to i64
%38 = getelementptr inbounds i32*, i32** %34, i64 %37
%39 = load i32*, i32** %38
%40 = load i32, i32* %14
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds i32, i32* %39, i64 %41
%43 = load i32, i32* %42
%44 = load i32*, i32** %10
%45 = load i32, i32* %13
%46 = sub nsw i32 %45, 1
%47 = sext i32 %46 to i64
%48 = getelementptr inbounds i32, i32* %44, i64 %47
%49 = load i32, i32* %48
%50 = load i32**, i32*** %11
%51 = load i32, i32* %13
%52 = sub nsw i32 %51, 1
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds i32*, i32** %50, i64 %53
%55 = load i32*, i32** %54
%56 = load i32, i32* %14
%57 = load i32*, i32** %9
%58 = load i32, i32* %13
%59 = sub nsw i32 %58, 1
%60 = sext i32 %59 to i64
%61 = getelementptr inbounds i32, i32* %57, i64 %60
%62 = load i32, i32* %61
%63 = sub nsw i32 %56, %62
%64 = sext i32 %63 to i64
%65 = getelementptr inbounds i32, i32* %55, i64 %64
%66 = load i32, i32* %65
%67 = add nsw i32 %49, %66
%68 = icmp sgt i32 %43, %67
br i1 %68, label %69, label %80
69: ; preds = %33
%70 = load i32**, i32*** %11
%71 = load i32, i32* %13
%72 = sub nsw i32 %71, 1
%73 = sext i32 %72 to i64
%74 = getelementptr inbounds i32*, i32** %70, i64 %73
%75 = load i32*, i32** %74
%76 = load i32, i32* %14
%77 = sext i32 %76 to i64
%78 = getelementptr inbounds i32, i32* %75, i64 %77
%79 = load i32, i32* %78
br label %105
80: ; preds = %33
%81 = load i32*, i32** %10
%82 = load i32, i32* %13
%83 = sub nsw i32 %82, 1
%84 = sext i32 %83 to i64
%85 = getelementptr inbounds i32, i32* %81, i64 %84
%86 = load i32, i32* %85
%87 = load i32**, i32*** %11
%88 = load i32, i32* %13
%89 = sub nsw i32 %88, 1
%90 = sext i32 %89 to i64
%91 = getelementptr inbounds i32*, i32** %87, i64 %90
%92 = load i32*, i32** %91
%93 = load i32, i32* %14
%94 = load i32*, i32** %9
%95 = load i32, i32* %13
%96 = sub nsw i32 %95, 1
%97 = sext i32 %96 to i64
%98 = getelementptr inbounds i32, i32* %94, i64 %97
%99 = load i32, i32* %98
%100 = sub nsw i32 %93, %99
%101 = sext i32 %100 to i64
%102 = getelementptr inbounds i32, i32* %92, i64 %101
%103 = load i32, i32* %102
%104 = add nsw i32 %86, %103
br label %105
105: ; preds = %80, %69
%106 = phi i32 [ %79, %69 ], [ %104, %80 ]
%107 = load i32**, i32*** %11
%108 = load i32, i32* %13
%109 = sext i32 %108 to i64
%110 = getelementptr inbounds i32*, i32** %107, i64 %109
%111 = load i32*, i32** %110
%112 = load i32, i32* %14
%113 = sext i32 %112 to i64
%114 = getelementptr inbounds i32, i32* %111, i64 %113
store i32 %106, i32* %114
%115 = load i32*, i32** %10
%116 = load i32, i32* %13
%117 = sub nsw i32 %116, 1
%118 = sext i32 %117 to i64
%119 = getelementptr inbounds i32, i32* %115, i64 %118
%120 = load i32, i32* %119
%121 = load i32**, i32*** %11
%122 = load i32, i32* %13
%123 = sub nsw i32 %122, 1
%124 = sext i32 %123 to i64
%125 = getelementptr inbounds i32*, i32** %121, i64 %124
%126 = load i32*, i32** %125
%127 = load i32, i32* %14
%128 = load i32*, i32** %9
%129 = load i32, i32* %13
%130 = sub nsw i32 %129, 1
%131 = sext i32 %130 to i64
%132 = getelementptr inbounds i32, i32* %128, i64 %131
%133 = load i32, i32* %132
%134 = sub nsw i32 %127, %133
%135 = sext i32 %134 to i64
%136 = getelementptr inbounds i32, i32* %126, i64 %135
%137 = load i32, i32* %136
%138 = add nsw i32 %120, %137
%139 = load i32**, i32*** %11
%140 = load i32, i32* %13
%141 = sub nsw i32 %140, 1
%142 = sext i32 %141 to i64
%143 = getelementptr inbounds i32*, i32** %139, i64 %142
%144 = load i32*, i32** %143
%145 = load i32, i32* %14
%146 = sext i32 %145 to i64
%147 = getelementptr inbounds i32, i32* %144, i64 %146
%148 = load i32, i32* %147
%149 = icmp sgt i32 %138, %148
br i1 %149, label %150, label %159
150: ; preds = %105
%151 = load i32**, i32*** %12
%152 = load i32, i32* %13
%153 = sext i32 %152 to i64
%154 = getelementptr inbounds i32*, i32** %151, i64 %153
%155 = load i32*, i32** %154
%156 = load i32, i32* %14
%157 = sext i32 %156 to i64
%158 = getelementptr inbounds i32, i32* %155, i64 %157
store i32 1, i32* %158
br label %168
159: ; preds = %105
%160 = load i32**, i32*** %12
%161 = load i32, i32* %13
%162 = sext i32 %161 to i64
%163 = getelementptr inbounds i32*, i32** %160, i64 %162
%164 = load i32*, i32** %163
%165 = load i32, i32* %14
%166 = sext i32 %165 to i64
%167 = getelementptr inbounds i32, i32* %164, i64 %166
store i32 -1, i32* %167
br label %168
168: ; preds = %159, %150
br label %196
169: ; preds = %24
%170 = load i32**, i32*** %12
%171 = load i32, i32* %13
%172 = sext i32 %171 to i64
%173 = getelementptr inbounds i32*, i32** %170, i64 %172
%174 = load i32*, i32** %173
%175 = load i32, i32* %14
%176 = sext i32 %175 to i64
%177 = getelementptr inbounds i32, i32* %174, i64 %176
store i32 -1, i32* %177
%178 = load i32**, i32*** %11
%179 = load i32, i32* %13
%180 = sub nsw i32 %179, 1
%181 = sext i32 %180 to i64
%182 = getelementptr inbounds i32*, i32** %178, i64 %181
%183 = load i32*, i32** %182
%184 = load i32, i32* %14
%185 = sext i32 %184 to i64
%186 = getelementptr inbounds i32, i32* %183, i64 %185
%187 = load i32, i32* %186
%188 = load i32**, i32*** %11
%189 = load i32, i32* %13
%190 = sext i32 %189 to i64
%191 = getelementptr inbounds i32*, i32** %188, i64 %190
%192 = load i32*, i32** %191
%193 = load i32, i32* %14
%194 = sext i32 %193 to i64
%195 = getelementptr inbounds i32, i32* %192, i64 %194
store i32 %187, i32* %195
br label %196
196: ; preds = %169, %168
br label %197
197: ; preds = %196
%198 = load i32, i32* %14
%199 = add nsw i32 %198, 1
store i32 %199, i32* %14
br label %20
200: ; preds = %20
br label %201
201: ; preds = %200
%202 = load i32, i32* %13
%203 = add nsw i32 %202, 1
store i32 %203, i32* %13
br label %15
204: ; preds = %15
%205 = load i32**, i32*** %11
%206 = load i32, i32* %7
%207 = sext i32 %206 to i64
%208 = getelementptr inbounds i32*, i32** %205, i64 %207
%209 = load i32*, i32** %208
%210 = load i32, i32* %8
%211 = sext i32 %210 to i64
%212 = getelementptr inbounds i32, i32* %209, i64 %211
%213 = load i32, i32* %212
ret i32 %213
}

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