[LLVMdev] Remove function from module

1,643 views
Skip to first unread message

Михаил

unread,
Apr 21, 2012, 1:09:19 PM4/21/12
to llvmdev
How correctly remove function from module?
For example:

int f1(int x) { 
   ...
   a = f2(smth);
   ...
}
int f2 (int y) {
   ...
   b = f1(smth);
   ...
}

I need delete from module both f1 and f2. They haven't uses in other part of module, but I can't delete them with eraseFromParent, because they are use each other.

Yours sincerely,
Kadysev Mikhail

Nick Lewycky

unread,
Apr 21, 2012, 3:45:52 PM4/21/12
to Михаил, llvmdev

Call X->replaceAllUsesWith(UndefValue::get(X->getType)) before calling
X->eraseFromParent().

Nick
_______________________________________________
LLVM Developers mailing list
LLV...@cs.uiuc.edu http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev

Dmitry N. Mikushin

unread,
Apr 21, 2012, 4:03:18 PM4/21/12
to Nick Lewycky, llvmdev
Hi Михаил,

You can also use GVExtractionPass:

if (!strcmp(argv[1], "pass"))
{
PassManager manager;
manager.add(new TargetData(m.get()));

// Delete functions specified in list of functions.
vector<GlobalValue*> functions;
functions.push_back(m.get()->getFunction("f1"));
functions.push_back(m.get()->getFunction("f2"));
manager.add(createGVExtractionPass(functions, true));

// Delete unreachable globals.
manager.add(createGlobalDCEPass());

// Remove dead debug info.
manager.add(createStripDeadDebugInfoPass());

// Remove dead func decls.
manager.add(createStripDeadPrototypesPass());

manager.run(*m.get());
}

if (!strcmp(argv[1], "manual"))
{
Function* f1 = m.get()->getFunction("f1");
Function* f2 = m.get()->getFunction("f2");

f1->replaceAllUsesWith(UndefValue::get((Type*)f1->getType()));
f2->replaceAllUsesWith(UndefValue::get((Type*)f2->getType()));

f1->eraseFromParent();
f2->eraseFromParent();
}

- D.

2012/4/21 Nick Lewycky <nich...@mxc.ca>:
makefile
test.c
test.ll
transform.cxx

Михаил

unread,
Apr 21, 2012, 4:09:15 PM4/21/12
to llvmdev
Thanks, but I replaceAllUsesWith() - works well, but I still get bug in eraseFromParent():

While deleting: i32 (%class.B*, i32)* %_ZN1B1xEi
An asserting value handle still pointed to this value!
UNREACHABLE executed at /Users/neonomaly/LLVM/LLVM/lib/VMCore/Value.cpp:561!


Yours sincerely,
Kadysev Mikhail

21.04.2012, в 23:45, Nick Lewycky написал(а):

Dmitry N. Mikushin

unread,
Apr 21, 2012, 4:30:23 PM4/21/12
to Михаил, llvmdev
Could you reproduce this assertion with my test program?

22 апреля 2012 г. 0:09 пользователь Михаил <neono...@gmail.com> написал:

Михаил

unread,
Apr 21, 2012, 5:44:27 PM4/21/12
to llvmdev
It also occurs on several (different) test cases. I have founded that assershion rises in void ValueHandleBase::ValueIsDeleted(Value *V);

Code from function:

  // All callbacks, weak references, and assertingVHs should be dropped by now.
  if (V->HasValueHandle) {
#ifndef NDEBUG      // Only in +Asserts mode...
    dbgs() << "While deleting: " << *V->getType() << " %" << V->getNameStr()
           << "\n";
    if (pImpl->ValueHandles[V]->getKind() == Assert)
      llvm_unreachable("An asserting value handle still pointed to this
                       " value!");

#endif
    llvm_unreachable("All references to V were not removed?");
  }

Yours sincerely,
Kadysev Mikhail

22.04.2012, в 1:41, Dmitry N. Mikushin написал(а):

Assertion occurs on some different test case? Could you attach its IR-code?

22 апреля 2012 г. 1:38 пользователь Михаил <neono...@gmail.com> написал:
Yes

Yours sincerely,
Kadysev Mikhail

22.04.2012, в 0:30, Dmitry N. Mikushin написал(а):

Nick Lewycky

unread,
Apr 21, 2012, 9:20:25 PM4/21/12
to Михаил, llvmdev
Михаил wrote:
> Thanks, but I replaceAllUsesWith() - works well, but I still get bug in
> eraseFromParent():
>
> While deleting: i32 (%class.B*, i32)* %_ZN1B1xEi
> An asserting value handle still pointed to this value!
> UNREACHABLE executed at /Users/neonomaly/LLVM/LLVM/lib/VMCore/Value.cpp:561!

The replaceAllUsesWith + eraseFromParent pattern remains correct, but
there's more to the story than the parts we've focused on. This error
means that there's some other code that is holding a pointer to the
function you tried to delete, but is using AssertingVH to do so, so as
to catch errors exactly like this producing a dangling pointer.

The error message doesn't tell us who owns the AssertingVH (indeed, the
asserting-vh doesn't know, much like a pointer doesn't know who owns it).

So, under what circumstance are you doing this deletion? Is it inside a
FunctionPass, or another kind of Pass? Are you using AssertingVH's or
calling other code that is? Such as ValueMap's, or some llvm analysis
pass which stores an AssertingVH?

Nick

