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.