[llvm-dev] LLVM Pass To Remove Dead Code In A Basic Block

Dean Michael Berris via llvm-dev llvm-dev at lists.llvm.org
Fri May 25 01:41:59 PDT 2018


> On 25 May 2018, at 03:53, Aaron <acraft at gmail.com> wrote:
> 
> Hi Dean,
> 
> Thanks for your reply.
> 
> That's exactly what I am doing, but I was looking for a default optimization or pass implementation if there was.
> 

There’s a dead code elimination pass, but it works with a control flow graph (it removes basic blocks that are unreachable after constant propagation and other passes earlier on have run).

> I used BasicBlock::splitBasicBlock() but it puts "br" end of original basic block. I tried to delete the br instruction by using eraseFromParent() but it didn't work.
> 

This is working as intended. All LLVM BasicBlocks *must* have a terminator as the last instruction.

> I had to rewrite my own splitBasicBlock() by modifying the original one. Just removed the br instruction creation lines.
> 

It sounds like it would have just been easier to replace the branch instruction into a ret, then remove all successors of the original br instruction. There’s nothing special here, this is how it’s supposed to be done.

> >> Just curious, how are you getting return instructions in the middle of a basic block?
> My code generation pass allows multiple return instruction generation since that simplifies front-end significantly.
> 

I’m just wondering why not have a ‘br’ to an exit basic block instead of ‘ret’ mid-stream of instructions. That way you don’t need to do any special post-processing while you’re emitting the LLVM IR, you end up with valid basic blocks all the time, and you can leverage all the other passes that come with LLVM already.

That at least sounds simpler to me.

I’m not sure whether you can have non-entry blocks with no predecessors in LLVM (need to look up the langref about that) but I can imagine it’s a fairly useful construct to support. e.g. something like (pseudo-IR):

.entry:
  <this is the entry block>
  <…>
  br .exit

.bb0:
  <this is by definition unreachable>
  <…>
  br .exit

.exit:
  ret

This structure makes it easier for dead code elimination to determine that .bb0 is unreachable from .entry and can elide it safely. From your front-end, you can have a single ‘.exit’ block in a function and let the optimisations do the basic-block merging later on.

Have you considered this approach instead?

-- Dean



More information about the llvm-dev mailing list