RFC: Constant Creation API

So, as you all probably noticed, the APIs for creating constants have been moved (or in a specific cases, are about to be moved) from static methods on Constant to instance methods on LLVMContext.

However, as was recently pointed out on llvm-commits and on IRC, this is no longer strictly necessary. Because types have contexts, all of the constant subclasses could be friended to LLVMContext, and then put the work of uniquing by accessing the context off of the type.

There are obviously some pros and to both approaches. Going back to the old-style increases compatibility with 2.5, and breaks up the massive LLVMContext class. On the downside, it would cause massive thrashing on TOT, because I will have to revert about two weeks worth of commits in widely dispersed parts of the tree, and because a number of clients have already switched to the new TOT API.

Any comments and/or opinions on this decision are welcome.

--Owen

Unless there is a good reason not to, I think that sticking to the LLVM 2.5-style of APIs makes sense.

-Chris

This also works for several of the Type classes, since many of them
take another type in their constructors. Functions, arrays, pointers,
vectors, and all structs except the empty one can pull the Context out
of one of their nested types. On the other hand, consistency may argue
for putting all type creators in one place.

Jeffrey

Chris Lattner wrote:

  
Unless there is a good reason not to, I think that sticking to the LLVM 2.5-style of APIs makes sense.
  
Oh no! :slight_smile: Can't you keep both APIs?

Nicolas

Chris Lattner skrev:

Unless there is a good reason not to, I think that sticking to the LLVM 2.5-style of APIs makes sense.

-Chris

Yes, please!

/Another api-in-flux-victim

srs wrote:

Chris Lattner skrev:

Unless there is a good reason not to, I think that sticking to the
LLVM 2.5-style of APIs makes sense.

Yes, please!

+1

Hi,

1 vote in favour of sticking with the 2.5 API

Mark.

Owen Anderson wrote:

I hate to say it (because I already made the changes), but keeping compatibility with 2.5 is a good thing.

-Rich

Owen Anderson wrote:

Yeah, for us who have already made the changes, this is kinda bitter sweet.

Maurice

The ones that don't can be static functions on the type class that take a context. For example, Type::Int32Ty needs to become a function that takes a context at some point.

-Chris

The ones that don't can be static functions on the type class that take a context. For example, Type::Int32Ty needs to become a function that takes a context at some point.

Why is that? If it is read-only then it should be possible to share
it between all threads.

Ciao,

Duncan.

Type's aren't readonly, see all the mutable fields in them. While we might be able to get away with a special case for these, I'd rather have a clean model where no IR is shared across contexts.

-Chris

If the 2.5 APIs are okay, then I also vote for sticking with them.

-bw

Hi,

The ones that don’t can be static functions on the type class that
take a context. For example, Type::Int32Ty needs to become a
function
that takes a context at some point.

Why is that? If it is read-only then it should be possible to share
it between all threads.

Type’s aren’t readonly, see all the mutable fields in them. While we
might be able to get away with a special case for these, I’d rather
have a clean model where no IR is shared across contexts.

I’m sorry if I am being dense so please bear with me.

Assuming that I have a threaded JIT server which has an llvmContext object
on the stack of every JITting thread in the server.

When using the 2.5. API like:

C = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);

I need to assume that there exists some global llvmContext object which holds
the predefined llvm types.

Does this entail that in my threaded server I need to create new types for
llvm::Type::Int32Ty and the like, which are associated with the llvm::Context on the stack?
Or will things work correctly when mixing values created using the global
context and other stuff created using the context object on the stack of threads?

I guess that I am trying to say that it seems to me that the 2.5 API is more
prone to synchronization issues than the interim 2.6 version of the API.
The reason for this assumtion is that it seemed clear which context
object governed the lifetime of all llvm related objects.

So why not support the newer interim 2.6 API as well?

Anybody willing to spell out what the rules will be for using
LLVM for multi-threaded JITting?

Thanks.

Kind regards,
Maurice

Yes, you’ll have to write something like:

C = llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);

-Chris

Assuming that I have a threaded JIT server which has an llvmContext object
on the stack of every JITting thread in the server.

When using the 2.5. API like:

C = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0);

I need to assume that there exists some global llvmContext object which holds
the predefined llvm types.

Does this entail that in my threaded server I need to create new types for
llvm::Type::Int32Ty and the like, which are associated with the llvm::Context on the stack?

Yes, you’ll have to write something like:

C = llvm::ConstantInt::get(llvm::Type::getInt32Ty(Context), 0);

Ok, Thanks.

Kind regards,
Maurice

Hi Owen,

What if I want to have global llvm::Type's, that can be used by many LLVMContext's. For example, I'd like to have one LLVMContext per function, and be able to create constants that belong to the context but using a global, shared amongst LLVMContext's, llvm::Type.

I know that's not doable right now, but aren't we losing this possibility if we move back to the old static functions?

Thanks,
Nicolas

Owen Anderson wrote:

Nicholas,

What if I want to have global llvm::Type’s, that can be used by many
LLVMContext’s. For example, I’d like to have one LLVMContext per
function, and be able to create constants that belong to the context
but using a global, shared amongst LLVMContext’s, llvm::Type.

I know that’s not doable right now, but aren’t we losing this
possibility if we move back to the old static functions?

That wasn’t going to be possible with the methods-on-LLVMContext either. The Type uniquing tables will be moving onto the context for similar reasons to the Constant ones, though we will make an effort to preserve the existing APIs.

I’m not sure I understand your goal with having one context per function. In general, each Module can have its own context, but functions within the same module need to have the same one, so that function types compare correctly, and so that constants in globals work properly. Trying to get around this is likely to cause screwy results, as things that should compare as equal won’t.

Hope that helps,

–Owen

Yes, definitely. The more stability across releases, the better.

                         -Dave

Owen Anderson wrote:

That wasn't going to be possible with the methods-on-LLVMContext either. The Type uniquing tables will be moving onto the context for similar reasons to the Constant ones, though we will make an effort to preserve the existing APIs.

OK.

I'm not sure I understand your goal with having one context per function.

The goal is to remove all constants created during IR creation of a function, once the function has been JITted. For example, after the function has been JIIted, I can call llvm::Function->deleteBody, that will delete the instructions in the function. But all llvm::Constants created by the function will remain in memory. If I could attach a LLVMContext per function to create the constants, I would be able to delete all constants created for the function's body by deleting the LLVMContext.

Does that make sense?

I know that this disables any IPO, but I'm currently more interested into memory savings than optimizations.

Nicolas