[llvm-dev] Testing utility for building and updating CFG

Tobias Grosser via llvm-dev llvm-dev at lists.llvm.org
Wed Jun 28 02:01:59 PDT 2017


On Wed, Jun 28, 2017, at 12:31 AM, Jakub (Kuba) Kuderski via llvm-dev
wrote:
> Hi folks,
> 
> I’m working on adding an API for incremental updates to DominatorTree and
> I
> noticed that there isn’t a simple way to quickly build and update CFG
> (just
> for testing) -- one has to either build CFG programmatically, or write IR
> by hand and manually map pointers to basic blocks. The downside is that
> it
> tends to be pretty verbose and not easy to update (e.g. adding a new edge
> often involves changing the type of terminator instruction).

Hi Jakub,

I really like the idea of automating the testing and to even prepare for
extensive fussing.

> My idea is to create a simple format for building arbitrary CFG’s and new
> utilities for updating it.
> 
> It can look something like this:
> b ModuleName FunctionName // Build module ‘ModuleName’ with a single
> 
>                          // function ‘FunctionName’.
> 
> a entry if                // Add new basic blocks (entry and if) and
> 
>                          // connect them with an edge.
> 
> a if if.then              // Add new basic block (if.then) and create
> 
>                          // an edge from if to if.then
> 
> a if if.else
> 
> a if.then foo
> 
> a if.else foo
> 
> a bar                     // Add a new block bar, but don’t create
> 
>                          // any edges.
> 
> e                         // Finish constructing initial CFG
> 
> i foo bar                 // Insert and edge from foo to bar.
> 
> d if if.then              // Delete the edge from if to if.then.
> 
> i if bar                  // Insert an edge from if to bar.
> 
> 
> 
> Under the hood, the utility would build IR with just switch instructions.
> 
> Then you could assign it to a string and use in a unit test:
> 
> CFGBuilder B(MyString);
> 
> Function *F = B.getFunction();
> 
>> 
> while (!B.finished()) {
> 
>    Update U = B.applyNextUpdate(); // B changes the CFG.
> 
> // U stores type of update (insertion/deletion) and a pair of BB’s
> 
> // (From and To).
> 
>    doSomethingWithTheUpdate(U);
> 
> }
> 
> Other CFG passes (e.g. LoopInfo, NewGVN) could also use it for testing.
> It
> would be also possible to hook it up to a fuzzer at some point in the
> future.
>
> What do you think about having such a utility in llvm?

I like the idea and if it helps to have extensive unit tests in LLVM,
that's great. I am slightly worried about a new DSL (which always has a
maintenance cost). However, this seems well contained and simple, so I
would expect it to remain unchanged and up-to-date for a while.

Some thoughts (which I mentioned earlier).

# lit compatibility and maybe even opt compatability

I believe that LLVM lit tests are the easiest tests to write and debug.
If there is a chance we can write such unit tests as lit tests,
I would really appreciate this. It might even make sense to allow these
update-sets to be read through an opt pass, such that
dominators, loop passes, ... can be tested as part of the pass pipeline.

---------------------------------
; RUN: opt -dom -verify-dom -cfg-updater -cfg-updater-file %s < %s
; 
; CFG: i entry, if
; CFG: i if if.then
; CFG: i if if.else
; CFG: i if.then a
; CFG: i if.else a
; CFG: d entry a
;
def void @entry() {
entry:
   br label %a

a:
  return
}
---------------------------------

# Which terminators do you return for bbs without a successor. Are these
automatically return blocks or can these also be unreachable?

Most of the above comments are mostly to provide you with more ideas. I
generally like the approach. As you are the one using it most at the
moment, you likely know best where to put emphasis on.

Best,
Tobias

> ~Kuba
> 
> -- 
> Jakub Kuderski
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev


More information about the llvm-dev mailing list