Input edges
Node inputs (use-def edges) is an ordered collection. Every node has a control input that has index 0. The value of it can be null, in which case it is not dependent on any control. The control edge is typically referenced by its index node->in(0), however many nodes define a constant to refer to it symbolically as in node->in(NodeType::Control), where NodeType is a particular type of a node.
Here is an example of a method that adds to integers passed as parameters to a function (the following print out of the graph can be obtained by specifying -XX:+PrintIdeal command-line option):
class X {
private static int foo1(int a, int b) {
return a + b;
}
}
11 Parm === 3 [[ 23 ]] Parm1: int !jvms: X::foo1 @ bci:-1
10 Parm === 3 [[ 23 ]] Parm0: int !jvms: X::foo1 @ bci:-1
3 Start === 3 0 [[ 3 5 6 7 8 9 10 11 ]] #{0:control, 1:abIO, 2:memory, 3:rawptr:BotPTR, 4:return_address, 5:int, 6:int}
23 AddI === _ 10 11 [[ 24 ]] !jvms: X::foo1 @ bci:2
9 Parm === 3 [[ 24 ]] ReturnAdr !jvms: X::foo1 @ bci:-1
8 Parm === 3 [[ 24 ]] FramePtr !jvms: X::foo1 @ bci:-1
7 Parm === 3 [[ 24 ]] Memory Memory: @BotPTR *+bot, idx=Bot; !jvms: X::foo1 @ bci:-1
6 Parm === 3 [[ 24 ]] I_O !jvms: X::foo1 @ bci:-1
5 Parm === 3 [[ 24 ]] Control !jvms: X::foo1 @ bci:-1
24 Return === 5 6 7 8 9 returns 23 [[ 0 ]]
0 Root === 0 24 [[ 0 1 3 ]] inner
Notice that AddI has the "_" placeholder, which means its control input is null.
Nodes that access memory or otherwise depend of memory state express that dependency by having a memory state edge. It can encoded as edge with index 1 for subclasses of MemNode (Loads and Stores), or at index 2 for subclasses of the SafePointNode (which are all the calls and the safepoint). It is a good idea refer to the index symbolically - MemNode::Memory for MemNode subclasses and TypeFunc::Memory for SafePointNode subclasses. When traversing the memory graph one has to dispatch on the type of the node to get the correct index of the memory edge. Store nodes produce memory directly, Call nodes need projection nodes to extract their memory effect result.
Some nodes (like calls) require dependency on the state that is different from memory, which is called an IO dependency (input with index 1 for SafePointNode subclasses) and can be refered to as NodeType::I_O, for example TypeFunc::I_O. The rest of the input edges depend on the type of node, in the example above AddI has two inputs for its left and right argument.
Whatever the input edges are the rules of the IR evaluation require that dependencies (all inputs) be evaluated before the given node (in general the evaluation model requires a depth-first traversal over input edges starting from the Return node). The graph itself encodes the program in essentially a functional form composing pure operations with monadic operations (that depend on control, memory and i/o side effects).