MachineLevel Programming 5 Structured Data Topics n Arrays

  • Slides: 25
Download presentation
Machine-Level Programming 5 Structured Data Topics n Arrays

Machine-Level Programming 5 Structured Data Topics n Arrays

Basic Data Types Integral n Stored & operated on in general registers n Signed

Basic Data Types Integral n Stored & operated on in general registers n Signed vs. unsigned depends on instructions used Intel GAS byte b word w double word Bytes 1 2 l C [unsigned] char [unsigned] short 4 [unsigned] int Floating Point n Stored & operated on in floating point registers Intel Single Double Extended – 2 – GAS s l t Bytes C 4 float 8 double 10/12/16 long double CMSC 313, F’ 09

Array Allocation Basic Principle T A[L]; n n Array of data type T and

Array Allocation Basic Principle T A[L]; n n Array of data type T and length L Contiguously allocated region of L * sizeof(T) bytes char string[12]; x x + 12 int val[5]; x double a[4]; x x + 8 x + 4 x + 8 x + 16 x + 12 x + 16 x + 24 x + 20 x + 32 char *p[3]; x – 3 – x + 4 x + 8 x + 12 CMSC 313, F’ 09

Array Access Basic Principle T A[L]; Array of data type T and length L

Array Access Basic Principle T A[L]; Array of data type T and length L n Identifier A can be used as a pointer to array element 0 n l Type T* int val[5]; 1 5 x Reference – 4 – val[4] val int * val+1 &val[2] val[5] *(val+1) val + i x + 4 2 x + 8 1 3 x + 12 x + 16 x + 20 Type Value int x int * int int * 3 x+4 x+8 ? ? 5 x+4 i CMSC 313, F’ 09

