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

Daniel Liew daniel.liew at imperial.ac.uk
Sun Sep 15 01:59:06 PDT 2013


I just realised I forgot to reply to this. Thanks for advise, it's good to know.

Thanks,
Dan Liew.

On 30 August 2013 16:25, David Blaikie <dblaikie at gmail.com> wrote:
> 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