2014-01-17 2 views
1

llvm 중간 코드에서 사용하지 않은 블록을 제거하려고합니다.사용하지 않는 기본 블록을 제거하는 방법 llvm

첫째,이 항목 basicblock로 시작과 종료 명령에서 모든 basicblock의 후계자를 추가하여, 도달 basicblocks의 컬렉션을 구축 : 그 후

bbset.insert(bbterm->getSuccessor(i)); 

, 내가 도달 할 수없는 basicblocks을 반복하고 사용하여 삭제 의 Utils/BasicBlockUtils.cpp

이 작품에서

DeleteDeadBlock(bb); 

하지만 일부 시나리오에서 나는 세그먼트 폴트를 얻을. 아래 코어 덤프입니다 :

opt: /home/user/llvm-3.3.src/lib/Transforms/Utils/BasicBlockUtils.cpp:38: void llvm::DeleteDeadBlock(llvm::BasicBlock*): Assertion `(pred_begin(BB) == pred_end(BB) || BB->getSinglePredecessor() == BB) && "Block is not dead!"' failed. 
0 opt    0x0000000001756825 llvm::sys::PrintStackTrace(_IO_FILE*) + 38 
1 opt    0x0000000001756aa2 
2 opt    0x000000000175651e 
3 libpthread.so.0 0x00007fe1fe76dbb0 
4 libc.so.6  0x00007fe1fdbaef77 gsignal + 55 
5 libc.so.6  0x00007fe1fdbb25e8 abort + 328 
6 libc.so.6  0x00007fe1fdba7d43 
7 libc.so.6  0x00007fe1fdba7df2 
8 opt    0x000000000138b004 llvm::DeleteDeadBlock(llvm::BasicBlock*) + 139 
9 opt    0x0000000000d49c2e 
10 opt    0x0000000001652942 llvm::FPPassManager::runOnFunction(llvm::Function&) + 290 
11 opt    0x0000000001652ab2 llvm::FPPassManager::runOnModule(llvm::Module&) + 84 
12 opt    0x0000000001652dd0 llvm::MPPassManager::runOnModule(llvm::Module&) + 502 
13 opt    0x00000000016533a0 llvm::PassManagerImpl::run(llvm::Module&) + 244 
14 opt    0x00000000016535ab llvm::PassManager::run(llvm::Module&) + 39 
15 opt    0x00000000008c6cb6 main + 5698 
16 libc.so.6  0x00007fe1fdb99de5 __libc_start_main + 245 
17 opt    0x00000000008b8a39 

어떤 아이디어가 문제가 될 수 있습니까?

답변

2

그건 segfault가 아니며 어설 션 오류이며 문제를 말하고 있습니다. 선행자 목록은 비어 있지 않습니다. DeleteDeadBlock은 삭제하려는 블록에 직계 전임자가 없다는 것을 확인하기 때문에이 어설 션 오류가 발생합니다.

그러나이 테스트는 블록이 살아 있음을 의미하지는 않습니다.

entry 
/
A B 
| | 
C D 
\/
    E 

B와 D가 모두 죽었하지만 B 전에 D를 제거하려고합니다 경우 D가 가지고 있기 때문에 당신이 주장을 얻을 것이다 : 예를 들어,이 시나리오에서 (선이 화살표를 아래로 향한 것으로 가정) 전임자 (자체가 아닌).

해결 방법? 위상 순서

  • 합니다 (unreachable 명령으로 모든 전임자의 종결을 교체하여 예) 삭제하려고 블록에서 모든 선배를 제거

      1. 프로세스 블록 : 당신이 중 하나를 수행 할 수 있습니다
      2. 또한 모든 블록에 당신이 죽은 첫째 식별하고
  • 이 가
    +0

    오크, 블록을 삭제 한 후, 내가 너무 얻을 임의의 순서대로 삭제하는 것이 할 수있는 나 phinode 지침 문제. % x = phi i32 [x, % label], [number, % 0], phi ins을 % 1 블록으로 대체 한 후, "PHINode는 부모 기본의 전신에 대해 하나의 항목을 가져야합니다 블록!" 왜냐하면 % 0은 phi 명령과 관련이 없기 때문입니다. 무슨 문제가 될 수 있니? – kaspersky

    +0

    @ gg.kaspersky 두 개의 기본 블록을 연결 해제 할 때마다 (살아 있는지 여부) - 후속 노드의 phi 노드를 업데이트해야합니다. 'PHINode :: removeIncomingValue'가 당신을 도울 수 있습니다. – Oak

    관련 문제