See the following runnable example:
import tvm
from tvm import relay
from tvm.relay.scope_builder import ScopeBuilder
shape = (5, 5)
sb1 = ScopeBuilder()
p0 = relay.var("p0", shape=shape)
p1 = relay.var("p1", shape=shape)
a0 = sb1.let("a0", relay.add(p0, relay.const(1)))
a1 = sb1.let("a1", relay.add(p1, relay.const(1)))
a2 = sb1.let("a2", relay.add(a0, a1))
sb1.ret(a2)
func1 = relay.Function([p0, p1], sb1.get())
print(func1)
sb2 = ScopeBuilder()
p0 = relay.var("p0", shape=shape)
p1 = relay.var("p1", shape=shape)
a1 = sb2.let("a1", relay.add(p1, relay.const(1)))
a0 = sb2.let("a0", relay.add(p0, relay.const(1)))
a2 = sb2.let("a2", relay.add(a0, a1))
sb2.ret(a2)
func2 = relay.Function([p0, p1], sb2.get())
print(func2)
# Should fail but didn't
tvm.ir.structural_equal(func1, func2)
I guess this is because structural equal recursively traverses the node arguments from the graph output for whatever dataflow graph or A-Normal form. It this an expected behavior or should we somehow fix structural equal to let it catch this difference?