View
219
Download
1
Tags:
Embed Size (px)
Citation preview
CMPUT 229 1
EfficiencyEfficiency
Often several ways to write the same Often several ways to write the same programprogram
Want to choose the most efficient Want to choose the most efficient implementationimplementation
SpaceSpace efficiency efficiency using small amount of memoryusing small amount of memory
TimeTime efficiency efficiency running in small amount of timerunning in small amount of time
These goals are sometimes at oddsThese goals are sometimes at odds need to make compromise between space need to make compromise between space
and timeand time
CMPUT 229 2
Space efficiencySpace efficiency
To achieve To achieve space efficiencyspace efficiency in in datadata allocate all allocate all variablesvariables to be of most to be of most
appropriate sizeappropriate size• use use charchar or or shortshort instead of instead of intint where where
applicable, especially in arraysapplicable, especially in arrays freefree unwanted unwanted dynamic datadynamic data share datashare data where possible where possible
• use pointers, which can point to same datause pointers, which can point to same data• e.g., don’t duplicate string, but point several e.g., don’t duplicate string, but point several
pointers to same stringpointers to same string• need to be careful of aliasing bugsneed to be careful of aliasing bugs
use use space-efficient algorithmsspace-efficient algorithms• e.g., quicksort (in-place) instead of mergesort e.g., quicksort (in-place) instead of mergesort
(needs temporary array)(needs temporary array)
CMPUT 229 3
Space efficiencySpace efficiency
To achieve To achieve space efficiencyspace efficiency in in codecode re-use codere-use code
• write functions wherever possiblewrite functions wherever possible avoid global variablesavoid global variables
• local variables can be accessed with one local variables can be accessed with one machine instructionmachine instruction
• globals require two machine instructions globals require two machine instructions to construct address and access variableto construct address and access variable
• MIPS features MIPS features $gp$gp (global pointer) (global pointer) register to make some global variables register to make some global variables more efficientmore efficient
CMPUT 229 4
Time efficiencyTime efficiency
To achieve To achieve time efficiencytime efficiency avoidavoid using using multiplymultiply and and dividedivide
instructionsinstructions• in MIPS, multiply and divide halt in MIPS, multiply and divide halt
processor until result is available, several processor until result is available, several clock cycles laterclock cycles later
• use shift (and perhaps add) instructions if use shift (and perhaps add) instructions if multiplying by a constantmultiplying by a constant
• n*8 = n << 3, n*10 = (n << 3)+(n << 1)n*8 = n << 3, n*10 = (n << 3)+(n << 1)
• when writing C, compiler will usually do when writing C, compiler will usually do this for youthis for you
CMPUT 229 5
Time efficiencyTime efficiency
To achieve To achieve time efficiencytime efficiency make program make program shortershorter
• each instruction takes same time to run, each instruction takes same time to run, so fewer instructions means shorter so fewer instructions means shorter executionexecution
• some space efficiency arguments also some space efficiency arguments also improve time efficiencyimprove time efficiency
• e.g., avoid globals, share datae.g., avoid globals, share data
make program make program take fewer stepstake fewer steps• economize jump/branch instructions, economize jump/branch instructions,
remove redundant onesremove redundant ones
CMPUT 229 6
Loop conditionsLoop conditions
In MIPS, ordered comparisons (In MIPS, ordered comparisons (bltblt, , bleble, , bgtbgt, , bgebge) are pseudoinstructions) are pseudoinstructions expand to more than one machine expand to more than one machine
instructioninstruction
Save one instruction per loop by using Save one instruction per loop by using unordered comparisons (unordered comparisons (beqbeq, , bnebne)) for (i = 0; i < 10; i++)for (i = 0; i < 10; i++) for (i = 0; i != 10; i++)for (i = 0; i != 10; i++)
can be unsafe to do this if loop is complexcan be unsafe to do this if loop is complex
CMPUT 229 7
Loop conditionsLoop conditions
Pre-testedPre-tested loop loop ((whilewhile))
# Do it 10 times.# Do it 10 times.
sw $0, xsw $0, x
loop: lw $t0, xloop: lw $t0, x beq $t0, 10, endbeq $t0, 10, end
# body of loop: n steps# body of loop: n steps
lw $t0, xlw $t0, x add $t0, $t0, 1add $t0, $t0, 1 sw $t0, xsw $t0, x j loopj loop
end: end: rest of program ...rest of program ...
Post-testedPost-tested loop loop ((do-whiledo-while))
# Do it 10 times.# Do it 10 times.
sw $0, xsw $0, x
loop: loop: # body of loop: n steps# body of loop: n steps
lw $t0, xlw $t0, x add $t0, $t0, 1add $t0, $t0, 1 sw $t0, xsw $t0, x
lw $t0, xlw $t0, x bne $t0, 10, loopbne $t0, 10, loop
# rest of program ...# rest of program ...
n+6 steps per iterationn+6 steps per iteration
n+5 steps per iterationn+5 steps per iteration
CMPUT 229 8
Loop conditionsLoop conditions
Post-testedPost-tested loops loops marginally more marginally more efficientefficient (space and time) (space and time) than pre-than pre-testedtested use use dodo--whilewhile loops if no harm in body loops if no harm in body
running oncerunning once
Compilers can turn while loop into Compilers can turn while loop into post-tested equivalentpost-tested equivalent by performing jump to test before by performing jump to test before
loop startsloop starts
CMPUT 229 9
Switch statementSwitch statement
When When switchswitch statement coded as statement coded as cascaded cascaded ifif--elseelse put put common cases firstcommon cases first
• fewer failed comparisonsfewer failed comparisons default case should be uncommondefault case should be uncommon
• since all comparisons must failsince all comparisons must fail
When switch statement coded with When switch statement coded with jump tablejump table need cases to be numerically denseneed cases to be numerically dense
Compilers can be directed to implement Compilers can be directed to implement switch statement either wayswitch statement either way depending on properties of casesdepending on properties of cases
CMPUT 229 10
Variables in registersVariables in registers# This version keeps a variable# This version keeps a variable# on stack.# on stack. .text.textmain: move $fp, $spmain: move $fp, $sp subu $sp, $sp, 4subu $sp, $sp, 4
li $v0, 5 li $v0, 5 # get repeat# get repeat syscall syscall # count from user# count from user sw $v0, -4($fp) sw $v0, -4($fp) # stack it# stack it
loop: lw $t0, -4($fp)loop: lw $t0, -4($fp) ble $t0, $zero, endble $t0, $zero, end
# Do something: n steps.# Do something: n steps.
lw $t0, -4($fp)lw $t0, -4($fp) sub $t0, $t0, 1sub $t0, $t0, 1 sw $t0, -4($fp)sw $t0, -4($fp) j loopj loop
end: addu $sp,$sp, 4end: addu $sp,$sp, 4 li $v0, 10li $v0, 10 syscallsyscall
# This version keeps a variable# This version keeps a variable# in a register ($s0).# in a register ($s0). .text.textmain: move $fp, $spmain: move $fp, $sp
li $v0, 5 li $v0, 5 # get repeat# get repeat syscall syscall # count from user# count from user move $s0, $v0 move $s0, $v0 # keep in reg# keep in reg
loop: ble $s0, $zero, endloop: ble $s0, $zero, end
# Do something: n steps.# Do something: n steps.
sub $s0, $s0, 1sub $s0, $s0, 1 j loopj loop
end: li $v0, 10end: li $v0, 10 syscallsyscalln+6 steps per iterationn+6 steps per iteration n+3 steps per iterationn+3 steps per iteration
CMPUT 229 11
Variables in registersVariables in registers
ImprovedImproved time and space time and space efficiencyefficiency by by storing storing locallocal variables in registersvariables in registers in MIPS, general-purpose registers in MIPS, general-purpose registers $s0$s0 to to $s7$s7 are available for variables are available for variables
if functions use these, must save old value if functions use these, must save old value on stack (along with on stack (along with $ra$ra and and $fp$fp))
Compiler can be directed to put some Compiler can be directed to put some local variables in registerslocal variables in registers C has C has registerregister keyword to provide hint to keyword to provide hint to
compiler (ignored by many compilers)compiler (ignored by many compilers)
CMPUT 229 12
Pointers and arraysPointers and arrays/* String copy using arrays. *//* String copy using arrays. */
char *strcpy(char s[], char t[])char *strcpy(char s[], char t[]){{ int i = 0;int i = 0;
while ((s[i] = t[i]) != '\0')while ((s[i] = t[i]) != '\0') {{ i++;i++; }}
return s;return s;}}
# strcpy function in MIPS.# strcpy function in MIPS.# Variables kept in registers:# Variables kept in registers:# i in $t9, s in $t4, t in $t5.# i in $t9, s in $t4, t in $t5.
strcpy: subu $sp, $sp, 8strcpy: subu $sp, $sp, 8 sw $ra, 4($sp)sw $ra, 4($sp) sw $fp, 0($sp)sw $fp, 0($sp) move $fp, $spmove $fp, $sp move $t9, $zero move $t9, $zero # i # i lw $t4, 8($fp) lw $t4, 8($fp) # s # s lw $t5, 12($fp) lw $t5, 12($fp) # t # tloop: add $t0, $t5, $t9loop: add $t0, $t5, $t9 lbu $t1, 0($t0) lbu $t1, 0($t0) # t[i]# t[i] add $t0, $t4, $t9add $t0, $t4, $t9 sb $t1, 0($t0) sb $t1, 0($t0) # s[i]# s[i] beq $t1, 0, endbeq $t1, 0, end add $t9, $t9, 1 add $t9, $t9, 1 # i++# i++ j loopj loopend: lw $v0, 8($fp) end: lw $v0, 8($fp) # s# s lw $fp, 0($sp)lw $fp, 0($sp) lw $ra, 4($sp)lw $ra, 4($sp) addu $sp, $sp, 8addu $sp, $sp, 8 jr $rajr $ra
7 instructions per copy 7 instructions per copy (would be 13 per copy (would be 13 per copy if everything kept on if everything kept on
stack)stack)
CMPUT 229 13
Pointers and arraysPointers and arrays/* String copy using pointers. *//* String copy using pointers. */
char *strcpy(char *s, char *t)char *strcpy(char *s, char *t){{ char *r = s;char *r = s;
while ((*s = *t) != '\0')while ((*s = *t) != '\0') {{ s++; t++;s++; t++; }}
return r;return r;}}
# strcpy function in MIPS.# strcpy function in MIPS.# Variables kept in registers:# Variables kept in registers:# r in $t8, s in $t4, t in $t5.# r in $t8, s in $t4, t in $t5.
strcpy: subu $sp, $sp, 8strcpy: subu $sp, $sp, 8 sw $ra, 4($sp)sw $ra, 4($sp) sw $fp, 0($sp)sw $fp, 0($sp) move $fp, $spmove $fp, $sp lw $t4, 8($fp) lw $t4, 8($fp) # s# s move $t8, $t4 move $t8, $t4 # r# r lw $t5, 12($fp) lw $t5, 12($fp) # t# tloop: lbu $t1, 0($t5) loop: lbu $t1, 0($t5) # *t# *t sb $t1, 0($t4) sb $t1, 0($t4) # *s# *s beq $t1, 0, endbeq $t1, 0, end add $t4, $t4, 1 add $t4, $t4, 1 # s++# s++ add $t5, $t5, 1add $t5, $t5, 1 # t++ # t++ j loopj loopend: move $v0, $t8 end: move $v0, $t8 # r # r lw $fp, 0($sp)lw $fp, 0($sp) lw $ra, 4($sp)lw $ra, 4($sp) addu $sp, $sp, 8addu $sp, $sp, 8 jr $rajr $ra
6 instructions per copy 6 instructions per copy (would be 12 per copy (would be 12 per copy if everything kept on if everything kept on
stack) stack)
CMPUT 229 14
Pointers and arraysPointers and arrays
PointersPointers oftenoften produce produce more more efficientefficient code than arrays code than arrays especially especially if arrays are being walkedif arrays are being walked
alongalong entire length entire length
CompilersCompilers were were not smart enoughnot smart enough to generate more efficient codeto generate more efficient code to get benefit, you to get benefit, you had to write had to write
different Cdifferent C code code this has improved considerablythis has improved considerably
CMPUT 229 15
Example for PointerExample for Pointer 1 #include <stdio.h> 2 void Swap(int firstVal, int secondVal); 3 4 main() 5 { 6 int valueA = 3; 7 int valueB = 4; 8 9 printf("Before Swap: valueA = %d and valueB = %d\n", valueA, valueB); 10 Swap(valueA, valueB);11 printf("After Swap: valueA = %d and valueB = %d\n", valueA, valueB);12 }1314 void Swap(int firstVal, int secondVal)15 {16 int tempVal;1718 tempVal = firstVal;19 firstVal = secondVal;20 secondVal = tempVal;21 }
CMPUT 229 16
1 #include <stdio.h> 2 void Swap(int firstVal, int secondVal); 3 4 main() 5 { 6 int valueA = 3; 7 int valueB = 4; 8 9 printf("Before Swap: valueA = %d and valueB = %d\n", valueA, valueB);10 Swap(valueA, valueB);11 printf("After Swap: valueA = %d and valueB = %d\n", valueA, valueB);12 }1314 void Swap(int firstVal, int secondVal)15 {16 int tempVal;1718 tempVal = firstVal;19 firstVal = secondVal;20 secondVal = tempVal;21 }
$a1
$a2
$a0
$v1
$v0
$at
0
4
bash-2.01$ ./swapO0Before Swap: valueA = 3 and valueB = 4After Swap: valueA = 3 and valueB = 4
CMPUT 229 17
1 #include <stdio.h> 2 void Swap(int firstVal, int secondVal); 3 4 main() 5 { 6 int valueA = 3; 7 int valueB = 4; 8 9 printf("Before Swap: valueA = %d and valueB = %d\n", valueA, valueB);10 Swap(valueA, valueB);11 printf("After Swap: valueA = %d and valueB = %d\n", valueA, valueB);12 }1314 void Swap(int firstVal, int secondVal)15 {16 int tempVal;1718 tempVal = firstVal;19 firstVal = secondVal;20 secondVal = tempVal;21 }
Assembly for Swap Assembly for Swap GeneratedGenerated
$a1
$a2
$a0
Stack
$v1
$v0
$at
0
4
# 5 main() # 6 {
addiu $sp,$sp,-32 # .frame.len.mainsd $gp,16($sp) # .lcl_spill_b002sd $ra,8($sp) # .lcl_spill_b001lui $a3,%hi(%neg(%gp_rel(main +0)))addiu $a3,$a3,%lo(%neg(%gp_rel(main +0))) addu $gp,$t9,$a3
# 7 int valueA = 3;addiu $a2,$zero,3 sw $a2,0($sp) # valueA
# 8 int valueB = 4;addiu $a1,$zero,4 sw $a1,4($sp) # valueB
# 10 printf("Before Swap: valueA = %d and valueB = %d\n", valueA, valueB);lw $a0,%got_page(.rodata)($gp) addiu $a0,$a0,%got_ofst(.rodata) lw $a1,0($sp) # valueAlw $a2,4($sp) # valueBlw $t9,%call16(printf)($gp) jalr $t9 # printfnop
CMPUT 229 18
.BB2.main: # 0x44 # 11 Swap(valueA, valueB);
lw $a0,0($sp) # valueAlw $a1,4($sp) # valueBlw $t9,%call16(Swap)($gp) jalr $t9 # Swapnop
.BB3.main: # 0x58 # 12 printf("After Swap: valueA = %d and valueB = %d\n", valueA, valueB);
lw $a0,%got_page(.rodata+48)($gp)addiu $a0,$a0,%got_ofst(.rodata+48)lw $a1,0($sp) # valueAlw $a2,4($sp) # valueBlw $t9,%call16(printf)($gp) jalr $t9 # printfnop
.BB4.main: # 0x74 # 13 }
or $v0,$zero,$zero ld $gp,16($sp) # .lcl_spill_b002ld $ra,8($sp) # .lcl_spill_b001addiu $sp,$sp,32 # .frame.len.mainjr $ra nop
CMPUT 229 19
Addresses and ValuesAddresses and Values
The problem with our swap program is that the main is passingthe values of variables valueA and valueB to the swap function.
Thus the swap function does all its work within its own frame inthe stack and never actually changes the state of the variablesin the main function.
Could a “smarter” compiler figure out that the swap function is doing nothing?
CMPUT 229 20
Example: A new swap functionExample: A new swap function 1 #include <stdio.h> 2 void NewSwap(int *firstVal, int *secondVal); 3 4 main() 5 { 6 int valueA = 3; 7 int valueB = 4; 8 9 printf("Before Swap: valueA = %d and valueB = %d\n", valueA, valueB);10 NewSwap(&valueA, &valueB);11 printf("After Swap: valueA = %d and valueB = %d\n", valueA, valueB);12 }1314 void NewSwap(int *firstVal, int *secondVal)15 {16 int tempVal;1718 tempVal = *firstVal;19 *firstVal = *secondVal;20 *secondVal = tempVal;21 }
bash-2.01$ ./newswapO0Before Swap: valueA = 3 and valueB = 4After Swap: valueA = 4 and valueB = 3
CMPUT 229 21
What if the data item to be passed What if the data item to be passed is not an integer, but a complex is not an integer, but a complex data structure?data structure?
CMPUT 229 22
The car.c programThe car.c program
#include <stdio.h>#define STRINGLENGTH 20
typedef struct c_node{ int vehicleID; char make[STRINGLENGTH]; char model[STRINGLENGTH]; int year; int mileage; double cost; struct c_node *next;} CarNode;
void ReadCar(CarNode *car);void PrintCar(CarNode car);
main(){ CarNode mycar; ReadCar(&mycar); PrintCar(mycar);}
void ReadCar(CarNode *car){ car->vehicleID = 2; strcpy(car->make,"DODGE"); strcpy(car->model,"STRATUS"); car->year = 1996; car->mileage = 70000; car->cost = 4,525.74;}
void PrintCar(CarNode car){ printf("vehicleID: %d\n",car.vehicleID); printf("make: %s\n",car.make); printf("model: %s\n",car.model); printf("year: %d\n",car.year); printf("mileage: %d\n",car.mileage); printf("cost: %f\n",car.cost);}
Patt and Patel, pp. 419
CMPUT 229 23
The car.c programThe car.c program
#define STRINGLENGTH 20
typedef struct c_node{ int vehicleID; char make[STRINGLENGTH]; char model[STRINGLENGTH]; int year; int mileage; double cost; struct c_node next;} CarNode;
vehicleID
make[20]
model[20]
yearmileage
cost
next
048
1216202428323640444852566064
CMPUT 229 24
The car.c programThe car.c program
#include <stdio.h>#define STRINGLENGTH 20
typedef struct c_node{ int vehicleID; char make[STRINGLENGTH]; char model[STRINGLENGTH]; int year; int mileage; double cost; struct c_node next;} CarNode;
void ReadCar(CarNode car);void PrintCar(CarNode car);
main(){ CarNode mycar; ReadCar(&mycar); PrintCar(mycar);}
main:subu $sp, 168sw $ra, 84($sp).frame $sp, 168, $ra
# 23 CarNode mycar; # 25 ReadCar(&mycar);
addu $a0, $sp, 88jal ReadCar
# 27 PrintCar(mycar);addu $t6, $sp, 88move $t9, $spaddu $t0, $t6, 72
L1:lw $t8, 0($t6)addu $t6, $t6, 12sw $t8, 0($t9)lw $t7, -8($t6)addu $t9, $t9, 12sw $t7, -8($t9)lw $t8, -4($t6)sw $t8, -4($t9)bne $t6, $t0, L1lw $a0, 0($sp)lw $a1, 4($sp)lw $a2, 8($sp)lw $a3, 12($sp)jal PrintCar
# 28 }move $v0, $zerolw $ra, 84($sp)addu $sp, 168j $ra
CMPUT 229 25
The car.c programThe car.c program
main:subu $sp, 168sw $ra, 84($sp).frame $sp, 168, $ra
# 23 CarNode mycar; # 25 ReadCar(&mycar);
addu $a0, $sp, 88jal ReadCar
# 27 PrintCar(mycar);addu $t6, $sp, 88move $t9, $spaddu $t0, $t6, 72
L1:lw $t8, 0($t6)addu $t6, $t6, 12sw $t8, 0($t9)lw $t7, -8($t6)addu $t9, $t9, 12sw $t7, -8($t9)lw $t8, -4($t6)sw $t8, -4($t9)bne $t6, $t0, L1lw $a0, 0($sp)lw $a1, 4($sp)lw $a2, 8($sp)lw $a3, 12($sp)jal PrintCar
# 28 }move $v0, $zerolw $ra, 84($sp)addu $sp, 168j $ra
next
cost
cost
mileage
year
model[16-19]
model[12-15]
model[8-11]
model[4-7]
model[0-3]
make[16-19]
make[12-15]
make[8-11]
make[4-7]
make[0-3]
vehicleID
SP00
04
08
12
16
20
24
28
32
36
40
44
48
52
56
60
64
68
72
76
80
84
88
92
180
184
188
96
100
104
108
112116
120
124
128
132
136
140
144148
152
156
160
164
168
172
176
$t9
$t6
$t0
$t8
$t7
vehicleID
CMPUT 229 26
The car.c programThe car.c program
main:subu $sp, 168sw $ra, 84($sp).frame $sp, 168, $ra
# 23 CarNode mycar; # 25 ReadCar(&mycar);
addu $a0, $sp, 88jal ReadCar
# 27 PrintCar(mycar);addu $t6, $sp, 88move $t9, $spaddu $t0, $t6, 72
L1:lw $t8, 0($t6)addu $t6, $t6, 12sw $t8, 0($t9)lw $t7, -8($t6)addu $t9, $t9, 12sw $t7, -8($t9)lw $t8, -4($t6)sw $t8, -4($t9)bne $t6, $t0, L1lw $a0, 0($sp)lw $a1, 4($sp)lw $a2, 8($sp)lw $a3, 12($sp)jal PrintCar
# 28 }move $v0, $zerolw $ra, 84($sp)addu $sp, 168j $ra
next
cost
cost
mileage
year
model[16-19]
model[12-15]
model[8-11]
model[4-7]
model[0-3]
make[16-19]
make[12-15]
make[8-11]
make[4-7]
make[0-3]
vehicleID
SP00
04
08
12
16
20
24
28
32
36
40
44
48
52
56
60
64
68
72
76
80
84
88
92
180
184
188
96
100
104
108
112116
120
124
128
132
136
140
144148
152
156
160
164
168
172
176
$t9
$t0
$t8
$t7
vehicleID
$t6
vehicleID
make[0-3]
CMPUT 229 27
The car.c programThe car.c program
main:subu $sp, 168sw $ra, 84($sp).frame $sp, 168, $ra
# 23 CarNode mycar; # 25 ReadCar(&mycar);
addu $a0, $sp, 88jal ReadCar
# 27 PrintCar(mycar);addu $t6, $sp, 88move $t9, $spaddu $t0, $t6, 72
L1:lw $t8, 0($t6)addu $t6, $t6, 12sw $t8, 0($t9)lw $t7, -8($t6)addu $t9, $t9, 12sw $t7, -8($t9)lw $t8, -4($t6)sw $t8, -4($t9)bne $t6, $t0, L1lw $a0, 0($sp)lw $a1, 4($sp)lw $a2, 8($sp)lw $a3, 12($sp)jal PrintCar
# 28 }move $v0, $zerolw $ra, 84($sp)addu $sp, 168j $ra
next
cost
cost
mileage
year
model[16-19]
model[12-15]
model[8-11]
model[4-7]
model[0-3]
make[16-19]
make[12-15]
make[8-11]
make[4-7]
make[0-3]
vehicleID
SP00
04
08
12
16
20
24
28
32
36
40
44
48
52
56
60
64
68
72
76
80
84
88
92
180
184
188
96
100
104
108
112116
120
124
128
132
136
140
144148
152
156
160
164
168
172
176
$t0
$t8
$t7
vehicleID
$t6
vehicleID
make[0-3]
$t9
make[0-3]
make[4-7]
make[4-7]
CMPUT 229 28
Why so much copying?Why so much copying?
The program car.c passes the datastructure CarNodeto the PrintCar function by value.
A copy of each byte of CarNode must be made in thestack for each call of the function PrintCar.
We could, instead have passed the address of the copyof CarNode that we already had in the stack.
CMPUT 229 29
The car2.c ProgramThe car2.c Program
#include <stdio.h>#define STRINGLENGTH 20
typedef struct c_node{ int vehicleID; char make[STRINGLENGTH]; char model[STRINGLENGTH]; int year; int mileage; double cost; struct c_node next;} CarNode;
void ReadCar(CarNode car);void PrintCar(CarNode car);
main(){ CarNode mycar; ReadCar(&mycar); PrintCar(&mycar);}
void ReadCar(CarNode car){ car->vehicleID = 2; strcpy(car->make,"DODGE"); strcpy(car->model,"STRATUS"); car->year = 1996; car->mileage = 70000; car->cost = 4,525.74;}
void PrintCar(CarNode car){ printf("vehicleID: %d\n",car->vehicleID); printf("make: %s\n",car->make); printf("model: %s\n",car->model); printf("year: %d\n",car->year); printf("mileage: %d\n",car->mileage); printf("cost: %f\n",car->cost);}
CMPUT 229 30
car-O0.s car2-O0.s
#include <stdio.h>#define STRINGLENGTH 20
typedef struct c_node{ int vehicleID; char make[STRINGLENGTH]; char model[STRINGLENGTH]; int year; int mileage; double cost; struct c_node next;} CarNode;
void ReadCar(CarNode car);void PrintCar(CarNode car);
main(){ CarNode mycar; ReadCar(&mycar); PrintCar(&mycar);}
main:subu $sp, 112sw $ra, 28($sp)
# 23 CarNode mycar; # 25 ReadCar(&mycar);
addu $a0, $sp, 32jal ReadCar
# 27 PrintCar(&mycar);addu $a0, $sp, 32jal PrintCar
# 28 }move $v0, $zerolw $ra, 28($sp)addu $sp, 112j $ra
CMPUT 229 31
Example 3 ArrayExample 3 Array
Question 4 in Assignment 3Question 4 in Assignment 3
CMPUT 229 32
Inline functionsInline functions# Calling a function ...# Calling a function ...
.text.textmain: move $fp, $spmain: move $fp, $sp subu $sp, $sp, 4 subu $sp, $sp, 4 # local# local
# Call func(local, 42)# Call func(local, 42) subu $sp, $sp, 8subu $sp, $sp, 8 lw $t0, -4($fp) lw $t0, -4($fp) # local# local sw $t0, 0($sp) sw $t0, 0($sp) # arg 1# arg 1 li $t0, 42li $t0, 42 sw $t0, 4($sp) sw $t0, 4($sp) # arg 2# arg 2 jal funcjal func addu $sp, $sp, 8addu $sp, $sp, 8
# more code ...# more code ...
# A function ...# A function ...
funcfunc: subu $sp, $sp, 8: subu $sp, $sp, 8 sw $ra, 4($sp)sw $ra, 4($sp) sw $fp, 0($sp)sw $fp, 0($sp) move $fp, $spmove $fp, $sp
# code that uses# code that uses # params at 8($fp)# params at 8($fp) # and 12($fp)# and 12($fp)
lw $fp, 0($sp)lw $fp, 0($sp) lw $ra, 4($sp)lw $ra, 4($sp) addu $sp, $sp, 8addu $sp, $sp, 8 jr $rajr $ra
8 instructions needed to 8 instructions needed to enter/leave functionenter/leave function
7 instructions 7 instructions needed to call needed to call
functionfunction
CMPUT 229 33
Inline functionsInline functions# Calling a function ...# Calling a function ...
.text.textmain: move $fp, $spmain: move $fp, $sp subu $sp, $sp, 4 subu $sp, $sp, 4 # local# local
# Pretend to call# Pretend to call # func(local, 42).# func(local, 42).
# Code that uses# Code that uses # value at -4($fp)# value at -4($fp) # and constant 42.# and constant 42.
# more code ...# more code ...
saved 15 instructions saved 15 instructions by putting body of by putting body of funcfunc
straight into straight into mainmain
# A function ...# A function ...
func: subu $sp, $sp, 8func: subu $sp, $sp, 8 sw $ra, 4($sp)sw $ra, 4($sp) sw $fp, 0($sp)sw $fp, 0($sp) move $fp, $spmove $fp, $sp
# code that uses# code that uses # params at 8($fp)# params at 8($fp) # and 12($fp)# and 12($fp)
lw $fp, 0($sp)lw $fp, 0($sp) lw $ra, 4($sp)lw $ra, 4($sp) addu $sp, $sp, 8addu $sp, $sp, 8 jr $rajr $ra
no longer even no longer even need this need this
function’s codefunction’s code
CMPUT 229 34
Inline functionsInline functions
Inlining functionsInlining functions gives large gives large improvementimprovement in in time efficiencytime efficiency at vast at vast cost of space efficiencycost of space efficiency only feasible for only feasible for very short functionsvery short functions
or for functions or for functions called very few timescalled very few times
Compilers can be directed to inline Compilers can be directed to inline selected functionsselected functions automatically, or hinted through use automatically, or hinted through use
of C of C inlineinline keyword keyword