diff --git a/src/relay/backend/compile_engine.cc b/src/relay/backend/compile_engine.cc index 0dc9e458d7aa..73bae053cc82 100644 --- a/src/relay/backend/compile_engine.cc +++ b/src/relay/backend/compile_engine.cc @@ -83,11 +83,20 @@ class ScheduleGetter : cache_node->func_name = readable_name_stream_.str(); CachedFunc cfunc(cache_node); CHECK(master_op_.defined()); + // Fusion over tupled results may leave identity relationships + // between inputs and outputs, and those should not be scheduled. + // Hence schedule only non PlaceholderOp outputs. + tvm::Array tensor_outs; + for (const auto& tensor : cache_node->outputs) { + if (!tensor->op.as()) { + tensor_outs.push_back(tensor); + } + } Schedule schedule; // No need to register schedule for device copy op. if (master_attrs_.as() == nullptr) { schedule = - fschedule[master_op_](master_attrs_, cache_node->outputs, target_); + fschedule[master_op_](master_attrs_, tensor_outs, target_); for (const auto& scalar : scalars_) { schedule[scalar].compute_inline(); } diff --git a/tests/python/relay/test_backend_compile_engine.py b/tests/python/relay/test_backend_compile_engine.py index 568d7849e7ee..a3a3af3f94b8 100644 --- a/tests/python/relay/test_backend_compile_engine.py +++ b/tests/python/relay/test_backend_compile_engine.py @@ -33,6 +33,16 @@ def get_func(shape): y.asnumpy(), x.asnumpy() * 3) engine.dump() +def test_compile_placeholder_bypass(): + engine = relay.backend.compile_engine.get() + x = relay.var("x", shape=(2, 3)) + y = relay.var("y", shape=(2, 3)) + z = relay.var("z", shape=(2, 3)) + result = relay.Tuple([x, relay.op.concatenate([y, z], axis=0)]) + func = relay.Function(relay.ir_pass.free_vars(result), result) + with relay.build_config(opt_level=0): + graph, lib, params = relay.build(func, 'llvm') if __name__ == "__main__": test_compile_engine() + test_compile_placeholder_bypass()