Break constant GEPs

Viewed 43

I need to break constant GEPs. I found an old BreakConstantGEPs pass and I try to use it with newer LLVM version. For the code:

int tab[1]={1};
void fun() 
{
    int val=tab[0];
}

without performing pass I get the following .ll file:

@tab = dso_local global [1 x i32] [i32 1], align 4

; Function Attrs: noinline nounwind optnone uwtable
define dso_local void @mult() #0 {
  %1 = alloca i32, align 4
  %2 = load i32, i32* getelementptr inbounds ([1 x i32], [1 x i32]* @tab, i64 0, i64 0), align 4
  store i32 %2, i32* %1, align 4
  ret void
}

Then I perform the pass. GEP is properly recognized. Here I present most important parts of the pass (full code in link above).

Creating new GEP instruction:

GetElementPtrInst::CreateInBounds(CE->getOperand(0), Indices, CE->getName(), InsertPt) //in original code GetElementPtrInst::Create() is used 

Replacing:

I->replaceUsesOfWith (CE, NewInst);
I->removeFromParent();

Unfortunately, the module verifier outputs errors:

Instruction referencing instruction not embedded in a basic block!
  %2 = getelementptr inbounds [1 x i32], [1 x i32]* @tab, i64 0, i64 0
  <badref> = load i32, i32* %2, align 4
Instruction does not dominate all uses!
  <badref> = load i32, i32* %2, align 4
  store i32 <badref>, i32* %1, align 4
in function fun
LLVM ERROR: Broken function found, compilation aborted!

What am I doing wrong?

1 Answers

Remove I->removeFromParent(); and it should work.

LLVM uses linked lists to represent most of its data, a Module holds global values (global variables, aliases and functions) in a linked list, a Function holds basic blocks in a linked list, and BasicBlock holds Instructions in a linked list. Thinking about this as memory ownership, the Instruction is owned by the BasicBlock and will be deleted when the BasicBlock is deleted. If you delete a Function then it will delete all the BasicBlocks it owns, which deletes all the Instructions and so on. We use linked lists instead of vectors in order to make moving instructions less expensive, you can hoist an instruction by detaching it from its parent basic block, and inserting it elsewhere.

When you created the instruction with GetElementPtrInst::CreateInBounds([...], InsertPt) you created a new getelementptr instruction and it was inserted in your code at the InsertPt insertion point (just any other instruction will do). Perfect.

Then you called I->removeFromParent() which removes the instruction from its basic block. It still exists as a C++ object but it has no parent basic block, it does not belong to any block or function or module, it never runs. Why did you do that? You probably didn't mean to do that. Or maybe you wanted to insert it somewhere other than the InsertPt?

Related