replacing GetElementPtrConstantExpr with GetElementPtrInst ... sometimes

Hi

During a pass, the XCore target lowers thread local global variables by turning them into global variable arrays indexed by the (max 8) thread ID.
(see XCoreLowerThreadLocal.cpp)

This works fine for instructions e.g. GetElementPtrInst
But can’t be done for constants e.g. GetElementPtrConstantExpr

Thus I would like to replace GetElementPtrConstantExpr with GetElementPtrInst when it is accessing a thread local global variable.
(Other constant expression ignored for now).

My attempt (example code below) has revealed my lack of understanding of llvm.
For one thing I need to distinguish when the GetElementPtrConstantExpr is a child of an instruction and hence can be changed into an instruction itself.

When offered:
@tl = external thread_local global [1 x i32]
define i32* @tli () {
ret i32* getelementptr([1 x i32]* @tl, i32 0, i32 0)
}
the example code prints:
@tl = external thread_local global [1 x i32]
ConstantExpr ops…
@tl = external thread_local global [1 x i32]
i32 0
i32 0
Replace…
i32* getelementptr inbounds ([1 x i32]* @tl, i32 0, i32 0)
with…
= getelementptr inbounds [1 x i32]* @tl, i32 0, i32 0
leave for backend error
Instruction does not dominate all uses!
= getelementptr inbounds [1 x i32]* @tl, i32 0, i32 0
ret i32*
Broken module found, compilation aborted!

Q: Is my approach generally correct?
I am also concerned that:
@i = constant i32* getelementptr ([1 x i32]* @tl, i32 0, i32 0)
must be skipped and not replaced.
Hence ‘replaceAllUsesWith’ is a bad idea!

I plan to explore the parent node next to verify its type and replace its GetElementPtrConstantExpr operand if it is an instruction.
Q: Is this the right direction?

Thank you.

Robert

namespace { struct ValuePair { Value * CE; Value * Inst; }; }

static bool hasNonInstructionUse(GlobalVariable GV) {
// first try to replace GetElementPtrConstantExpr with GetElementPtrInst
SmallVector<ValuePair,4> Replace;
for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E; ++UI) {
ConstantExpr * CE = dyn_cast(UI);
if ( CE && CE->getOpcode() == Instruction::GetElementPtr) {
dbgs() << “ConstantExpr ops…\n”;
SmallVector<Value
,4> OpVec;
for (ConstantExpr::op_iterator OpIt = CE->op_begin(), E = CE->op_end(); OpIt != E; ++OpIt) {
OpVec.push_back(cast(OpIt));
cast(OpIt)->dump();
}
ArrayRef<Value
> Ops(OpVec);
Instruction * NewInst = GetElementPtrInst::CreateInBounds(Ops[0], Ops.slice(1), CE->getName() );
ValuePair vp = {CE,NewInst};
Replace.push_back(vp);
}
}
for (SmallVectorImpl::const_iterator I = Replace.begin(),
E = Replace.end();
I != E; ++I) {
dbgs() << “Replace…\n”; I->CE->dump();
dbgs() << “with…\n”; I->Inst->dump();
I->CE->replaceAllUsesWith(I->Inst);
}

// we can’t lower non instruction - leave to error later
for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E; ++UI)
if (!isa(*UI)) {
dbgs() << “leave for backend error\n”;
return true;
}
return false;
}

Hi

During a pass, the XCore target lowers thread local global variables by
turning them into global variable arrays indexed by the (max 8) thread ID.
(see XCoreLowerThreadLocal.cpp)

This works fine for instructions e.g. GetElementPtrInst
But can't be done for constants e.g. GetElementPtrConstantExpr

Thus I would like to replace GetElementPtrConstantExpr with
GetElementPtrInst when it is accessing a thread local global variable.
(Other constant expression ignored for now).

My attempt (example code below) has revealed my lack of understanding of
llvm.
For one thing I need to distinguish when the GetElementPtrConstantExpr is a
child of an instruction and hence can be changed into an instruction itself.

When offered:
    @tl = external thread_local global [1 x i32]
    define i32* @tli () {
        ret i32* getelementptr([1 x i32]* @tl, i32 0, i32 0)
    }
the example code prints:
    @tl = external thread_local global [1 x i32]
    ConstantExpr ops...
    @tl = external thread_local global [1 x i32]
    i32 0
    i32 0
    Replace...
    i32* getelementptr inbounds ([1 x i32]* @tl, i32 0, i32 0)
    with...
      <badref> = getelementptr inbounds [1 x i32]* @tl, i32 0, i32 0
    leave for backend error
    Instruction does not dominate all uses!
      <badref> = getelementptr inbounds [1 x i32]* @tl, i32 0, i32 0
      ret i32* <badref>
    Broken module found, compilation aborted!

Q: Is my approach generally correct?
I am also concerned that:
    @i = constant i32* getelementptr ([1 x i32]* @tl, i32 0, i32 0)
must be skipped and not replaced.
Hence 'replaceAllUsesWith' is a bad idea!

This isn't legal IR given that tl is thread-local: what would it even mean?

I plan to explore the parent node next to verify its type and replace its
GetElementPtrConstantExpr operand if it is an instruction.
Q: Is this the right direction?

You're going to need something a lot more complicated: in the general
case, you need to split critical edges if there's a reference to the
global in an operand to a PHI nodes. ISel already has a bunch of
utilities for handling that sort of thing; you might want to consider
putting your lowering there instead.

-Eli