>
>
> Yours sincerely,
> Kadysev Mikhail
>
> 21.04.2012, в 23:45, Nick Lewycky написал(а):
>
>> Михаил wrote:
>>> How correctly remove function from module?
>>> For example:
>>>
>>> int f1(int x) {
>>> ...
>>> a = f2(smth);
>>> ...
>>> }
>>> int f2 (int y) {
>>> ...
>>> b = f1(smth);
>>> ...
>>> }
>>>
>>> I need delete from module both f1 and f2. They haven't uses in other
>>> part of module, but I can't delete them with eraseFromParent, because
>>> they are use each other.
>>
>> Call X->replaceAllUsesWith(UndefValue::get(X->getType)) before calling
>> X->eraseFromParent().
>>
>> Nick
>
>
>

Михаил

unread,
Apr 22, 2012, 3:17:03 PM4/22/12
to llvmdev
It is ModulePass with AnalysisUsage of CallGraph
Yours sincerely,
Kadysev Mikhail

22.04.2012, в 5:20, Nick Lewycky написал(а):

Nick Lewycky

unread,
Apr 22, 2012, 3:30:45 PM4/22/12
to Михаил, llvmdev
Михаил wrote:
> It is ModulePass with AnalysisUsage of CallGraph

Ah, then you'll need to update the CallGraph first. Use
"CG.removeFunctionFromModule(F);" before deleting it.

Nick

>>> LLV...@cs.uiuc.edu <mailto:LLV...@cs.uiuc.edu> http://llvm.cs.uiuc.edu

Михаил

unread,
Apr 23, 2012, 4:49:36 AM4/23/12
to llvmdev
Thanks.


I try to delete function like this (rta_IsFunctionVisited.find - set of good functions) :

// delete dead functions
for (Module::iterator Fx = M->begin(), FE = M->end(); Fx!=FE; Fx++) {
if (rta_IsFunctionVisited.find(Fx)==rta_IsFunctionVisited.end()) {
Fx->replaceAllUsesWith(UndefValue::get(Fx->getType()));
}
}

for (CallGraph::iterator CGN = CG.begin(); CGN!=CG.end(); CGN++) {
if (rta_IsFunctionVisited.find(CGN->second->getFunction())==rta_IsFunctionVisited.end()) {
CGN->second->removeAllCalledFunctions();
}
}

for (Module::iterator Fx = M->begin(), FE = M->end(); Fx!=FE;) {
if (rta_IsFunctionVisited.find(Fx)==rta_IsFunctionVisited.end()) {
CallGraphNode *CGN = CG.getOrInsertFunction(Fx);
CG.removeFunctionFromModule(Fx);
wasChanged=true;
Fx=M->begin();
} else Fx++;
}

return true;

But I still have a bug:

opt(63981) malloc: *** error for object 0x7ff1394050a0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
0  libLLVM-3.0.dylib 0x00000001082d7605 _ZL15PrintStackTracePv + 53
1  libLLVM-3.0.dylib 0x00000001082d7c6c _ZL13SignalHandleri + 364
2  libsystem_c.dylib 0x00007fff9152dcfa _sigtramp + 26
3  libsystem_c.dylib 0x00007fff66d6a878 _sigtramp + 18446744072996768664
4  libsystem_c.dylib 0x00007fff9152b84c free + 389
5  libLLVM-3.0.dylib 0x00000001083536b0 __gnu_cxx::new_allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> >::deallocate(std::pair<llvm::WeakVH, llvm::CallGraphNode*>*, unsigned long) + 32
6  libLLVM-3.0.dylib 0x000000010835360e std::_Vector_base<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::_M_deallocate(std::pair<llvm::WeakVH, llvm::CallGraphNode*>*, unsigned long) + 62
7  libLLVM-3.0.dylib 0x00000001083535bd std::_Vector_base<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~_Vector_base() + 45
8  libLLVM-3.0.dylib 0x0000000108353509 std::vector<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~vector() + 105
9  libLLVM-3.0.dylib 0x0000000108353495 std::vector<std::pair<llvm::WeakVH, llvm::CallGraphNode*>, std::allocator<std::pair<llvm::WeakVH, llvm::CallGraphNode*> > >::~vector() + 21
10 libLLVM-3.0.dylib 0x000000010852be3e llvm::CallGraphNode::~CallGraphNode() + 110
11 libLLVM-3.0.dylib 0x0000000108529d55 llvm::CallGraphNode::~CallGraphNode() + 21
12 libLLVM-3.0.dylib 0x0000000108528468 llvm::CallGraph::destroy() + 264
13 libLLVM-3.0.dylib 0x00000001085295f8 (anonymous namespace)::BasicCallGraph::destroy() + 120
14 libLLVM-3.0.dylib 0x0000000108529379 (anonymous namespace)::BasicCallGraph::releaseMemory() + 25
15 libLLVM-3.0.dylib 0x0000000107bf5d93 llvm::PMDataManager::freePass(llvm::Pass*, llvm::StringRef, llvm::PassDebuggingString) + 179
16 libLLVM-3.0.dylib 0x0000000107bf5c89 llvm::PMDataManager::removeDeadPasses(llvm::Pass*, llvm::StringRef, llvm::PassDebuggingString) + 505
17 libLLVM-3.0.dylib 0x0000000107bf8ee8 llvm::MPPassManager::runOnModule(llvm::Module&) + 1016
18 libLLVM-3.0.dylib 0x0000000107bf949c llvm::PassManagerImpl::run(llvm::Module&) + 172
19 libLLVM-3.0.dylib 0x0000000107bf997d llvm::PassManager::run(llvm::Module&) + 29
20 opt               0x000000010717f057 main + 6903
21 opt               0x000000010716d7b4 start + 52
22 opt               0x0000000000000007 start + 18446744069295646855



Yours sincerely,
Kadysev Mikhail

22.04.2012, в 23:30, Nick Lewycky написал(а):
Reply all
Reply to author
Forward
0 new messages