[LLVMdev] Graphviz and LLVM-TV

Ioannis Nousias ioannis.nousias at googlemail.com
Sun Sep 6 09:57:28 PDT 2009


Edwin,

thank you for your effort, but I'm not sure I understand.
Are you describing a graph traversal problem? Is the data model stored 
in a predecessor/successor fashion, which requires you to 'walk' the 
graph in order to visit all nodes? (and what happens when you have 
disjointed DFGs?).

inline comments follow...

Török Edwin wrote:
> On 2009-09-06 17:30, Ioannis Nousias wrote:
>   
>> I've tried to write a DFGPrinter based on the CFGPrinter, as you 
>> suggested, but encountered problems.
>>
>> The GraphWriter expects 
>> GraphTraits<GraphType>::nodes_begin()/nodes_end(). The way this is 
>> implemented in CFG.h, a function is a graph of basic blocks. A 
>> GraphTraits<Function*>  inherits from GraphTraits<BasicBlock*>, and 
>> implements those nodes_begin()/nodes_end() wrapper functions. Should I 
>> modify CFG.h and make now BasicBlock a graph of Instruction(s) ?
>>
>> The DataFlow.h deals with Value and User. Now BasicBlock is derived from 
>> Value and Instruction from User, but I don't understand how that helps.
>>
>> It's a bit confusing to be honest. Can you help?
>>   
>>     
>
> Here are some examples on how to use the dataflow graphs:
>
> Value *V = ...
> for(df_iterator<Value*> UI = df_begin(V), UE = df_end(V); UI != UE; ++UI) {
> ...
> }
>
>
> typedef SmallPtrSet<const Value*, 16> SmallValueSet;
> SmallValueSet DFSet;
> const User* U = ...;
> for (idf_ext_iterator<const User*, SmallValueSet> I=idf_ext_begin(U,
> DFSet), E=idf_ext_end(U, DFSet); I != E; ++I) {
> ..
> }
>
>
>   
I don't understand why I'd need a depth-first iterator.


> There is no common root for the dataflow graph from which you can
> enumerate all dataflows, but you could take
> each instruction in a function that you're interested in, and output a
> dataflow graph rooted at that instruction,
> unless that instruction was part of some other dataflow graph already.
>
>   
from this I'm getting that you suggest finding all "root" instructions 
and traverse each chain of instruction (data-flow) separately. 
Considering that most dataflows are not simple expanding trees, and are 
instead merging and spliting at several points, I'm not sure what good 
that would do.

> Perhaps something like:
>
> SmallValueSet PrintedSet;
> for (Function::arg_iterator I=F.arg_begin(), E=F.arg_end(); I != E; ++I) {
>        if (!PrintedSet.count(*I)) {
>              ... print graph rooted at V, add each node printed to
> PrintedSet
>       }   
> }
> for (inst_iterator I=inst_begin(F), E=inst_end(F); I != E; ++I) {
>        if (!PrintedSet.count(*I)) {
>              ... print graph rooted at V, add each node printed to
> PrintedSet
>       }   
> }
>
> Best regards,
> --Edwin
>   
Most likely I'm missing some information here. There's probably some 
internal structure, probably how the data-model is build, that requires 
this sort of traversal. Can you elaborate please.

What I'm looking for, to start with, is something rather simple (or at 
least it should be). A per BasicBlock view of their DFGs. I'm not 
interested in the inter-BasicBlock connections, for now. I'm tempted to 
just iterate through the instructions container of each BasicBlock and 
output the graphviz manually. However, I'd prefer using any facilities 
present. The way I see it, all I need to do is iterate through the 
instructions of the BasicBlock, enumerate them to the graphviz data 
model, then iterate through them once more, checking their 
predecessor/successor instructions (inputs/outputs), to register their 
connectivity (edges). Right?


thanks,
Ioannis



PS: By the way. How come and you guys are not using Graphviz's library 
API? Avoiding the dependency?




More information about the llvm-dev mailing list