Array Example typedef int zip_dig[5]; zip_dig cmu = { 1, 5, 2, 1, 3

Array Example typedef int zip_dig[5]; zip_dig cmu = { 1, 5, 2, 1, 3 }; zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig umbc = { 2, 1, 2, 5, 0 }; zip_dig cmu; 1 16 zip_dig mit; 5 20 0 36 zip_dig umbc; 24 2 40 2 56 2 28 1 44 1 60 1 32 3 48 2 64 3 9 52 5 68 36 56 0 72 76 Notes n Declaration “zip_dig umbc” equivalent to “int umbc[5]” n Example arrays were allocated in successive 20 byte blocks l Not guaranteed to happen in general – 5 – CMSC 313, F’ 09

Array Accessing Example Computation n n Register %edx contains starting address of array Register

Array Accessing Example Computation n n Register %edx contains starting address of array Register %eax contains array index Desired digit at 4*%eax + %edx int get_digit (zip_dig z, int dig) { return z[dig]; } Use memory reference (%edx, %eax, 4) IA 32 Memory Reference Code # %edx = z # %eax = dig movl (%edx, %eax, 4), %eax # z[dig] – 6 – CMSC 313, F’ 09

Referencing Examples zip_dig cmu; 1 16 zip_dig mit; 5 20 0 36 zip_dig umbc;

Referencing Examples zip_dig cmu; 1 16 zip_dig mit; 5 20 0 36 zip_dig umbc; 24 2 40 2 56 2 28 1 44 1 60 1 32 3 48 2 64 3 36 9 52 5 68 56 0 72 76 Code Does Not Do Any Bounds Checking! Reference Address Value Guaranteed? mit[3] 36 + 4* 3 = 48 3 Yes mit[5] 36 + 4* 5 = 56 2 No mit[-1] 36 + 4*-1 = 32 3 No cmu[15] 16 + 4*15 = 76 ? ? No n Out of range behavior implementation-dependent l No guaranteed relative allocation of different arrays – 7 – CMSC 313, F’ 09

Array Loop Example Original Source Transformed Version As generated by GCC n Eliminate loop

Array Loop Example Original Source Transformed Version As generated by GCC n Eliminate loop variable i n Convert array code to pointer code n Express in do-while form n l No need to test at entrance – 8 – int zd 2 int(zip_dig z) { int i; int zi = 0; for (i = 0; i < 5; i++) { zi = 10 * zi + z[i]; } return zi; } int zd 2 int(zip_dig z) { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while (z <= zend); return zi; } CMSC 313, F’ 09

Array Loop Implementation (IA 32) Registers %ecx %eax %ebx z zi zend Computations 10*zi

Array Loop Implementation (IA 32) Registers %ecx %eax %ebx z zi zend Computations 10*zi + *z implemented as *z + 2*(zi+4*zi) z++ increments by 4 n – 9 – # %ecx = z xorl %eax, %eax leal 16(%ecx), %ebx. L 59: leal (%eax, 4), %edx movl (%ecx), %eax addl $4, %ecx leal (%eax, %edx, 2), %eax cmpl %ebx, %ecx jle. L 59 int zd 2 int(zip_dig z) { { int zi = 0; int *zend = z + 4; do { zi = 10 * zi + *z; z++; } while(z <= zend); return zi; } } # zi = 0 # zend = z+4 # 5*zi # *z�� # *z # z++ # zi = *z + 2*(5*zi) # z : zend # if <= goto loop CMSC 313, F’ 09

Nested Array Example #define PCOUNT 4 zip_dig md[PCOUNT] = {{2, 1, 1, 6, 2},

Nested Array Example #define PCOUNT 4 zip_dig md[PCOUNT] = {{2, 1, 1, 6, 2}, {2, 1, 2, 2, 8 }, {2, 1, 0, 4, 2 }, {2, 1, 0 }}; zip_dig md[4]; 2 1 1 6 2 2 1 2 2 8 2 1 0 4 2 2 1 0 76 n 96 116 136 156 Declaration “zip_dig md[4]” equivalent to “int md[4][5]” l Variable md denotes array of 4 elements » Allocated contiguously l Each element is an array of 5 int’s » Allocated contiguously n – 10 – “Row-Major” ordering of all elements guaranteed CMSC 313, F’ 09

Viewing as Multidimensional Array Declaration T A[R][C]; n n n A[0][0] 2 D array

Viewing as Multidimensional Array Declaration T A[R][C]; n n n A[0][0] 2 D array of data type T R rows, C columns Type T element requires K bytes • • • A[0][C-1] • • • A[R-1][0] • • • A[R-1][C-1] Array Size n R * C * K bytes Arrangement n Row-Major Ordering int A[R][C]; A A [0] • • • [0] [1] • • • [1] [0] [C-1] • • • A A [R-1] • • • [R-1] [0] [C-1] 4*R*C Bytes – 11 – CMSC 313, F’ 09

Nested Array Row Access Row Vectors n n n A[i] is array of C

Nested Array Row Access Row Vectors n n n A[i] is array of C elements Each element of type T requires K bytes Starting address A + i * (C * K) int A[R][C]; A[0] A – 12 – • • • A[i] A [0] • • • [C-1] A [i] [0] • • • A+i*C*4 A[R-1] A A [i] • • • [R-1] [C-1] [0] • • • A [R-1] [C-1] A+(R-1)*C*4 CMSC 313, F’ 09

Nested Array Row Access Code int *get_md_zip(int index) { return md[index]; } Row Vector

Nested Array Row Access Code int *get_md_zip(int index) { return md[index]; } Row Vector n n md[index] is array of 5 int’s Starting address md + 20*index IA 32 Code n n Computes and returns address Compute as md + 4*(index + 4*index) # %eax = index leal (%eax, 4), %eax # 5 * index leal md(, %eax, 4), %eax # md + (20 * index) – 13 – CMSC 313, F’ 09

Nested Array Element Access Array Elements n n A [i] [j] A[i][j] is element

Nested Array Element Access Array Elements n n A [i] [j] A[i][j] is element of type T Address A + i * (C * K) + j * K = A + (i * C + j)* K int A[R][C]; A[0] A • • • A[R-1] A[i] A [0] • • • [C-1] • • • A [i] [j] • • • A+i*C*4 A • • • [R-1] [0] • • • A [R-1] [C-1] A+(R-1)*C*4 A+(i*C+j)*4 – 14 – CMSC 313, F’ 09

Nested Array Element Access Code Array Elements n n md[index][dig] is int Address: md

Nested Array Element Access Code Array Elements n n md[index][dig] is int Address: md + 20*index + 4*dig IA 32 Code n int get_md_digit (int index, int dig) { return md[index][dig]; } Computes address md + 4*dig + 4*(index+4*index) n movl performs memory reference # %ecx = dig # %eax = index leal 0(, %ecx, 4), %edx leal (%eax, 4), %eax movl md(%edx, %eax, 4), %eax – 15 – # 4*dig # 5*index # *(md + 4*dig + 20*index) CMSC 313, F’ 09

Strange Referencing Examples zip_dig md[4]; 2 1 1 6 2 2 1 2 2

Strange Referencing Examples zip_dig md[4]; 2 1 1 6 2 2 1 2 2 8 2 1 0 4 2 2 1 0 76 96 Reference Address md[3][3] md[2][5] md[2][-1] md[4][-1] md[0][19] md[0][-1] 116 136 156 Value Guaranteed? 76+20*3+4*3 = 148 1 76+20*2+4*5 = 136 2 76+20*2+4*-1 = 112 76+20*4+4*-1 = 152 76+20*0+4*19 = 152 76+20*0+4*-1 = 72 ? ? Yes 8 0 0 Yes Yes No Code does not do any bounds checking n Ordering of elements within array guaranteed n – 16 – CMSC 313, F’ 09

Multi-Level Array Example n n Variable univ denotes array of 3 elements Each element

Multi-Level Array Example n n Variable univ denotes array of 3 elements Each element is a pointer l 4 bytes n zip_dig cmu = { 1, 5, 2, 1, 3 }; zip_dig mit = { 0, 2, 1, 3, 9 }; zip_dig umbc = { 2, 1, 2, 5, 0 }; #define UCOUNT 3 int *univ[UCOUNT] = {mit, cmu, umbc}; Each pointer points to array of int’s cmu univ 160 36 164 16 168 56 mit 1 16 20 0 umbc 36 56 – 17 – 5 2 24 2 40 9 28 1 44 4 60 1 32 3 48 7 64 3 9 52 2 68 36 56 0 72 76 CMSC 313, F’ 09

Element Access in Multi-Level Array Computation (IA 32) int get_univ_digit (int index, int dig)

Element Access in Multi-Level Array Computation (IA 32) int get_univ_digit (int index, int dig) { return univ[index][dig]; } n Element access Mem[univ + 4*index] + 4*dig] n Must do two memory reads l First get pointer to row array l Then access element within array # %ecx = index # %eax = dig leal 0(, %ecx, 4), %edx # 4*index movl univ(%edx), %edx # Mem[univ + 4*index] movl (%edx, %eax, 4), %eax # Mem[. . . + 4*dig] – 18 – CMSC 313, F’ 09

