Machine-Level Programming V: Control: loops Comp 21000: Introduction to Computer Organization & Systems Systems book chapter 3* * Modified slides from the book “Computer Systems: a Programmer’s Perspective, 3rd ed.”, Randy Bryant & David O’Hallaron, 2015
Today Complete addressing mode, address computation (leal) Arithmetic operations x86-64 Control: Condition codes Conditional branches and moves Loops
“Do-While” Loop Example C Code Goto Version int pcount_do(unsigned x) { int result = 0; do { result += x & 0x1; x >>= 1; } while (x); return result; } int pcount_do(unsigned x) { int result = 0; loop: result += x & 0x1; x >>= 1; if (x) goto loop; return result; } Count number of 1’s in argument x (“popcount”) Use conditional branch to either continue looping or to exit loop
“Do-While” Loop Compilation Goto Version long pcount_goto (unsigned long x) { long result = 0; loop: result += x & 0x1; x >>= 1; if(x) goto loop; return result; } Register Use(s) %rdi Argument x %rax result movl $0, %eax # result = 0 .L2: # loop: movq %rdi, %rdx andl $1, %edx # t = x & 0x1 addq %rdx, %rax # result += t shrq %rdi # x >>= 1 jne .L2 # if (x) goto loop rep; ret
General “Do-While” Translation C Code Goto Version do Body while (Test); loop: Body if (Test) goto loop Body: Test returns integer = 0 interpreted as false ≠ 0 interpreted as true { Statement1; Statement2; … Statementn; }
General “While” Translation #1 “Jump-to-middle” translation Used with –O0 or -Og Goto Version goto test; loop: Body test: if (Test) goto loop; done: While version while (Test) Body
While Loop Example #1 C Code Jump to Middle Version long pcount_while (unsigned long x) { long result = 0; while (x) { result += x & 0x1; x >>= 1; } return result; long pcount_goto_jtm (unsigned long x) { long result = 0; goto test; loop: result += x & 0x1; x >>= 1; test: if(x) goto loop; return result; } Compare to do-while version of function Initial goto starts loop at test
General “While” Translation #2 While version “Do-while” conversion Used with –O1 while (Test) Body Goto Version Do-While Version if (!Test) goto done; loop: Body if (Test) goto loop; done: if (!Test) goto done; do Body while(Test); done:
While Loop Example #2 C Code Do-While Version long pcount_while (unsigned long x) { long result = 0; while (x) { result += x & 0x1; x >>= 1; } return result; long pcount_goto_dw (unsigned long x) { long result = 0; if (!x) goto done; loop: result += x & 0x1; x >>= 1; if(x) goto loop; done: return result; } Compare to do-while version of function Initial conditional guards entrance to loop
“For” Loop Example C Code Is this code equivalent to other versions? #define WSIZE 8*sizeof(int) int pcount_for(unsigned x) { int i; long result = 0; for (i = 0; i < WSIZE; i++) { unsigned bit = (x >> i) & 0x1; result += bit; } return result; Is this code equivalent to other versions?
for (Init; Test; Update ) “For” Loop Form Init i = 0 General Form Test for (Init; Test; Update ) Body i < WSIZE Update i++ for (i = 0; i < WSIZE; i++) { unsigned bit = (x >> i) & 0x1; result += bit; } Body { unsigned bit = (x >> i) & 0x1; result += bit;}
for (Init; Test; Update ) “For” Loop While Loop For Version for (Init; Test; Update ) Body While Version Init; while (Test ) { Body Update; }
For-While Conversion Init Test Update Body long pcount_for_while (unsigned long x) { size_t i; long result = 0; i = 0; while (i < WSIZE) unsigned bit = (x >> i) & 0x1; result += bit; i++; } return result; Init i = 0 Test i < WSIZE Update i++ Body { unsigned bit = (x >> i) & 0x1; result += bit; }
“For” Loop … Goto For Version goto Version While Version Init; if (!Test) goto done; loop: Body Update if (Test) goto loop; done: For Version goto Version for (Init; Test; Update ) Body While Version Do-While Version Init; while (Test ) { Body Update; } Init; if (!Test) goto done; do Body Update while(Test); done:
“For” Loop Do-While Conversion Goto Version C Code long pcount_for_goto_dw (unsigned long x) { size_t i; long result = 0; i = 0; if (!(i < WSIZE)) goto done; loop: { unsigned bit = (x >> i) & 0x1; result += bit; } i++; if (i < WSIZE) goto loop; done: return result; long pcount_for (unsigned long x) { size_t i; long result = 0; for (i = 0; i < WSIZE; i++) unsigned bit = (x >> i) & 0x1; result += bit; } return result; Init !Test Body Update Test Initial test can be optimized away; i always < WSIZE since WSIZE is a constant
“For” Loop Do-While Conversion Goto Version C Code long pcount_for_goto_dw (unsigned long x) { size_t i; long result = 0; i = 0; if (!(i < WSIZE)) goto done; loop: { unsigned bit = (x >> i) & 0x1; result += bit; } i++; if (i < WSIZE) goto loop; done: return result; long pcount_for (unsigned long x) { size_t i; long result = 0; for (i = 0; i < WSIZE; i++) unsigned bit = (x >> i) & 0x1; result += bit; } return result; Init !Test Body Update Test Initial test can be optimized away What if WSIZE < 0? Then compiler will recognize that the loop will never run and will eliminate code
“For” Loop Conversion Example Assembly Version _pcount_for: 0x040052d <+0>: push %rbp 0x040052e <+1>: mov %rsp,%rbp 0x0400531 <+4>: mov %rdi,-0x28(%rbp) 0x0400535 <+8>: movq $0x0,-0x8(%rbp) 0x040053d <+16>: movq $0x0,-0x10(%rbp) 0x0400545 <+24>: jmp 0x400569 <pcount_for+60> 0x0400547 <+26>: mov -0x10(%rbp),%rax 0x040054b <+30>: mov -0x28(%rbp),%rdx 0x040054f <+34>: mov %eax,%ecx 0x0400551 <+36>: shr %cl,%rdx 0x0400554 <+39>: mov %rdx,%rax 0x0400557 <+42>: and $0x1,%eax 0x040055a <+45>: mov %eax,-0x14(%rbp) 0x040055d <+48>: mov -0x14(%rbp),%eax 0x0400560 <+51>: add %rax,-0x8(%rbp) 0x0400564 <+55>: addq $0x1,-0x10(%rbp) 0x0400569 <+60>: cmpq $0x3f,-0x10(%rbp) 0x040056e <+65>: jbe 0x400547 <pcount_for+26> 0x0400570 <+67>: mov -0x8(%rbp),%rax 0x0400574 <+71>: pop %rbp 0x0400575 <+72>: retq Note that the compiler changed 64 to 63 and < to <=
Summary Today Next Time Complete addressing mode, address computation (leal) Arithmetic operations Control: Condition codes Conditional branches & conditional moves Loops Next Time Switch statements Stack Call / return Procedure call discipline