> [ Snip replacing globals with local vars ]
This is a relatively difficult transformation to prove safe... you
have to prove that the global is only used by instructions (directly
or indirectly) in one function (or possibly a group of functions with
a single entry point), the address of the global doesn't escape, the
value from the previous call to a function isn't used (by either
ensuring the value is set before used, or ensuring that the value is
set to a known constant when the function returns), and that there
isn't any unsafe recursion.
In general, I'm transforming global variables to struct alloca'd in the run()
function (which is our equivalent of the main() function). All other
functions will get an additional struct argument and return value, that
contains all the global variables. This seems to work pretty ok in general.
I've implemented most of the checks you mention, which means that variables
used in a gepconstantexpr aren't transformed (which is why I want to replace
The only check that I didn't implement is to check that the run function does
in fact dominate all uses of each global, but since we are only using this
pass after internalizing every function except run, this should work out.
I can't imagine any uses for a method like that besides a pass like
yours. (This method is essentially the opposite of
ConstantFoldInstruction, and is therefore usually the opposite of what
we want to do.) Anyone else have any ideas for uses?
Yeah, I couldn't find any other pass that does something similar either.
That said, it should be pretty simple to write recursively: first,
transform all the constants that use the current constant (this must
be possible due to the constraint that the global is only used by
instructions and transformable constants), second, build the value to
replace the constant (inserted in the entry block immediately after
all the allocas), and third, call replaceAllUsesWith on the constant.
Yeah, I was thinking along exactly those lines. However, I might not do a
replaceAllUsesWith, but just replace each individual use and return false if
not all uses could be replaced.
Or would it be better to first see if the constexpr is replaceable (by
recursively calling a CanReplaceWithInst method or similar) and only replace
something if it is possible?
The bulk of the code, of course, is building the value. In general,
it can take an arbitrary number of instructions to build a constant
(for example, if the constant is a ConstantStruct), so be careful not
to assume that a constant derivation maps to a single instruction.
Hmm, I hadn't though about constantstructs yet, but for consistency those
should probably be replaced by a chain of insertvalues as well.
The case for ConstantExpr is probably the longest, but there aren't
actually that many cases: you just have GetElementPtrInst, CastInst,
CmpInst, SelectInst, InsertValueInst, and ExtractValueInst (assuming
you wouldn't try to prove the legality for anything involving
ptrtoint). (Okay, that list ended up a bit longer than I expected,
but it still isn't that long.)
AFAICS all of those are pretty simple (only a single instruction). Only
ConstantStruct would end up emitting more than one instruction, but I've been
getting quite adept at emitting insertvalue chains by now :-p
I'll probably not get around to creating a patch until later this week, mainly
because we can live without supporting globals that result in gepconstantexprs
for at least a while.