Array Element Accesses n Similar C references n Nested Array Different address computation Multi-Level

Array Element Accesses n Similar C references n Nested Array Different address computation Multi-Level Array int get_md_digit (int index, int dig) { return md[index][dig]; } int get_univ_digit (int index, int dig) { return univ[index][dig]; } Element at Mem[md+20*index+4*dig] Element at Mem[univ+4*index]+4*dig] n n cmu univ 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 2 1 1 5 2 0 1 76 96 116 136 156 160 36 164 16 168 56 mit 1 16 20 0 umbc ucb 36 56 – 19 – 5 2 24 2 40 29 9 28 1 44 1 4 60 1 32 3 48 2 7 64 3 52 5 2 68 36 9 56 0 72 76 CMSC 313, F’ 09

Strange Referencing Examples cmu univ 160 36 164 16 168 56 mit 1 16

Strange Referencing Examples cmu univ 160 36 164 16 168 56 mit 1 16 20 0 umbc 36 56 Reference Address 5 2 24 2 40 9 28 1 44 4 60 1 32 3 48 7 64 n – 20 – 36 9 52 2 68 56 0 72 76 Value Guaranteed? univ[2][3] 56+4*3 = 68 2 univ[1][5] 16+4*5 = 36 0 univ[2][-1] 56+4*-1 = 52 9 univ[3][-1] ? ? univ[1][12] 16+4*12 = 64 7 n 3 Yes No No Code does not do any bounds checking Ordering of elements in different arrays not guaranteed CMSC 313, F’ 09

