Skip to content

Commit 9089532

Browse files
Merge branch 'main' into add-logical-binary-ops-to-executorch
2 parents 7144767 + 51901f3 commit 9089532

File tree

56 files changed

+594
-589
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+594
-589
lines changed

.ci/docker/common/install_java.sh

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
# Copyright (c) Meta Platforms, Inc. and affiliates.
3+
# All rights reserved.
4+
#
5+
# This source code is licensed under the BSD-style license found in the
6+
# LICENSE file in the root directory of this source tree.
7+
8+
set -ex
9+
10+
apt-get update
11+
12+
apt-get install -y --no-install-recommends openjdk-17-jdk

.ci/docker/ubuntu/Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ ARG BUCK2_VERSION
3030
COPY ./common/install_buck.sh install_buck.sh
3131
RUN bash ./install_buck.sh && rm install_buck.sh
3232

33+
# Install java
34+
COPY ./common/install_java.sh install_java.sh
35+
RUN bash ./install_java.sh && rm install_java.sh
36+
3337
# Setup user
3438
COPY ./common/install_user.sh install_user.sh
3539
RUN bash ./install_user.sh && rm install_user.sh

.github/workflows/doc-build.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ jobs:
6868
make html
6969
cd ..
7070
71+
# Build javadoc:
72+
cd extension/android
73+
./gradlew javadoc
74+
cp -rf build/docs/javadoc "${RUNNER_DOCS_DIR}"
75+
cd ../..
76+
7177
# If it's main branch, add noindex tag to all .html files to exclude from Google Search indexing.
7278
echo "GitHub Ref: ${GITHUB_REF}"
7379
if [[ "${{ github.ref }}" == 'refs/heads/main' ]]; then

CODEOWNERS

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
/backends/vulkan @SS-JIA
1616
/backends/xnnpack @digantdesai @mcr229
1717

18-
/build @GregoryComer @dbort @kirklandsign
18+
/build @GregoryComer @kirklandsign
1919

2020
/codegen @larryliu0820 @lucylq
2121

@@ -47,32 +47,32 @@
4747
/extension/apple @shoumikhin
4848
/extension/aten_util @JacobSzwejbka
4949
/extension/benchmark @tarun292
50-
/extension/data_loader @JacobSzwejbka @lucylq @dbort
51-
/extension/evalue_util @GregoryComer @dbort
50+
/extension/data_loader @JacobSzwejbka @lucylq
51+
/extension/evalue_util @GregoryComer
5252
/extension/export_util @kimishpatel
5353
/extension/flat_tensor @lucylq
5454
/extension/gguf_util @larryliu0820
5555
/extension/kernel_util @kimishpatel @manuelcandales
5656
/extension/llm @jackzhxng @iseeyuan @larryliu0820
57-
/extension/memory_allocator @JacobSzwejbka @dbort
57+
/extension/memory_allocator @JacobSzwejbka
5858
/extension/module @shoumikhin
5959
/extension/parallel @kimishpatel
6060
/extension/pybindings @JacobSzwejbka @larryliu0820
6161
/extension/pytree @JacobSzwejbka
62-
/extension/runner_util @dbort
62+
# /extension/runner_util @dbort
6363
/extension/tensor @shoumikhin
64-
/extension/testing_util @dbort
64+
# /extension/testing_util @dbort
6565
/extension/threadpool @kimishpatel
6666
/extension/training @JacobSzwejbka
6767

6868
/kernels @manuelcandales
6969

7070
/profiler @tarun292 @Gasoonjia
7171

72-
/runtime @dbort @JacobSzwejbka @lucylq
72+
/runtime @JacobSzwejbka @lucylq
7373
/runtime/backend @cccclai
7474

75-
/schema @dbort @JacobSzwejbka @lucylq
75+
/schema @JacobSzwejbka @lucylq
7676

7777
/scripts @GregoryComer
7878

backends/apple/coreml/test/test_coreml_partitioner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def forward(self, q, k, v, mask):
117117
v = torch.randn(batch_size, n_heads, max_seq_length, embedding_dim)
118118
mask = torch.randn(seq_len, max_seq_length)
119119
example_inputs = (q, k, v, mask)
120-
ep = torch.export.export(model, example_inputs)
120+
ep = torch.export.export(model, example_inputs, strict=True)
121121
coreml_partitioner = CoreMLPartitioner()
122122

123123
# Using to_edge_transform_and_lower, we expect SDPA will be preserved and show up in delegated graph

