In homework I received a task to change a C code to ASM of simplified DLX:
a = 0;
for (i = 1; i < 14; i++)
a = a + c;
A[0] = a;
My solution:
Assuming:
- Value of
a
is in register R1 - Value of
c
is in register R2 - Value of
i
is in register R3 - Value of address of
A
(means&A
) is in register R4
Then:
addi R1 R0 0 // init a = 0
addi R3 R0 1 // init i = 1
slti R5 R3 14 // test (i < 14) ; R5 = 1 if i < 14
beqz R5 3 // branch 3 lines of R5 == 0
add R1 R1 R2 // a = a + c
addi R3 R3 1 // i++
beqz R0 -5 // return up to the condition of the for loop
sw R1 R4 0 // A[0] = 0
Their solution:
Assuming:
- Value of
a
is in register R1 - Value of
i
is in register R2 (notice the change here) - Value of
c
is in register R3 (notice the change here) - Value of address of
A
(means&A
) is in register R4
Then:
addi R1 R0 0 // a = 0
addi R2 R0 1 // i = 1
add R1 R1 R3 // a = a+c
addi R2 R2 1 // i++
slti R5 R2 14 // R5=1 iff i<14
bnez R5 -4 // jump 4 lines up from the next line if
// R5!=0, that is if i<14
sw R1 R4 0 // store the new value of A[0]=a (R1)
Difference:
Their solution is obviously better because that there's 1 less command - my code has an additional conditional branching. Their code is exactly what I wanted to do in the first place, but then I recalled of the for
loop algorithm:
- Initialize a variable
- Check if condition is
True
.
IfTrue
: Apply commands within the loop,
Otherwise: exit the loop. - Increment variable
- return to #2
So their code differs from the for loop algorithm, because that it doesn't check the condition (#2) after the initialization (#1)...
I thought to myself - is this the result of an optimization?
What level of optimization is this? (IIRC there are 4 levels: O0, O1, O2, O3)
Is it expected to optimize code by default when interpreting a C code?
When an optimization is activated, your compiler review its assembly code in order to see if there is anything to improve, in particular avoid useless instructions or check.
For instance, in your code, the
for
loop is an initialization, then a classicwhile
loop. A classic optimization is to check if awhile
condition can be false at the first entry, and if not, transform it in ado while
loop.This is precisely your case.
i < 14
cannot be false if you check it just after an instruction meaningi = 1
. So it is faster to run:So yes, it is a form of optimization. But when you code directly in assembly language, you are usually expected to do this kind of tricks, because the goal of assembly programming (and mainly learn it) is to make your code as fast as possible, using any possibilities to reduce instruction calls.
This is a result of level O1 optimization on GCC.