Using Nested Arrays #define N 16 typedef int fix_matrix[N][N]; Strengths n n C compiler

Using Nested Arrays #define N 16 typedef int fix_matrix[N][N]; Strengths n n C compiler handles doubly subscripted arrays Generates very efficient code l Avoids multiply in index computation Limitation n Only works if have fixed array size (*, k) /* Compute element i, k of fixed matrix product */ int fix_prod_ele (fix_matrix a, fix_matrix b, int i, int k) { int j; int result = 0; for (j = 0; j < N; j++) result += a[i][j]*b[j][k]; return result; } (i, *) Row-wise A B Column-wise – 21 – CMSC 313, F’ 09

Dynamic Nested Arrays Strength n Can create matrix of arbitrary size Programming n int

Dynamic Nested Arrays Strength n Can create matrix of arbitrary size Programming n int * new_var_matrix(int n) { return (int *) calloc(sizeof(int), n*n); } Must do index computation int var_ele explicitly (int *a, int i, int j, int n) { Performance return a[i*n + j]; n Accessingle element }� n costly Must do multiplication movl 12(%ebp), %eax movl 8(%ebp), %edx imull 20(%ebp), %eax addl 16(%ebp), %eax movl (%edx, %eax, 4), %eax – 22 – # i # a # n*i+j # Mem[a+4*(i*n+j)] CMSC 313, F’ 09

Dynamic Array Multiplication Without Optimizations n Multiplies l 2 for subscripts l 1 for

Dynamic Array Multiplication Without Optimizations n Multiplies l 2 for subscripts l 1 for data n Adds l 2 for array indexing l 1 for loop index l 1 for data (*, k) /* Compute element i, k of variable matrix product */ int var_prod_ele (int *a, int *b, int i, int k, int n) { int j; int result = 0; for (j = 0; j < n; j++) result += a[i*n+j] * b[j*n+k]; return result; } (i, *) Row-wise A B Column-wise – 23 – CMSC 313, F’ 09

Optimizing Dynamic Array Mult. Optimizations n Performed when set optimization level to -O 2

Optimizing Dynamic Array Mult. Optimizations n Performed when set optimization level to -O 2 Code Motion n Expression i*n can be computed outside loop Strength Reduction n Incrementing j has effect of incrementing j*n+k by n Performance n – 24 – Compiler can optimize regular access patterns { int j; int result = 0; for (j = 0; j < n; j++) result += a[i*n+j] * b[j*n+k]; return result; } { int j; int result = 0; int i. Tn = i*n; int j. Tn. Pk = k; for (j = 0; j < n; j++) { result += a[i. Tn+j] * b[j. Tn. Pk]; j. Tn. Pk += n; } return result; } CMSC 313, F’ 09

Summary Arrays in C n Contiguous allocation of memory n Pointer to first element

Summary Arrays in C n Contiguous allocation of memory n Pointer to first element No bounds checking n – 25 – CMSC 313, F’ 09