Skip to content

Instantly share code, notes, and snippets.

@wjlafrance
Last active August 29, 2015 14:03
Show Gist options
  • Save wjlafrance/c1f89e74ba436e26aa65 to your computer and use it in GitHub Desktop.
Save wjlafrance/c1f89e74ba436e26aa65 to your computer and use it in GitHub Desktop.
func max1(numbers: [Int]) -> Int {
var maximumSoFar: Int = 0
for i in numbers {
maximumSoFar = max(maximumSoFar, i)
}
return maximumSoFar
}
Compiled with -Ofast -emit-assembly:
Notice how it doesn't call max()! It optimized it to cmpq/cmovgeq!
__TF11maximumFast4max1FGSaSi_Si:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
pushq %rax
movq %rdi, %r15
callq _swift_retain
movq %rax, %r14
xorl %ebx, %ebx
testq %r15, %r15
je LBB1_3
leaq 32(%r15), %rax
movq $-1, %rcx ; loop starts at -1, because i is incremented at the beginning. weird.
xorl %ebx, %ebx
jmp LBB1_2
.align 4, 0x90
LBB1_4: ; loop start
movq (%rax), %rdx ; rdx = *rax
addq $8, %rax ; move rax pointer forward by sizeof(Int64)
cmpq %rbx, %rdx ; if (rdx >= rbx)
cmovgeq %rdx, %rbx ; rbx = rdx
LBB1_2:
incq %rcx ; ++i
cmpq 16(%r15), %rcx ; condition = (i == lastIndex)
jne LBB1_4 ; if (!condition) goto LBB1_4
LBB1_3:
movq %r14, %rdi
callq _swift_release
movq %r14, %rdi
callq _swift_release
movq %rbx, %rax
addq $8, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
@wjlafrance
Copy link
Author

Actually, the notes on 34 and 35 are not entirely accurate but I'm not sure how to better express what's going on in pseudo-C.

On line 34 rbx and rdx are compared. Currently rbx is holding the value of maximumSoFar and rdx is holding the next i from the array.

On line 35, the magical cmovge instruction is used, or "conditionally move if greater than or equal". The result of the cmp instruction is checked, and if it's greater than or equal, it performs the move.

This is an example of how the compiler writes better assembler than I do, based on it knowing instructions I don't. If I were to go on the fool's errand of writing this myself, the assembler would look like this:

  cmp rbx, rdx
  jge new_maximum_found
  jmp loop_bottom
new_maximum_found:
  mov rbx, rdx
loop_bottom:

So, trust your compiler. It's smarter than you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment