Change the order to Relay IR when converting to string

For graphs with multi branches, there might be more than one execution order. For example, the following DAG can be either executed in d -> e -> f -> out or e -> d -> f -> out. However, it seems in relay IR, we cannot determine which order to display when serializing.

a = relay.var("a", shape=[1, 10])
b = relay.var("b", shape=[1, 10])
c = relay.var("c", shape=[1, 10])
d = a + b
e = a * c
f = b / e
out = d - f
fn = relay.Function([a,b,c], out)
print(fn)
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
  %0 = add(%a, %b) /* string */;
  %1 = multiply(%a, %c) /* string */;
  %2 = divide(%b, %1) /* string */;
  subtract(%0, %2) /* string */
}
'''
#wanted version
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
  %1 = multiply(%a, %c) /* string */;
  %0 = add(%a, %b) /* string */;
  %2 = divide(%b, %1) /* string */;
  subtract(%0, %2) /* string */
}
'''

Even we manually switch the order, it will still display the original one

code = '''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
  %0 = add(%a, %b) /* string */;
  %1 = multiply(%a, %c) /* string */;
  %2 = divide(%b, %1) /* string */;
  subtract(%0, %2) /* string */
}
'''
fn = tvm.parser.parse_expr(code)
print(fn)
'''
fn (%a: Tensor[(1, 10), float32], %b: Tensor[(1, 10), float32], %c: Tensor[(1, 10), float32]) {
  %0 = multiply(%a, %c);
  %1 = add(%a, %b);
  %2 = divide(%b, %0);
  subtract(%1, %2)
}
'''
1 Like

The order of multiple branches in the DAG is unspecified. You might want to use A normal form if you need strict ordering.

1 Like