[LLVMdev] Are instr_iterators invalidated when function inlining is performed?

David Blaikie dblaikie at gmail.com
Fri Aug 30 08:25:36 PDT 2013


On Fri, Aug 30, 2013 at 7:53 AM, Daniel Liew <daniel.liew at imperial.ac.uk> wrote:
> Hi,
>
> I'm trying to write a small piece of code that inlines all calls to a
> particular function. The codes is as follows
>
>   Function* klee_check_divF = module->getFunction("klee_div_zero_check");
>   assert(klee_check_divF != 0 && "Failed to find klee_div_zero_check function");
>   // Hack inline checks
>   for (Module::iterator f = module->begin(), fe = module->end(); f != fe; ++f) {
>     for (inst_iterator i=inst_begin(f), ie = inst_end(f); i != ie; ++i) {
>       if ( CallInst* ci = dyn_cast<CallInst>(&*i) )
>       {
>         if ( ci->getCalledFunction() == klee_check_divF)
>         {
>             std::cout << "Trying to inline klee_div_zero_check" << std::endl;
>             InlineFunctionInfo IFI(0,0);
>             if (InlineFunction(ci,IFI))
>             {
>               std::cout << "Did inline" << std::endl; std::cout.flush();
>             }
>             else
>               std::cout << "Failed to inline" << std::endl;
>         }
>       }
>
>     }
>   }
>
> The problem I'm finding is after doing the first inline of a call
> (using InlineFunction(ci,IFI) ) the program then SEGFAULTS which I
> believe is happening because the instruction iterator is made invalid
> when I do inlining (looking in gdb one of its fields I see is
> NodePtr=0x0 ).
>
> Is this normal behaviour?

In many situations in C++ this is normal behavior (inlining
presumably, removes the instruction you pass it - because there's no
longer a call) - if you remove an element from a sequence (eg: using
std::list<T>::erase(iterator)) the current iterator becomes invalid.

The common idiom to deal with this is to copy the iterator and
increment the copy before the operation that invalidates the iterator:

instead of:

for (iter i = begin(); i != end(); ++i) {
  if (cond)
    erase(i); // next increment will be invalid
}

one would write:

for (iter i = begin(); i != end(); ) {
  if (cond) {
    iter t = i;
    ++i;
    erase(t);
  } else {
    ++i;
  }
}

> If so what is the correct way to implement
> what I'm trying to do?
>
> For now I'm going to implement the code so that it instead collects a
> set of pointers to all the CallInstr of interest whilst iterating
> through the module. Then after iterating through the module, iterate
> through the set of collected CallInstr* and inline each one.
>
> Thanks,
> Dan Liew
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev



More information about the llvm-dev mailing list