From: Chris Wilson <cwilson@CS.Stanford.EDU>
Date: Fri, 22 Mar 96 18:43:56 PST
Subject: Re: Newbie II
Message-Id: <CMM.0.90.4.827549036.cwilson@Xenon.Stanford.EDU>
> > More basic front-end questions
> >
> > . I've tried a few C case statements and found they don't get snooted
> > into io_mbr instructions as I expected. What sort of case statements will
> > cause the mbr to be used?
>
> Try making more complicated switch statements. If they're too simple,
> snoot is smart enough to translate them to if-then-elses instead of
> multiway branches.
The way snoot handles switches is retained from the algorithm lcc
uses, with the modification that where lcc would use a lookup-table
for the branch, snoot uses an mbr instruction. See the swgen()
function in snoot/stmt.cc. Roughly, it uses a cutoff density of
targets in a range to decide whether or not to use an mbr instruction.
The cutoff density defaults to 50% but can be changed by a
command-line argument. If the density is less, it breaks up the
range, uses if-then-else's, and recursively tries using mbrs on
sub-ranges if they meet the density requirements. So you can end up
with arbitrarily complex constructs for a single switch statement.
Another point about switch statements is that they usually end up with
an unnecessary indirection of most cases, i.e. a branch to an
unconditional jump statement. ``porky -ucf-opt'' should be run to get
rid of the unnecessary branching, if you really care about the code
being generated by the switch statement.
> > . Ditto for memcpy. What C constructs result in its use?
>
> Assignments and copies of structures.
Actually, assignments and copies of structures use copy instructions,
just like assignments and copies of data of any other type, whenever
the copies are between var_syms. As with any other type, loads,
stores, and memcpy instructions are only used when the assignments are
indirect, through explicit use of pointers.
The way snoot handles memcpy instructions is as a post-pass: anything
that would otherwise produce a load-store pair (the result of a load
being used immediately as the source of a store with no type change)
is automatically converted to a memcpy. Snoot handles structures
exactly the same way as any other types in this respect.
> > . Am curious why immeds built from large unsigned ints get stored
> > as ext_integer rather than regular int. Conversion to and from
> > ext_int's string format is invisible, but slower than native integer
> > operations. What problem is ext_int solving? Isn't a flag sufficient
> > to identify numbers that don't fit in a signed int?
>
> The extended integers address the more general problem of representing
> numbers that are too big for the native integer size. This is usually
> only an issue for cross compiling. Since we have the more general
> mechanism already, it's easy to use it to handle large unsigned ints.
> You are right that a flag would be sufficient (and more efficient as well).
It's for historical reasons that this approach is used. Originally,
SUIF only had ``int'' immeds. We added the ext_integer immeds, as Bob
said, as a general way to handle numbers that don't fit in the native
integer size. Since this handles unsigneds with the high bit
correctly, too, adding an additional new way of handling these big
unsigneds didn't seem worth it -- it would cause more incompatibility
with existing code just to make things more efficient for the case of
unsigneds with the high bit set. The conversion to native
``unsigned'' is, as you said, automatic, so a small efficiency hit is
the only cost.
> > . I noticed that snoot added a dummy return value to an integer function
> > that I neglected to give a return value for. Rather nice of it! Got
> > me wondering if all modern compilers either do as snoot does, or give
> > an error message as my Visual C++ does.
>
> C++ is more strict than C in this regard. I'm sure that almost all
> C compilers will do the same thing as snoot (with warning messages).
> It would be strange to say that "all modern compilers" do this, since
> it's actually a holdover from pre-ANSI C.
ANSI says that if no value is returned and the caller actually uses
the value, the value it gets is undefined, but if the value is not
used it's perfectly legal. That is, of course, meant to allow most
old K&R C programs that used ``int'' where they really wanted
``void'', to remain perfectly legal in ANSI C. So modern compilers
have to do something correct for this case.
For the compiler writer, it's often better to have simpler, stricter
rules. So in SUIF we require all procedures to end with return
statements, and the expression for a return statement to have the same
type as the return type of the function. Snoot silently fixes up
programs that don't meet the SUIF requirements because this is
something that can easily be done automatically. Which means that the
writer of a SUIF pass doesn't have to consider as many cases.
> > . sym_addr offsets are unsigned. Pointer arithmetic on sym_addrs can
> > cause the offset to underflow (in the case of flawed input programs),
> > yielding a bogus address. I believe ANSI C allows pointers to extend
> > one location below and above a block. Array instructions, in contrast,
> > do compute addresses, yet their parameters are ints. While not a big deal,
> > this seems inconsistent. Comments?
>
> The sym_addr offsets are used for direct field references only.
> Pointer arithmetic must be represented by (surprise!) arithmetic
> instructions. You're comparing apples and oranges here.
>
> --Bob
Actually, this isn't quite true either.
For one thing, sym_addrs are the only thing SUIF currently allows as
static intializers. In C, you can have something like:
static int x[100];
static int *y = &x[-1];
and the ``&x[-1]'' has to be turned into a sym_addr. In fact, the way
ANSI C defines what is legal for static initialization is very close
to what a sym_addr gives: an address of something else static and an
offset. So it is a really flaw in SUIF that sym_addr offsets are
``unsigned'' numbers of bits. Not only are negative offsets not
supported, but large offsets also are not -- since the offset is in
bits, not bytes, on a 32 bit machine, you only get 29 bits of address
space supported in offsets. This impacts SUIF's ability to deal with
some real programs.
In fact, sym_addrs in SUIF are legal shorthand for any address and
offset, and porky's constant folding will fold pointer arithmetic into
ldc's of sym_addrs wherever overflow will not occur. If overflow
would occur, explicit pointer arithmetic is used instead. It is the
static initialization that is the real problem with sym_addrs.
--Chris
From: Nelson Teru Minoura <minoura@lsi.usp.br>
Date: Thu, 21 Mar 1996 11:15:41 -0300
Subject: Generating libruntime_sgi for mips-1
Message-Id: <199603211415.LAA19069@ofelia>
Dear Chris,
Sorry to ask again, but have you already discovered where the functions
Simcp0_ll and Simcp0_sc are ? I need them to build a Mips-1 version of
libruntime_sgi.a.
Thanks in advance for any help.
-Nelson T Minoura
(minoura@lsi.usp.br)
(http://www.lsi.usp.br/~phoenix)
From: Bob Wilson <bwilson@shasta.Stanford.EDU>
Date: Fri, 22 Mar 96 9:39:29 PST
Subject: Re: Newbie II
Message-Id: <199603221739.JAA22540@shasta.Stanford.EDU>
> More basic front-end questions
>
> . I've tried a few C case statements and found they don't get snooted
> into io_mbr instructions as I expected. What sort of case statements will
> cause the mbr to be used?
Try making more complicated switch statements. If they're too simple,
snoot is smart enough to translate them to if-then-elses instead of
multiway branches.
> . Ditto for memcpy. What C constructs result in its use?
Assignments and copies of structures.
> . Am curious why immeds built from large unsigned ints get stored
> as ext_integer rather than regular int. Conversion to and from
> ext_int's string format is invisible, but slower than native integer
> operations. What problem is ext_int solving? Isn't a flag sufficient
> to identify numbers that don't fit in a signed int?
The extended integers address the more general problem of representing
numbers that are too big for the native integer size. This is usually
only an issue for cross compiling. Since we have the more general
mechanism already, it's easy to use it to handle large unsigned ints.
You are right that a flag would be sufficient (and more efficient as well).
> . I noticed that snoot added a dummy return value to an integer function
> that I neglected to give a return value for. Rather nice of it! Got
> me wondering if all modern compilers either do as snoot does, or give
> an error message as my Visual C++ does.
C++ is more strict than C in this regard. I'm sure that almost all
C compilers will do the same thing as snoot (with warning messages).
It would be strange to say that "all modern compilers" do this, since
it's actually a holdover from pre-ANSI C.
> . sym_addr offsets are unsigned. Pointer arithmetic on sym_addrs can
> cause the offset to underflow (in the case of flawed input programs),
> yielding a bogus address. I believe ANSI C allows pointers to extend
> one location below and above a block. Array instructions, in contrast,
> do compute addresses, yet their parameters are ints. While not a big deal,
> this seems inconsistent. Comments?
The sym_addr offsets are used for direct field references only.
Pointer arithmetic must be represented by (surprise!) arithmetic
instructions. You're comparing apples and oranges here.
--Bob
From: BROYLES@maven.dnet.teradyne.com
Date: Fri, 22 Mar 1996 09:08:36 -0500 (EST)
Subject: Newbie II
Message-Id: <01I2MTVHUL36002UPU@A1GATE.TERADYNE.COM>
More basic front-end questions
. I've tried a few C case statements and found they don't get snooted
into io_mbr instructions as I expected. What sort of case statements will
cause the mbr to be used?
. Ditto for memcpy. What C constructs result in its use?
. Am curious why immeds built from large unsigned ints get stored
as ext_integer rather than regular int. Conversion to and from
ext_int's string format is invisible, but slower than native integer
operations. What problem is ext_int solving? Isn't a flag sufficient
to identify numbers that don't fit in a signed int?
. I noticed that snoot added a dummy return value to an integer function
that I neglected to give a return value for. Rather nice of it! Got
me wondering if all modern compilers either do as snoot does, or give
an error message as my Visual C++ does.
. sym_addr offsets are unsigned. Pointer arithmetic on sym_addrs can
cause the offset to underflow (in the case of flawed input programs),
yielding a bogus address. I believe ANSI C allows pointers to extend
one location below and above a block. Array instructions, in contrast,
do compute addresses, yet their parameters are ints. While not a big deal,
this seems inconsistent. Comments?