[LLVMdev] replacing GetElementPtrConstantExpr with GetElementPtrInst ... sometimes

Robert Lytton robert at xmos.com
Fri Aug 2 10:56:50 PDT 2013


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!

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<ConstantExpr>(*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<Value>(OpIt));
        cast<Value>(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<ValuePair>::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<Instruction>(*UI)) {
      dbgs() << "leave for backend error\n";
      return true;
  }
  return false;
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130802/916565a4/attachment.html>


More information about the llvm-dev mailing list