From 36e8c7f64c972bf736910ece4f8317fd919f6c7a Mon Sep 17 00:00:00 2001 From: Stephen Jia Date: Thu, 27 Aug 2026 08:02:11 -0700 Subject: [PATCH] Update [ghstack-poisoned] --- backends/native/runtime/graph/Ids.h | 33 ++++++++ backends/native/runtime/graph/Value.cpp | 38 +++++++++ backends/native/runtime/graph/Value.h | 97 +++++++++++++++++++++++ backends/native/runtime/graph/targets.bzl | 22 +++++ 4 files changed, 190 insertions(+) create mode 100644 backends/native/runtime/graph/Ids.h create mode 100644 backends/native/runtime/graph/Value.cpp create mode 100644 backends/native/runtime/graph/Value.h diff --git a/backends/native/runtime/graph/Ids.h b/backends/native/runtime/graph/Ids.h new file mode 100644 index 00000000000..24cb394f9d1 --- /dev/null +++ b/backends/native/runtime/graph/Ids.h @@ -0,0 +1,33 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include + +namespace ptn { + +// Index-arena handles: a NodeRef indexes the graph's node arena, a ValueRef +// its value arena. Plain int32_t aliases — they index, compare, and hash +// directly, at the cost of no NodeRef/ValueRef type distinction. kInvalid marks +// "no ref". +using NodeRef = int32_t; +using ValueRef = int32_t; +constexpr int32_t kInvalid = -1; + +inline bool valid(int32_t ref) { + return ref >= 0; +} + +// std::cmp_less compares the signed ref against the unsigned size without +// casting either side. +inline bool in_bounds(int32_t ref, size_t size) { + return valid(ref) && std::cmp_less(ref, size); +} + +} // namespace ptn diff --git a/backends/native/runtime/graph/Value.cpp b/backends/native/runtime/graph/Value.cpp new file mode 100644 index 00000000000..ebea426a65b --- /dev/null +++ b/backends/native/runtime/graph/Value.cpp @@ -0,0 +1,38 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#include + +#include + +namespace ptn { + +const TensorMeta& Value::tensor_meta() const { + const TensorMeta* m = std::get_if(&value_); + if (m == nullptr) { + throw std::runtime_error("Value::tensor_meta: value is not a Tensor"); + } + return *m; +} + +const Scalar& Value::scalar() const { + const Scalar* s = std::get_if(&value_); + if (s == nullptr) { + throw std::runtime_error("Value::scalar: value is not a Scalar"); + } + return *s; +} + +const std::vector& Value::content_refs() const { + const std::vector* refs = + std::get_if>(&value_); + if (refs == nullptr) { + throw std::runtime_error("Value::content_refs: value is not a List"); + } + return *refs; +} + +} // namespace ptn diff --git a/backends/native/runtime/graph/Value.h b/backends/native/runtime/graph/Value.h new file mode 100644 index 00000000000..70e4d32e0aa --- /dev/null +++ b/backends/native/runtime/graph/Value.h @@ -0,0 +1,97 @@ +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree. + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace ptn { + +enum class ValueKind : int8_t { + None = 0, + Tensor = 1, + Scalar = 2, + List = 3, +}; + +// A single SSA value (dataflow edge) in a Graph: its contents plus def-use +// wiring, a storage alias and an open annotation map. The ref fields are plain +// handles; whether one is in range is a property of the owning arena, so +// nothing here validates them. +// +// The variant's alternatives are listed in ValueKind order, so kind() is its +// index. A List holds ValueRefs to its elements rather than nested Values, so +// nesting goes through the arena; nothing deserialized is a List, it exists for +// in-memory rewrites such as grouping a tuple. +class Value { + private: + std::variant> + value_; + + public: + // SSA name, scoped to the enclosing Graph. + std::string name; + // Defining node; invalid => graph input. + NodeRef producer_ref = kInvalid; + // Def-use, built by inverting node inputs. + std::vector consumer_refs; + // Shares storage with this value (a view); fresh if invalid. + ValueRef alias_ref = kInvalid; + // Open annotations for graph passes and engines, like node.meta in FX. + std::unordered_map attrs; + + Value() = default; // a None value with an empty name + + explicit Value(std::string name) // a named None value + : name(std::move(name)) {} + + Value(std::string name, TensorMeta meta) + : value_(std::move(meta)), name(std::move(name)) {} + + // The empty dim_order_hint is what makes the tensor contiguous. + Value(std::string name, ScalarType dtype, std::vector sizes) + : value_(TensorMeta{dtype, std::move(sizes), {}}), + name(std::move(name)) {} + + Value(std::string name, Scalar value) + : value_(value), name(std::move(name)) {} + + Value(std::string name, std::vector elem_refs) + : value_(std::move(elem_refs)), name(std::move(name)) {} + + ValueKind kind() const { + return static_cast(value_.index()); + } + bool is_tensor() const { + return std::holds_alternative(value_); + } + bool is_scalar() const { + return std::holds_alternative(value_); + } + bool is_list() const { + return std::holds_alternative>(value_); + } + bool is_none() const { + return std::holds_alternative(value_); + } + + // Typed payload accessors: throw std::runtime_error unless the kind matches. + const TensorMeta& tensor_meta() const; + const Scalar& scalar() const; + const std::vector& content_refs() const; +}; + +} // namespace ptn diff --git a/backends/native/runtime/graph/targets.bzl b/backends/native/runtime/graph/targets.bzl index cf5beef5de7..5da780d9d2f 100644 --- a/backends/native/runtime/graph/targets.bzl +++ b/backends/native/runtime/graph/targets.bzl @@ -38,3 +38,25 @@ def define_common_targets(): ], visibility = ["//executorch/backends/native/..."], ) + + runtime.cxx_library( + name = "ids", + exported_headers = [ + "Ids.h", + ], + visibility = ["//executorch/backends/native/..."], + ) + + runtime.cxx_library( + name = "value", + srcs = ["Value.cpp"], + exported_headers = [ + "Value.h", + ], + exported_deps = [ + ":ids", + ":scalar", + ":tensor_meta", + ], + visibility = ["//executorch/backends/native/..."], + )