replacing a global variable by a constant

Hi,

I am trying to replace a global variable with a constant.
I did manage to do it, but somehow it appears to be fairly bruteforce by
just iterating over all functions/bblocks/instructions and filtering for
those that load the variable and replacing the instruction with
Instruction::replaceAllUsesWith().
The more intuitive way of iterating over the uses of the variable did
not work out as I have to replace the whole instruction instead of just
the operand (as GlobalVariable::replaceAllUsesWith() does) in order to
prevent loading from the memory address of the constant instead of
loading the constant :p. Basically what seems to be missing is some
method that returns the parent-instruction of a Use.

Maybe I am even tackling the whole problem from the wrong side anyway?!

And another question:
Does an invokation of a JIT through runFunction() perform any
optimization(s) by itself? Is there a way to display the generated code?

Thank you in advance :).

Regards,
Ralf

Hi Ralf,

I am trying to replace a global variable with a constant.

You should be able to replace the initializer for the global with your
constant, mark it as having internal linkage and then run some optimization
pass over it to do the rest (not sure which one it was again, probably some
constant propagation or global value optimization).

That pass would then probably do some similar iterating as you've described,
but at least you won't have to maintain that part of code :slight_smile:

I did manage to do it, but somehow it appears to be fairly bruteforce by
just iterating over all functions/bblocks/instructions and filtering for
those that load the variable and replacing the instruction with
Instruction::replaceAllUsesWith().
The more intuitive way of iterating over the uses of the variable did
not work out as I have to replace the whole instruction instead of just
the operand (as GlobalVariable::replaceAllUsesWith() does) in order to
prevent loading from the memory address of the constant instead of
loading the constant :p. Basically what seems to be missing is some
method that returns the parent-instruction of a Use.

You can use Use::getUser(), which returns a User (from which Instruction and
LoadInst derive). Note that you will have to accoutn for other uses than Loads
(such as the initializers of other globals), but in those cases your
transformation can probably not proceed anyway.

Does an invokation of a JIT through runFunction() perform any
optimization(s) by itself?

I don't thinks so, not sure.

Is there a way to display the generated code?

No clue :slight_smile:

Gr.

Matthijs

Thanks a lot for your help Matthijs! :slight_smile:

basically this does the job quite nicely I think:
for (llvm::GlobalVariable::use_iterator U = gv->use_begin(); U !=
gv->use_end(); ++U) {
    llvm::Instruction *I = llvm::cast<llvm::Instruction>(U);
    I->replaceAllUsesWith(constPtr);
    I->eraseFromParent();
}

Cheers,
Ralf

Matthijs Kooijman wrote:

Thanks a lot for your help Matthijs! :slight_smile:

basically this does the job quite nicely I think:
for (llvm::GlobalVariable::use_iterator U = gv->use_begin(); U !=
gv->use_end(); ++U) {
   llvm::Instruction *I = llvm::cast<llvm::Instruction>(U);
   I->replaceAllUsesWith(constPtr);
   I->eraseFromParent();
}

You're deferencing an invalidated iterator here. Try this:

for (llvm::GlobalVariable::use_iterator U = gv->use_begin(); U != gv- >use_end(); ) {
    llvm::Instruction *I = llvm::cast<llvm::Instruction>(U++);
    I->replaceAllUsesWith(constPtr);
    I->eraseFromParent();
}

Even this is not guaranteed to work depending on if an instruction can use the global more than once (think a call instruction).

If you know that all users are loads, the edited code above should work.

-Chris