4/16 In a C statement like "if (foo > bar)" where foo is a int8 and
bar is in32, how does the compiler translate that? Does it turn
it into a int32 to int32 comparison? Or does it chop off bar and
turn it into int8 to int8 comparison? If it does turn foo into an
int32, where does it get the memory? Compiler assign it a new
register? If so, is there a possibility that you run out of registers
if you have lot of comparisons of different sizes? Thanks.
\_ 1. How a person writes a program has no bearing on how it will
look like in the procedure stack. If a function is a leaf
function and uses less registers than is actually available then
there's no need for a new procedure stack. Where does it get the
memory? The compiler figures this out.
2. Yes, you can run out of registers. What's the solution?
It's called register allocation. There exists a myriad of
algorithms to deal with this issue. Take 164 and you'll learn
all about them. Not everything in a function fits in the register
ints means "store in register and allow the automatic sign
extension to happen". don't let the above comment make you
think that int8<>int32 comparisons are somehow less efficient.
file.
\_ Uh, 164 with Savage Sue barely touched on register allocation.
\_ C does type promotion. In this case, foo will end up being a
32-bit value that is the same, numerically, as the original
8-bit value.
\_ It creates a temporary int32 for the comparison. The temporary
value is normally stored in a register, but it will end up in
memory instead if you run out of registers.
\_ note that this doesn't mean shit in a modern architecture.
your registers are 32 bits wide at least already, so that
additional 24 bits are already wasted. type promotion of
ints is actually a noop in a modern architecture: it's already
stored as a sign extended 32 bit value. don't let the above
comment make you think that int8<>int32 comparisons are somehow
less efficient.
\_ They are less efficient. ALU operations don't automatically
sign extend 8-bit values in a register. You need to do that
separately. For example, on a Sun:
foo.c
-----
int foo(char c, int i) { return c + i; }
int bar(int i1, int i2) { return i1 + i2; }
when you compile this with the -S option the two functions
are almost the same except:
stb %o0, [%fp-17]
ldub [%fp-17], %o0
sll %o0, 24, %o1
sra %o1, 24, %o0
ld [%fp+72], %o1
used to perform the sign extension
\_ can you turn on -O and rerun this, please?
\_ Similar results, though much shorter. For both Sun
cc and gcc, foo produces a sll and sra by 24 but
not for bar. So yes, C promotion does incur overhead.
foo:
sll %o0, 24, %o0
sra %o0, 24, %o0
retl
add %o0, %o1, %o0
bar:
retl
add %o0, %o1, %o0
\_ i based my initial assertion on the fact that
many architectures provide a load byte instruction
which does sign extension on load to register. |