Robert Lytton
2013-Aug-02 17:56 UTC
[LLVMdev] 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... <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>
Eli Friedman
2013-Aug-02 18:14 UTC
[LLVMdev] replacing GetElementPtrConstantExpr with GetElementPtrInst ... sometimes
On Fri, Aug 2, 2013 at 10:56 AM, Robert Lytton <robert at xmos.com> wrote:> 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
Maybe Matching Threads
- [LLVMdev] GetElementPtrConstantExpr question
- [LLVMdev] Pulling line number/file/path information from DbgStopPointInst instructions
- [LLVMdev] How to get the indices in an getelementptr Value?
- [LLVMdev] <badref> showed up when duplicating a list of dependent instructions
- [LLVMdev] <badref> showed up when duplicating a list of dependent instructions