Accessing merged globals through PointerType

Hi,

I am trying to create a pass that is similar to the GlobalMerge code found here:
http://llvm.org/docs/doxygen/html/GlobalMerge_8cpp_source.html

I am concerned with lines 149-163 of the above file. From the documentation at the top of the file, it will convert this:

static int foo[N], bar[N], baz[N];

for (i = 0; i < N; ++i) {

foo[i] = bar[i] * baz[i];
}

Into something like this (slightly modified):

struct mergestruct {
int foo[N];
int bar[N];
int baz[N];
};

static struct mergestruct merged;
for (i = 0; i < N; ++i) {
merged.foo[i] = merged.bar[i] * merged.baz[i];
}

Great, now in addition I want to use an extra pointer to access the elements, like this:

struct mergestruct *merged_ptr = &merged;
for (i = 0; i < N; ++i) {
merged_ptr->foo[i] = merged_ptr->bar[i] * merged_ptr->baz[i];
}

So I add something like this after line 153:

PointerType *MergedPointerType = PointerType::get(MergedTy, 0);
GlobalVariable *MergedPointer = new GlobalVariable(M, MergedPointerType, false,
GlobalValue::ExternalLinkage, MergedGV, “_MergedGlobalsPtr”);

This is where I’m stuck. How can I use replaceAllUsesWith() to replace uses of each global with accesses through the new MergedPointer instead of through indices into the MergedGV struct as is currently done? Is this possible?

Thanks,
Rob

Hi Rob,

I am trying to create a pass that is similar to the GlobalMerge code found here:
http://llvm.org/docs/doxygen/html/GlobalMerge_8cpp_source.html

I am concerned with lines 149-163 of the above file. From the documentation at
the top of the file, it will convert this:

static int foo[N], bar[N], baz[N];

for (i = 0; i < N; ++i) {

   foo[i] = bar[i] * baz[i];
}

Into something like this (slightly modified):

struct mergestruct {
   int foo[N];
   int bar[N];
   int baz[N];
};

static struct mergestruct merged;
for (i = 0; i < N; ++i) {
   merged.foo[i] = merged.bar[i] * merged.baz[i];
}

Great, now in addition I want to use an extra pointer to access the elements,
like this:

struct mergestruct *merged_ptr = &merged;
for (i = 0; i < N; ++i) {
   merged_ptr->foo[i] = merged_ptr->bar[i] * merged_ptr->baz[i];
}

So I add something like this after line 153:

PointerType *MergedPointerType = PointerType::get(MergedTy, 0);
GlobalVariable *MergedPointer = new GlobalVariable(M, MergedPointerType, false,
   GlobalValue::ExternalLinkage, MergedGV, "_MergedGlobalsPtr");

This is where I'm stuck. How can I use replaceAllUsesWith() to replace uses of
each global with accesses through the new MergedPointer instead of through
indices into the MergedGV struct as is currently done? Is this possible?

if I understand right, you want everywhere that used the original global to
instead load the value stored in _MergedGlobalsPtr, and then use that instead?
For every instruction that uses the original global, you can try inserting a
load instruction before it, and replace that use with the load (be careful if
the global is used in a phi node, you will need to insert the load in the
incoming block, which becomes tricky if that block ends in an invoke). You
also need to take care of constant expressions that use the original global,
for example constant getelementptr expressions. For each instruction that uses
such an expression you will not only have to insert a load of MergedGlobalsPtr
before it, but also a sequence of instructions that performs the same operation
that the constant expression did.

That said, why do you want to do this?

Ciao, Duncan.