[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