| 159 | } |
| 160 | |
| 161 | ValueRefList TracingTransformation::apply_transformation( |
| 162 | const Operator& op, Span<ValueRef> inputs) { |
| 163 | if (auto* op_value = op.as<ApplyOp>()) { |
| 164 | SmallVector<ValueRef> unwrapped_inputs; |
| 165 | SmallVector<TracingValue::ref_t> wrapped_inputs; |
| 166 | SmallVector<size_t> input_ids; |
| 167 | for (auto input : inputs) { |
| 168 | auto tracing_value = input.as_ref(m_value_type); |
| 169 | if (!tracing_value) { |
| 170 | tracing_value = |
| 171 | record_var(input, m_capture_as_const, VarKind::External); |
| 172 | } |
| 173 | unwrapped_inputs.push_back(tracing_value->value()); |
| 174 | wrapped_inputs.push_back(tracing_value); |
| 175 | input_ids.push_back(tracing_value->id()); |
| 176 | } |
| 177 | // TODO: remove OpDef::set_scope |
| 178 | auto scopes = Transformation::scopes(); |
| 179 | std::string scopes_join; |
| 180 | for (auto&& scope : scopes) { |
| 181 | if (!scopes_join.empty()) { |
| 182 | scopes_join.push_back('.'); |
| 183 | } |
| 184 | scopes_join.append(scope); |
| 185 | } |
| 186 | const_cast<OpDef&>(op_value->op()).set_scope(scopes_join); |
| 187 | auto unwrapped_outputs = imperative::apply(op, unwrapped_inputs); |
| 188 | ValueRefList wrapped_outputs(unwrapped_outputs.size()); |
| 189 | SmallVector<size_t> output_ids; |
| 190 | for (size_t i = 0; i < unwrapped_outputs.size(); ++i) { |
| 191 | auto&& output = unwrapped_outputs[i]; |
| 192 | auto wrapped_output = record_var(output, false, VarKind::Internal); |
| 193 | wrapped_outputs[i] = wrapped_output; |
| 194 | output_ids.push_back(wrapped_output->id()); |
| 195 | } |
| 196 | m_seq.push_back({op_value->op().shared_from_this(), input_ids, output_ids}); |
| 197 | return wrapped_outputs; |
| 198 | } else if (auto* create_tensor = op.as<CreateTensor>()) { |
| 199 | auto outputs = imperative::apply(op, inputs); |
| 200 | if (create_tensor->kind() == CreateTensor::NoTrace) { |
| 201 | return outputs; |
| 202 | } |
| 203 | bool is_const = create_tensor->kind() == CreateTensor::Const; |
| 204 | bool as_const = is_const || m_capture_as_const; |
| 205 | auto wrapped_input = record_var( |
| 206 | outputs[0], as_const, is_const ? VarKind::Constant : VarKind::External); |
| 207 | // bound data to outputs too to reduce runtime overhead for shape/value infer |
| 208 | auto wrapped_output = record_var(outputs[0], as_const, VarKind::Internal); |
| 209 | auto input_id = wrapped_input->id(); |
| 210 | auto output_id = wrapped_output->id(); |
| 211 | |
| 212 | m_seq.push_back({{}, {input_id}, {output_id}, OpKind::CreateTensor}); |
| 213 | return {wrapped_output}; |
| 214 | } else if (auto* get_attr = op.as<GetAttr>()) { |
| 215 | auto unwrapped_input = unwrap_var(inputs[0]); |
| 216 | auto outputs = imperative::apply(op, unwrapped_input); |
| 217 | if (auto* tracing_value = inputs[0].as(m_value_type)) { |
| 218 | auto& var_info = m_vars[tracing_value->id()]; |
nothing calls this directly
no test coverage detected