The C statement
Let’s look at some C code to set
an integer m to the larger of the
integers x, y, and z.
if (x >= y && x >= z) {
m = x ;
} else if (y >= z) {
m = y ;
} else {
m = z ;
}
If you use the rules of the control structures section, which ignores expression evaluation, you’ll get something like the following:
int τ1 = x >= y && x >= z ;
if (τ1 == 0) goto λ1 ;
m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
Now we have to worry about evaluating the expression
with the &&.
Here we use the rules for
dealing with logical expression.
This is going to get very messy.
First, we get the following:
int τ1 ;
if (! (x >= y)) {
τ1 = 0 ;
} else if (! (x >= z)) {
τ1 = 0 ;
} else {
τ1 = 1 ;
}
if (τ1 == 0) goto λ1 ;
m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
Then we go back and apply the rules of the
if—else, and it gets even worse.
int τ1 ;
int τ3 = ! (x >= y) ;
if (τ3 == 0) goto λ4 ;
τ1 = 0 ;
goto λ6 ;
λ4: int τ4 = ! (x >= z) ;
if (τ4 == 0) goto λ5 ;
τ1 = 0 ;
goto λ6 ;
λ5: τ1 = 1 ;
λ6: if (τ1 == 0) goto λ1 ;
m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
Huh?
Yep. That’s pretty silly. Let’s do some optimiztions. First simplify those comparisions.
int τ1 ;
int τ3 = (x < y) ;
if (τ3 == 0) goto λ4 ;
τ1 = 0 ;
goto λ6 ;
λ4: int τ4 = (x < z) ;
if (τ4 == 0) goto λ5 ;
τ1 = 0 ;
goto λ6 ;
λ5: τ1 = 1 ;
λ6: if (τ1 == 0) goto λ1 ;
m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
There are some branching inefficiences here.
For example, in one place τ1 is set to
0 before a transfer to λ6 where
τ1 is immediately compared to 0 before
transfering to λ1.
Let’s speed that up a little. We can even eliminate τ1.
int τ3 = (x < y) ;
if (τ3 == 0) goto λ4 ;
goto λ1 ;
λ4: int τ4 = (x < z) ;
if (τ4 == 0) goto λ5 ;
goto λ1 ;
λ5: m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
Next we can remove a few of those unconditional goto’s
by optimizing the tests.
int τ3 = (x < y) ;
if (τ3 != 0) goto λ1 ;
int τ4 = (x < z) ;
if (τ4 != 0) goto λ1 ;
m = x ;
goto λ3 ;
λ1: int τ2 = y >= z ;
if (τ2 == 0) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
You might find this a little easier to read if we just
got rid of τ2,
τ3, and τ4.
if (x < y) goto λ1 ;
if (x < z) goto λ1 ;
m = x ;
goto λ3 ;
λ1: if (y < z) goto λ2 ;
m = y ;
goto λ3 ;
λ2: m = z ;
λ3:
That’s what any self respecting C compiler would do.