void brick_shift_up(char brick[4][4], int count) {
  for (int n = 0; n < count; n++) {
    for (int x = 0; x < 4; x++) {
      for (int y = 0; y < 3; y++) {
        char tmp = brick[y][x];
        brick[y][x] = brick[y + 1][x];
        brick[y + 1][x] = tmp;
      }
    }
  }
}


x86 assembly (clang, -O0):
<brick_shift_up>:
push   %rbp
mov    %rsp,%rbp
mov    %rdi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
movl   $0x0,-0x10(%rbp)
mov    -0x10(%rbp),%eax
cmp    -0xc(%rbp),%eax
jge    11dc <brick_shift_up+0xdc>
movl   $0x0,-0x14(%rbp)
cmpl   $0x4,-0x14(%rbp)
jge    11c9 <brick_shift_up+0xc9>
movl   $0x0,-0x18(%rbp)
cmpl   $0x3,-0x18(%rbp)
jge    11b6 <brick_shift_up+0xb6>
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
movslq -0x14(%rbp),%rcx
mov    (%rax,%rcx,1),%al
mov    %al,-0x19(%rbp)
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
shl    $0x2,%rcx
add    %rcx,%rax
movslq -0x14(%rbp),%rcx
mov    (%rax,%rcx,1),%dl
mov    -0x8(%rbp),%rax
movslq -0x18(%rbp),%rcx
shl    $0x2,%rcx
add    %rcx,%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x19(%rbp),%dl
mov    -0x8(%rbp),%rax
mov    -0x18(%rbp),%ecx
add    $0x1,%ecx
movslq %ecx,%rcx
shl    $0x2,%rcx
add    %rcx,%rax
movslq -0x14(%rbp),%rcx
mov    %dl,(%rax,%rcx,1)
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1136 <brick_shift_up+0x36>
jmp    11bb <brick_shift_up+0xbb>
mov    -0x14(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x14(%rbp)
jmp    1125 <brick_shift_up+0x25>
jmp    11ce <brick_shift_up+0xce>
mov    -0x10(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x10(%rbp)
jmp    1112 <brick_shift_up+0x12>
pop    %rbp
ret

x86 assembly (clang, -O2):
<brick_shift_up>:
test   %esi,%esi
jle    1146 <brick_shift_up+0x46>
movdqu (%rdi),%xmm0
cmp    $0x1,%esi
jne    1115 <brick_shift_up+0x15>
test   $0x1,%sil
jne    1139 <brick_shift_up+0x39>
jmp    113d <brick_shift_up+0x3d>
mov    %esi,%eax
and    $0xfffffffe,%eax
nopw   0x0(%rax,%rax,1)
movdqa %xmm0,%xmm1
pshufd $0x4e,%xmm0,%xmm0
add    $0xfffffffe,%eax
jne    1120 <brick_shift_up+0x20>
pshufd $0x39,%xmm1,%xmm1
test   $0x1,%sil
je     113d <brick_shift_up+0x3d>
movdqa %xmm0,%xmm1
pshufd $0x39,%xmm1,%xmm0
movdqu %xmm0,(%rdi)
ret

LLVM IR (-O0):
define void @brick_shift_up([4 x i8]* %0, i32 %1) {
%3 = alloca [4 x i8]*
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i8
store [4 x i8]* %0, [4 x i8]** %3
store i32 %1, i32* %4
store i32 0, i32* %5
br label %9
9: ; preds = %63, %2
%10 = load i32, i32* %5
%11 = load i32, i32* %4
%12 = icmp slt i32 %10, %11
br i1 %12, label %13, label %66
13: ; preds = %9
store i32 0, i32* %6
br label %14
14: ; preds = %59, %13
%15 = load i32, i32* %6
%16 = icmp slt i32 %15, 4
br i1 %16, label %17, label %62
17: ; preds = %14
store i32 0, i32* %7
br label %18
18: ; preds = %55, %17
%19 = load i32, i32* %7
%20 = icmp slt i32 %19, 3
br i1 %20, label %21, label %58
21: ; preds = %18
%22 = load [4 x i8]*, [4 x i8]** %3
%23 = load i32, i32* %7
%24 = sext i32 %23 to i64
%25 = getelementptr inbounds [4 x i8], [4 x i8]* %22, i64 %24
%26 = load i32, i32* %6
%27 = sext i32 %26 to i64
%28 = getelementptr inbounds [4 x i8], [4 x i8]* %25, i64 0, i64 %27
%29 = load i8, i8* %28
store i8 %29, i8* %8
%30 = load [4 x i8]*, [4 x i8]** %3
%31 = load i32, i32* %7
%32 = add nsw i32 %31, 1
%33 = sext i32 %32 to i64
%34 = getelementptr inbounds [4 x i8], [4 x i8]* %30, i64 %33
%35 = load i32, i32* %6
%36 = sext i32 %35 to i64
%37 = getelementptr inbounds [4 x i8], [4 x i8]* %34, i64 0, i64 %36
%38 = load i8, i8* %37
%39 = load [4 x i8]*, [4 x i8]** %3
%40 = load i32, i32* %7
%41 = sext i32 %40 to i64
%42 = getelementptr inbounds [4 x i8], [4 x i8]* %39, i64 %41
%43 = load i32, i32* %6
%44 = sext i32 %43 to i64
%45 = getelementptr inbounds [4 x i8], [4 x i8]* %42, i64 0, i64 %44
store i8 %38, i8* %45
%46 = load i8, i8* %8
%47 = load [4 x i8]*, [4 x i8]** %3
%48 = load i32, i32* %7
%49 = add nsw i32 %48, 1
%50 = sext i32 %49 to i64
%51 = getelementptr inbounds [4 x i8], [4 x i8]* %47, i64 %50
%52 = load i32, i32* %6
%53 = sext i32 %52 to i64
%54 = getelementptr inbounds [4 x i8], [4 x i8]* %51, i64 0, i64 %53
store i8 %46, i8* %54
br label %55
55: ; preds = %21
%56 = load i32, i32* %7
%57 = add nsw i32 %56, 1
store i32 %57, i32* %7
br label %18
58: ; preds = %18
br label %59
59: ; preds = %58
%60 = load i32, i32* %6
%61 = add nsw i32 %60, 1
store i32 %61, i32* %6
br label %14
62: ; preds = %14
br label %63
63: ; preds = %62
%64 = load i32, i32* %5
%65 = add nsw i32 %64, 1
store i32 %65, i32* %5
br label %9
66: ; preds = %9
ret void
}

LLVM IR (-O2):
define void @brick_shift_up([4 x i8]* nocapture %0, i32 %1) {
%3 = icmp sgt i32 %1, 0
br i1 %3, label %4, label %25
4: ; preds = %2
%5 = bitcast [4 x i8]* %0 to <16 x i8>*
%6 = load <16 x i8>, <16 x i8>* %5
%7 = and i32 %1, 1
%8 = icmp eq i32 %1, 1
br i1 %8, label %18, label %9
9: ; preds = %4
%10 = and i32 %1, -2
br label %11
11: ; preds = %11, %9
%12 = phi <16 x i8> [ %6, %9 ], [ %15, %11 ]
%13 = phi i32 [ 0, %9 ], [ %16, %11 ]
%14 = shufflevector <16 x i8> %12, <16 x i8> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3>
%15 = shufflevector <16 x i8> %14, <16 x i8> undef, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3>
%16 = add i32 %13, 2
%17 = icmp eq i32 %16, %10
br i1 %17, label %18, label %11
18: ; preds = %11, %4
%19 = phi <16 x i8> [ undef, %4 ], [ %14, %11 ]
%20 = phi <16 x i8> [ %6, %4 ], [ %15, %11 ]
%21 = icmp eq i32 %7, 0
%22 = select i1 %21, <16 x i8> %19, <16 x i8> %20
%23 = shufflevector <16 x i8> %22, <16 x i8> poison, <16 x i32> <i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 0, i32 1, i32 2, i32 3>
%24 = bitcast [4 x i8]* %0 to <16 x i8>*
store <16 x i8> %23, <16 x i8>* %24
br label %25
25: ; preds = %18, %2
ret void
}