backends/apple/mps/runtime/MPSBackend.mm

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,11 @@ bool is_available() const override {
4343
BackendInitContext& context,
4444
FreeableBuffer* processed,
4545
ArrayRef<CompileSpec> compile_specs) const override {
46-
auto executor = ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(
47-
context.get_runtime_allocator(), mps::delegate::MPSExecutor);
46+
auto executor = context.get_runtime_allocator()->allocateInstance<mps::delegate::MPSExecutor>();
47+
if (executor == nullptr) {
48+
return Error::MemoryAllocationFailed;
49+
}
50+
4851
// NOTE: Since we use placement new and since this type is not trivially
4952
// destructible, we must call the destructor manually in destroy().
5053
new (executor) mps::delegate::MPSExecutor;

backends/arm/runtime/EthosUBackend.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,11 @@ class EthosUBackend final : public ::executorch::runtime::BackendInterface {
120120
}
121121

122122
MemoryAllocator* allocator = context.get_runtime_allocator();
123-
ExecutionHandle* handle =
124-
ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(allocator, ExecutionHandle);
123+
ExecutionHandle* handle = allocator->allocateInstance<ExecutionHandle>();
124+
if (handle == nullptr) {
125+
return Error::MemoryAllocationFailed;
126+
}
127+
125128
handle->processed = processed;
126129

127130
// Return the same buffer we were passed - this data will be

backends/cadence/aot/remove_ops.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -807,6 +807,72 @@ def remove_branched(
807807
user.replace_all_uses_with(node.args[0])
808808

809809

810+
class RemoveCatFromSliceCopyPass(ExportPass):
811+
def _remove_unused_cat(self, graph_module: torch.fx.GraphModule) -> None:
812+
slice_copy_nodes = [
813+
node
814+
for node in graph_module.graph.nodes
815+
if node.target == exir_ops.edge.aten.slice_copy.Tensor
816+
]
817+
for slice_copy_node in slice_copy_nodes:
818+
slice_dim, start_idx, end_idx, step = 0, 0, float("inf"), 1
819+
input_node, *other_args = slice_copy_node.args
820+
if len(other_args) >= 1:
821+
slice_dim = other_args[0]
822+
if len(other_args) >= 2:
823+
start_idx = other_args[1]
824+
if len(other_args) >= 3:
825+
end_idx = other_args[2]
826+
if len(other_args) >= 4:
827+
step = other_args[3]
828+
if step != 1:
829+
continue
830+
slice_copy_dtype = slice_copy_node.meta["val"].dtype
831+
if input_node.target != exir_ops.edge.aten.cat.default:
832+
continue
833+
cat_dtype = input_node.meta["val"].dtype
834+
if slice_copy_dtype != cat_dtype:
835+
continue
836+
cat_dim = input_node.args[1:]
837+
if len(cat_dim) == 0:
838+
cat_dim = 0
839+
if cat_dim != slice_dim:
840+
continue
841+
cat_output_shape = input_node.meta["val"].shape
842+
start_idx = (
843+
cat_output_shape[cat_dim] + start_idx if start_idx < 0 else start_idx
844+
)
845+
end_idx = (
846+
cat_output_shape[cat_dim]
847+
if end_idx > cat_output_shape[cat_dim]
848+
else end_idx
849+
)
850+
base_idx = 0
851+
cat_input_to_keep = None
852+
for cat_input_node in input_node.args[0]:
853+
cat_input_dtype = cat_input_node.meta["val"].dtype
854+
if slice_copy_dtype != cat_input_dtype:
855+
continue
856+
cat_input_shape = cat_input_node.meta["val"].shape
857+
858+
# check if the slice range overlaps with the cat range
859+
if (
860+
base_idx <= start_idx
861+
and end_idx <= list(cat_input_shape)[cat_dim] + base_idx
862+
):
863+
cat_input_to_keep = cat_input_node
864+
break
865+
base_idx += list(cat_input_shape)[cat_dim]
866+
if cat_input_to_keep is not None:
867+
slice_copy_node.replace_input_with(input_node, cat_input_to_keep)
868+
869+
def call(self, graph_module: torch.fx.GraphModule) -> PassResult:
870+
self._remove_unused_cat(graph_module)
871+
graph_module.recompile()
872+
graph_module.graph.eliminate_dead_code()
873+
return super().call(graph_module)
874+
875+
810876
# The following class consolidates functions to remove ops that are redundant
811877
# in Jarvis. Currently, each function in this class iterates over each node of
812878
# the graph module once. In future, we could consolidate them into a monolithic

backends/cadence/aot/tests/test_remove_ops_passes.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
from executorch.backends.cadence.aot.remove_ops import (
2323
RemoveAliasCopyOpPass,
2424
RemoveBranchedQuantDequant,
25+
RemoveCatFromSliceCopyPass,
2526
RemoveCloneOpPass,
2627
RemoveContiguousOpPass,
2728
RemoveDetachCopyPass,
@@ -741,3 +742,54 @@ def forward(self, x):
741742
},
742743
)
743744
)
745+
746+
def test_remove_cat_from_slice_copy_all_removal(self) -> None:
747+
class M(torch.nn.Module):
748+
def __init__(self):
749+
super().__init__()
750+
751+
def forward(self, x, y):
752+
x1 = torch.cat((x, y), 0) # (2, 4)
753+
return torch.slice_copy(x1, dim=0, start=0, end=1)
754+
755+
inputs = tuple(torch.randn(2, 4) for _ in range(2))
756+
graph_module = export_to_edge(M(), inputs).exported_program().graph_module
757+
p = RemoveCatFromSliceCopyPass()
758+
graph_module = cast(PassResult, p(graph_module)).graph_module
759+
760+
# Ensure both cat nodes were removed
761+
self.assertEqual(count_node(graph_module, exir_ops.edge.aten.cat.default), 0)
762+
763+
def test_remove_cat_from_slice_copy_no_removal(self) -> None:
764+
class M(torch.nn.Module):
765+
def __init__(self):
766+
super().__init__()
767+
768+
def forward(self, x, y):
769+
x1 = torch.cat((x, y), 0) # (2, 4)
770+
return torch.slice_copy(x1, dim=0, start=0, end=3)
771+
772+
inputs = tuple(torch.randn(2, 4) for _ in range(2))
773+
graph_module = export_to_edge(M(), inputs).exported_program().graph_module
774+
p = RemoveCatFromSliceCopyPass()
775+
graph_module = cast(PassResult, p(graph_module)).graph_module
776+
777+
# Ensure both cat nodes were removed
778+
self.assertEqual(count_node(graph_module, exir_ops.edge.aten.cat.default), 1)
779+
780+
def test_remove_cat_from_slice_copy_zero_range(self) -> None:
781+
class M(torch.nn.Module):
782+
def __init__(self):
783+
super().__init__()
784+
785+
def forward(self, x, y):
786+
x1 = torch.cat((x, y), 0) # (2, 4)
787+
return torch.slice_copy(x1, dim=0, start=0, end=0)
788+
789+
inputs = tuple(torch.randn(2, 4) for _ in range(2))
790+
graph_module = export_to_edge(M(), inputs).exported_program().graph_module
791+
p = RemoveCatFromSliceCopyPass()
792+
graph_module = cast(PassResult, p(graph_module)).graph_module
793+
794+
# Ensure both cat nodes were removed
795+
self.assertEqual(count_node(graph_module, exir_ops.edge.aten.cat.default), 0)

