[LLVMdev] Plans considering first class structs and multiple return values

Matthijs Kooijman matthijs at stdin.nl
Mon Jun 9 01:31:07 PDT 2008


Hi Chris,

On Sat, Jun 07, 2008 at 02:59:03PM -0700, Chris Lattner wrote:
> On Jun 2, 2008, at 1:03 PM, Matthijs Kooijman wrote:
> >> Can you give some background about what kinds of things you're  
> >> thinking
> >> about for this?
> > For example, when I have a function returning {i32, i32} and I want  
> > to add
> > another i32 to that. If this was a function that simply returns two  
> > i32
> > values, any caller will only use extractvalue on the result to get the
> > seperate values (since the struct as a whole has no meaning). In  
> > this case, I
> > can make the function return {i32, i32, i32}, add an extra  
> > extractvalue in
> > each caller and be done.
> 
> This can't really work in either case.  Once created, there is no way  
> to change the type of a Value*.  Changing the result of a call from  
> {i32, i32} to {i32, i32, i32} is just as impossible as changing it  
> from {i32,i32} to i32.  You have to create a new callinst in either  
> case.
By "Changing the return type", I meant "Create a new function with a changed
return type and updating all calls". The argument still holds, that this is
easier to do in some cases than others.


> > { {i32, i32}, i32}, which means we get something like:
> >
> > 	%tmp = @foo () ; { {i32, i32}, i32}
> > 	%complex  = extractvalue { {i32, i32}, i32} %tmp, 0
> > 	@bar ( {i32, i32 } %complex)
> 
> Why would you ever want to pass multiple values as an aggregate to a  
> call?  The only thing I can think of is for ABI reasons.  If you can  
> do an ABI changing transformation (such as you propose) the first  
> thing I'd do is  expand the aggregate to pass as a series of scalars.   
> Having argpromotion do this would be very natural.
I was just using @bar to show that the complex struct is used as-is somewhere,
so it can't be broken up completely. In this particular case, it could be that
@foo() is internal (and thus can be changed) but @bar is external and has to
be kept unchanged.

Anyway, it was just an example.

In practice, just taking whatever the function is returning now, and put that
into a struct together with whatever you want to add and then letting other
passes make something pretty out of the resulting extractvalue/insertvalue
forest will work just fine.

> After MRVs are working really well, I'd like to consider removing the  
> void type:
> http://nondot.org/sabre/LLVMNotes/EliminatingVoid.txt
> 
> This would make it so that calls always return a value, and 'ret'  
> always takes a value.  This would be a nice simplification to the IR I  
> think.
Doing this will make functions returning a single value stand out even more,
since a function returning 0 or more than 1 values will always return a
struct, while a function returning 1 value will just return that value. Don't
think this is really a problem, though.

> If you're using IRBuilder, why not just add a new CreateBuildMRV  
> method that inserts the sequence of insertvalue's for you?
Hmm, that would actually make sense I guess. I'm not currently using
IRBuilder, but I might move some code into there.

> stretpromotion was really just for testing.  I expect that when MRVs  
> work predictably 100% of the time (even if not something the ABI  
> supports, for example) that the functionality will be pulled into the  
> argpromotion pass.
Will sretpromotion still be needed? If the frontends would generate functions
returning a struct directly instead of using an sret argument, sret could
perhaps be removed alltogether? Though I guess there is an ABI difference
between using sret and returning a structure directly?

Gr.

Matthijs
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20080609/845b4de8/attachment.sig>


More information about the llvm-dev mailing list