Error Calling eraseFromParent()

Hi.
This is part of my code:

if (auto* op = dyn_cast(&I)) {

Value* lhs = op->getOperand(0);
Value* rhs = op->getOperand(1);
Value* mul = builder.CreateMul(lhs, rhs);

for (auto& U : op->uses()) {
User* user = U.getUser();
user->setOperand(U.getOperandNo(), mul);
}

I.eraseFromParent();
}

This leads to the following runtime error:

LLVMSymbolizer: error reading file: No such file or directory

Does anybody know the solution?
Regards.

LLVMSymbolizer is invoked while trying to pretty-print a crash backtrace. “error reading file” suggests that you are on Windows and it cannot find the .pdb file with symbol information.

If that’s the case, are you doing either a Debug or RelWithDebInfo build? If you are, I don’t know what else to suggest.

Note that LLVMSymbolizer is trying to make the traceback more understandable; it has nothing to do with the cause of your problem. If you are triggering an assertion, the assertion message should tell you where that is. (You did run cmake with –DLLVM_ENABLE_ASSERTIONS=ON, right?) If not, likely you are dereferencing a null pointer somewhere. Personally I debug with ‘printf’ statements, but that’s just me.

–paulr

The code is really simple. But I can not the reason for the segmentation fault. I only know that the eraseFromParent() function leads to it. The whole code is:

bool runOnFunction(Function &F) override {

for (auto &I : instructions(F)) {

if (auto* op = dyn_cast(&I)) {
IRBuilder<> builder(op);

Value* lhs = op->getOperand(0);
Value* rhs = op->getOperand(1);
Value* mul = builder.CreateMul(lhs, rhs);

for (auto& U : op->uses()) {
User* user = U.getUser();
user->setOperand(U.getOperandNo(), mul);
}

I.eraseFromParent();
}

}

And I think that the code worked well with LLVM-3.6.0 that I tested one year ago. Now, I use LLVM-6.0.0.
Regards.

It looks quite dangerous to erase the instruction I inside the loop when iterating over all instructions in the function.
I guess it depends on how the range based iterator is implemented if that works or not.

I think that you, for example, can change the range based iteration

   for (auto &I : instructions(F))

into something like this

   for (inst_iterator It = inst_begin(&F), Ie = inst_end(&F); It != Ie;) {
      Instruction *I = &*(It++);
      ...
    }

That will make sure that you step the iterator before modifying the data structure you iterate over.

Regards,
Björn

Thanks Bjorn! But The problem is still there.

Hi:
As stated in the documentation you shouldn’t modify it while iterating as this invalidates the iterator. Try save the pointers to a vector outside your loop and perform erasing in a new loop following your current one.

Zhang

Hi. Thanks. I changed the code but the problem exists. This is my new code which is again very simple:


bool runOnFunction(Function &F) override {

vector<Instruction *> dels;
dels.clear();

for (inst_iterator It = inst_begin(&F), Ie = inst_end(&F); It != Ie;) {
Instruction I = &(It++);

if (auto* op = dyn_cast(I)) {
IRBuilder builder(op);

Value* lhs = op->getOperand(0);
Value* rhs = op->getOperand(1);
Value* mul = builder.CreateMul(lhs, rhs);

for (auto& U : op->uses()) {
User* user = U.getUser();
user->setOperand(U.getOperandNo(), mul);
}
//I->eraseFromParent();
dels.push_back(I);
}
}

for (auto &I : dels) {
I->eraseFromParent();
}

Hmmmm that’s strange. Do you get an assert when you build LLVM with this code in Debug Mode or is it simply null pointer dereference?
On a side note, usually when doing transforms similar to yours I use IRBuilder’s CreateXXX followed by a ReplaceInstWithInst which works perfectly fine for me.

Zhang

LLVM is built in Release mode. The version is 6.0.0. I think that a similar code worked on verison 3.9.0. It is probably a null pointer dereference occurring in eraseFromParent(). I checked and reconfirmed that the instruction had no uses. Perhaps I should rebuild LLVM. Thanks.

Hmmmm.
One more guess is that since you used IRBuilder to insert new Instructions, you are still actually modifying the BB and thus invalidated the iterator. I just picked up some old work regarding this and in my example I just wrote something like this:

if (BinaryOperator *BO = dyn_cast(Inst)) {
BinaryOperator *newBO = llvm::BinaryOperator::Create(newOp, BO->getOperand(0),BO->getOperand(1));
llvm::ReplaceInstWithInst(BO, newBO);
}

Sorry for the bad formatting, I typed this on mobile. Hope this helps : )

Zhang

Ahmad,

I would highly recommend, at least if you are running into problems, that
debug using asserts enabled. This will (most of the time) give you a better
"explanation" as to what you've done wrong. Not every time, but for many of
the "we expect someone to get this wrong at some pont" type of problems.

Trying to figure out why something failed in a release build without
asserts is often painfully hard, because when you crash, the "reason" for
the crash is in code that has been inlined, the actual understanding of
what went wrong is several layers of calls above the crash-point.

Well, the problem was with the LLVM build. I re-extracted the sources and recompiled the whole tool and then SegFaul disappeared! :smiley:
Many Thanks all you guys especially Zhang!