backends/mediatek/runtime/NeuronBackend.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ Result<DelegateHandle*> NeuronBackend::init(
6868
processed->size());
6969

7070
MemoryAllocator* runtime_allocator = context.get_runtime_allocator();
71-
NeuronExecuTorchDelegate* delegate = ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(
72-
runtime_allocator, NeuronExecuTorchDelegate);
71+
NeuronExecuTorchDelegate* delegate =
72+
runtime_allocator->allocateInstance<NeuronExecuTorchDelegate>();
73+
if (delegate == nullptr) {
74+
return Error::MemoryAllocationFailed;
75+
}
76+
7377
new (delegate) NeuronExecuTorchDelegate();
7478

7579
if (delegate == nullptr) {

backends/qualcomm/_passes/decompose_any.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ def call(self, graph_module: torch.fx.GraphModule) -> PassResult:
4141
keepdim = node.args[2] if len(node.args) > 2 else False
4242
model = Any(dim, keepdim)
4343
edge_mgr = to_edge(
44-
torch.export.export(model, (node.args[0].meta["val"],))
44+
torch.export.export(model, (node.args[0].meta["val"],), strict=True)
4545
)
4646
decomposed_module = edge_mgr.exported_program()
4747

backends/qualcomm/_passes/decompose_linalg_vector_norm.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ def call(self, graph_module: torch.fx.GraphModule) -> PassResult:
4646
model = LinalgVectorNorm(ord, dim, keepdim)
4747
if self.aten_dialect_capture:
4848
decomposed_module = torch.export.export(
49-
model, (node.args[0].meta["val"],)
49+
model, (node.args[0].meta["val"],), strict=True
5050
).module()
5151
else:
5252
edge_mgr = to_edge(
53-
torch.export.export(model, (node.args[0].meta["val"],))
53+
torch.export.export(
54+
model, (node.args[0].meta["val"],), strict=True
55+
)
5456
)
5557
decomposed_module = edge_mgr.exported_program()
5658

backends/qualcomm/runtime/QnnExecuTorchBackend.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ Result<DelegateHandle*> QnnExecuTorchBackend::init(
6666

6767
// Create QnnManager
6868
MemoryAllocator* runtime_allocator = context.get_runtime_allocator();
69-
QnnManager* qnn_manager =
70-
ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(runtime_allocator, QnnManager);
69+
QnnManager* qnn_manager = runtime_allocator->allocateInstance<QnnManager>();
70+
if (qnn_manager == nullptr) {
71+
return Error::MemoryAllocationFailed;
72+
}
7173

7274
// NOTE: Since we use placement new and since this type is not trivially
7375
// destructible, we must call the destructor manually in destroy().

backends/qualcomm/tests/utils.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,9 @@ def get_qdq_module(
526526
dynamic_shapes: Dict = None,
527527
bypass_check: bool = False,
528528
) -> torch.fx.GraphModule:
529-
m = torch.export.export(module, inputs, dynamic_shapes=dynamic_shapes).module()
529+
m = torch.export.export(
530+
module, inputs, dynamic_shapes=dynamic_shapes, strict=True
531+
).module()
530532

531533
quantizer = QnnQuantizer()
532534
quantizer.add_custom_quant_annotations(custom_quant_annotations)

backends/qualcomm/utils/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ def capture_program(
452452
dynamic_shapes: Dict = None,
453453
) -> exir.ExirExportedProgram:
454454
module = _preprocess_module(module, inputs)
455-
ep = torch.export.export(module, inputs, dynamic_shapes=dynamic_shapes)
455+
ep = torch.export.export(module, inputs, dynamic_shapes=dynamic_shapes, strict=True)
456456
decomposed_ep = ep.run_decompositions(get_decomp_table())
457457
core_ep = ExirExportedProgram(decomposed_ep, False)
458458
core_ep.transform(TensorI64toI32(edge_program=core_ep))

backends/transforms/test/test_rank_0_to_rank_1.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ def forward(self, x, y):
1717
model.eval()
1818

1919
example_inputs = (torch.tensor(1.0), torch.tensor(2.0))
20-
aten = torch.export.export(model, example_inputs)
20+
aten = torch.export.export(model, example_inputs, strict=True)
2121

2222
# Check that the input rank is 0
2323
for node in aten.graph.nodes:

backends/vulkan/op_registry.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,6 @@ def register_view_op(features: OpFeatures):
530530
exir_ops.edge.aten.flip.default,
531531
exir_ops.edge.aten.index_select.default,
532532
exir_ops.edge.aten.select_copy.int,
533-
exir_ops.edge.aten.slice_copy.Tensor,
534533
# Tensor combination
535534
exir_ops.edge.aten.cat.default,
536535
exir_ops.edge.aten.split_with_sizes_copy.default,
@@ -557,6 +556,19 @@ def register_ported_op(features: OpFeatures):
557556
return features
558557

559558

559+
@update_features(
560+
[
561+
# Indexing and lookup
562+
exir_ops.edge.aten.slice_copy.Tensor,
563+
]
564+
)
565+
def register_ported_op_all_packed_dims(features: OpFeatures):
566+
features.texture_impl = TextureImplFeatures(
567+
valid_packed_dims=all_packed_dims,
568+
)
569+
return features
570+
571+
560572
# Ported ops that support their own prepacking.
561573
@update_features(
562574
[

backends/vulkan/runtime/VulkanBackend.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -510,8 +510,11 @@ class VulkanBackend final : public ::executorch::runtime::BackendInterface {
510510
BackendInitContext& context,
511511
FreeableBuffer* processed,
512512
ArrayRef<CompileSpec> compile_specs) const override {
513-
ComputeGraph* compute_graph = ET_ALLOCATE_INSTANCE_OR_RETURN_ERROR(
514-
context.get_runtime_allocator(), ComputeGraph);
513+
ComputeGraph* compute_graph =
514+
context.get_runtime_allocator()->allocateInstance<ComputeGraph>();
515+
if (compute_graph == nullptr) {
516+
return Error::MemoryAllocationFailed;
517+
}
515518

516519
new (compute_graph) ComputeGraph(get_graph_config(compile_specs));
517520

backends/vulkan/runtime/gen_vulkan_spv.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,12 @@ def process_shader(shader_paths_pair):
769769
+ self.glslc_flags.split()
770770
)
771771

772-
subprocess.check_call(cmd)
772+
try:
773+
subprocess.check_call(cmd)
774+
except subprocess.CalledProcessError as e:
775+
raise RuntimeError(
776+
f"Failed to compile {os.getcwd()}/{glsl_out_path}"
777+
) from e
773778

774779
return (spv_out_path, glsl_out_path)
775780

0 commit comments

Comments
 (0)