Skip to content

Commit 8077bb6

Browse files
authored
Revert "Reland "Arm backend: Add transpose propagation pass" (pytorch#20748)"
Differential Revision: D112005256 Pull Request resolved: pytorch#20947
1 parent 7bb34e1 commit 8077bb6

9 files changed

Lines changed: 28 additions & 2632 deletions

backends/arm/_passes/__init__.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,6 @@
155155
)
156156
from .normalize_while_initial_args_pass import NormalizeWhileInitialArgsPass # noqa
157157
from .promote_bool_operands_pass import PromoteBoolOperandsPass # noqa
158-
from .propagate_view_copy_permute_pass import ( # noqa
159-
PropagateViewCopyPermuteDownPass,
160-
PropagateViewCopyPermuteUpPass,
161-
)
162158
from .remove_getitem_pass import RemoveGetItemPass # noqa
163159
from .remove_graph_asserts_pass import RemoveGraphAssertsPass # noqa
164160
from .remove_noop_pass import RemoveNoopPass # noqa

backends/arm/_passes/arm_pass_manager.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
AccumulateIndexPutPass,
1616
BroadcastArgsPass,
1717
CanonicalizeGatherPass,
18+
CanonicalizeViewCopyPermutePass,
1819
CastInt64BuffersToInt32Pass,
1920
CastToInt32Pass,
2021
ComputeConstantOpsAOTPass,
@@ -134,12 +135,11 @@
134135
NormalizeTransformInputPlaceholdersPass,
135136
NormalizeWhileInitialArgsPass,
136137
PromoteBoolOperandsPass,
137-
PropagateViewCopyPermuteDownPass,
138-
PropagateViewCopyPermuteUpPass,
139138
QuantizeClampArgumentsPass,
140139
RemoveGetItemPass,
141140
RemoveGraphAssertsPass,
142141
RemoveNoopPass,
142+
RemovePermutesAroundElementwiseTosaOps,
143143
ReplaceInfAndLimitValuesPass,
144144
ReplaceScalarWithTensorByProfilePass,
145145
RewriteAdaptiveAvgPool2dPass,
@@ -175,6 +175,9 @@
175175
TosaLoweringContext,
176176
TosaSpecification,
177177
)
178+
from executorch.backends.transforms.fuse_cascaded_transpose_or_permute_ops import (
179+
FuseCascadedTransposeOrPermuteOps,
180+
)
178181

179182
from executorch.exir import ExportedProgram
180183
from executorch.exir._program_utils import _get_updated_graph_signature
@@ -606,7 +609,6 @@ def _tosa_pipeline(
606609
RewriteAvgPool2dPass(),
607610
ComputeConstantOpsAOTPass(exported_program),
608611
FuseConstantArgsPass(exported_program),
609-
CastInt64BuffersToInt32Pass(exported_program),
610612
DecomposeSelectPass(),
611613
ConvertSqueezesToViewPass(),
612614
CastToInt32Pass(),
@@ -631,14 +633,14 @@ def _tosa_pipeline(
631633
RewriteMatmulPass(),
632634
RewritePadPass(),
633635
FuseViewCopyTransformPass(),
634-
PropagateViewCopyPermuteDownPass(self.compile_spec, exported_program),
635-
PropagateViewCopyPermuteUpPass(self.compile_spec, exported_program),
636+
RemovePermutesAroundElementwiseTosaOps(exported_program),
637+
CanonicalizeViewCopyPermutePass(),
638+
FuseCascadedTransposeOrPermuteOps(),
636639
RewriteHighRankSingletonPermutePass(),
637640
DecomposePermuteForU55Pass(),
638641
RewriteSlicePass(),
639642
FuseConsecutiveSlicesPass(),
640643
InsertConstShapesPass(),
641-
InsertDataLayoutCastsPass(),
642644
]
643645
)
644646

backends/arm/_passes/dim_maps.py

Lines changed: 6 additions & 263 deletions
Original file line numberDiff line numberDiff line change
@@ -306,28 +306,15 @@ def map_dim(
306306
return None
307307

308308
groups = self._valid_groups()
309-
if not self._is_valid_reduction_or_singleton(
310-
normalized_dims, groups.source_axis_to_groups
311-
):
309+
if not self._is_valid_reduction(normalized_dims, groups.source_axis_to_groups):
312310
return None
313311

314-
source_to_target_axes = self.source_to_target_axes()
315-
target_dims = sorted(
316-
_dedupe(
317-
target_axis
318-
for source_dim in normalized_dims
319-
for target_axis in source_to_target_axes[source_dim]
320-
)
312+
target_dims = self._map_dims(
313+
normalized_dims,
314+
groups.source_axis_to_groups,
315+
groups.group_to_target_axes,
321316
)
322-
if not target_dims or any(
323-
source_axis not in normalized_dims
324-
for target_axis in target_dims
325-
for source_axis in self.source_axes_for_target_axis(
326-
target_axis, source_to_target_axes
327-
)
328-
):
329-
return None
330-
if not self._is_valid_reduction_or_singleton(
317+
if not target_dims or not self._is_valid_reduction(
331318
target_dims, groups.target_axis_to_groups
332319
):
333320
return None
@@ -445,226 +432,6 @@ def map_permutation_inverse(
445432
else None
446433
)
447434

448-
def remap_target_shape(self, source_shape: Sequence[_Dim]) -> list[_Dim] | None:
449-
if len(source_shape) != self.source_rank:
450-
return None
451-
452-
source_to_target_axes = self.source_to_target_axes()
453-
target_to_source_axes = [
454-
self.source_axes_for_target_axis(target_axis, source_to_target_axes)
455-
for target_axis in range(self.target_rank)
456-
]
457-
target_shape: list[_Dim] = [1] * self.target_rank
458-
459-
for source_axis, target_axes in enumerate(source_to_target_axes):
460-
updates = self._target_axis_updates_for_source_axis(
461-
source_shape,
462-
source_axis,
463-
target_axes,
464-
target_to_source_axes,
465-
)
466-
if updates is None:
467-
return None
468-
for target_axis, target_dim in updates:
469-
target_shape[target_axis] = target_dim
470-
471-
if not same_numel(source_shape, target_shape):
472-
return None
473-
if not self._preserves_source_axis_order(source_shape, source_to_target_axes):
474-
return None
475-
return target_shape
476-
477-
def _target_axis_updates_for_source_axis(
478-
self,
479-
source_shape: Sequence[_Dim],
480-
source_axis: int,
481-
target_axes: Sequence[int],
482-
target_to_source_axes: Sequence[Sequence[int]],
483-
) -> list[tuple[int, _Dim]] | None:
484-
if not target_axes:
485-
return []
486-
487-
if len(target_axes) == 1:
488-
target_axis = target_axes[0]
489-
source_axes = target_to_source_axes[target_axis]
490-
if source_axis != source_axes[0]:
491-
return []
492-
target_dim = numel(source_shape[source_axis] for source_axis in source_axes)
493-
return [(target_axis, target_dim)]
494-
495-
if any(
496-
len(target_to_source_axes[target_axis]) > 1 for target_axis in target_axes
497-
):
498-
return []
499-
500-
target_dims = [self.target_shape[target_axis] for target_axis in target_axes]
501-
if _dim_equals(source_shape[source_axis], self.source_shape[source_axis]):
502-
return list(zip(target_axes, target_dims))
503-
if _dim_equals(numel(target_dims), 1):
504-
return [(target_axes[0], source_shape[source_axis])]
505-
if _dim_equals(numel(target_dims), self.source_shape[source_axis]):
506-
return list(zip(target_axes, target_dims))
507-
return None
508-
509-
def remap_unit_slice(
510-
self,
511-
producer_shape: Sequence[_Dim],
512-
slice_dim: int,
513-
start: _Dim,
514-
end: _Dim,
515-
step: _Dim = 1,
516-
) -> tuple[list[_Dim], int, _Dim, _Dim] | None:
517-
"""Move a view before a unit slice.
518-
519-
Returns the new view shape and slice interval for:
520-
521-
view(slice(x, dim, start, end), self.target_shape)
522-
== slice(view(x, new_shape), new_dim, new_start, new_end)
523-
524-
This handles the case where a unit slice produces a singleton source
525-
axis that the view removes, so normal source-to-target dim mapping has
526-
no target axis for the slice dim.
527-
528-
"""
529-
if (
530-
len(producer_shape) != self.source_rank
531-
or not isinstance(slice_dim, int)
532-
or not isinstance(start, (int, torch.SymInt))
533-
or not isinstance(end, (int, torch.SymInt))
534-
or not isinstance(step, (int, torch.SymInt))
535-
):
536-
return None
537-
if not _dim_equals(step, 1) or not _dim_equals(end - start, 1):
538-
return None
539-
540-
try:
541-
slice_dim = _normalize_dim(slice_dim, self.source_rank)
542-
except AssertionError:
543-
return None
544-
545-
source_to_target_axes = self.source_to_target_axes()
546-
if source_to_target_axes[slice_dim]:
547-
return None
548-
549-
prev_target_axes = [
550-
target_axis
551-
for target_axes in source_to_target_axes[:slice_dim]
552-
for target_axis in target_axes
553-
]
554-
next_target_axes = [
555-
target_axis
556-
for target_axes in source_to_target_axes[slice_dim + 1 :]
557-
for target_axis in target_axes
558-
]
559-
fold_axes = [
560-
target_axes[0]
561-
for target_axes in source_to_target_axes[slice_dim + 1 :]
562-
if target_axes
563-
]
564-
fold_axes = [
565-
target_axis
566-
for target_axis in fold_axes
567-
if all(
568-
prev_target_axis <= target_axis for prev_target_axis in prev_target_axes
569-
)
570-
and all(
571-
target_axis <= next_target_axis for next_target_axis in next_target_axes
572-
)
573-
]
574-
if not fold_axes:
575-
return None
576-
577-
fold_axis = fold_axes[0]
578-
target_shape = list(self.target_shape)
579-
chunk = target_shape[fold_axis]
580-
target_shape[fold_axis] = chunk * producer_shape[slice_dim]
581-
return target_shape, fold_axis, start * chunk, end * chunk
582-
583-
def source_to_target_axes(self) -> list[list[int]]:
584-
groups = self._valid_groups()
585-
source_to_target_axes = [
586-
self._map_dims(
587-
[source_axis],
588-
groups.source_axis_to_groups,
589-
groups.group_to_target_axes,
590-
)
591-
for source_axis in range(self.source_rank)
592-
]
593-
594-
self._add_singleton_axes(source_to_target_axes)
595-
return source_to_target_axes
596-
597-
def map_source_dims_to_target_axes(
598-
self, source_dims: int | Sequence[int]
599-
) -> list[int] | None:
600-
try:
601-
normalized_dims = _normalize_dims(source_dims, self.source_rank)
602-
except AssertionError:
603-
return None
604-
source_to_target_axes = self.source_to_target_axes()
605-
return _dedupe(
606-
target_axis
607-
for source_dim in normalized_dims
608-
for target_axis in source_to_target_axes[source_dim]
609-
)
610-
611-
@staticmethod
612-
def source_axes_for_target_axis(
613-
target_axis: int, source_to_target_axes: Sequence[Sequence[int]]
614-
) -> list[int]:
615-
return [
616-
source_axis
617-
for source_axis, target_axes in enumerate(source_to_target_axes)
618-
if target_axis in target_axes
619-
]
620-
621-
def _add_singleton_axes(self, source_to_target_axes: list[list[int]]) -> None:
622-
mapped_source_axes = {
623-
source_axis
624-
for source_axis, target_axes in enumerate(source_to_target_axes)
625-
if target_axes
626-
}
627-
mapped_target_axes = {
628-
target_axis
629-
for target_axes in source_to_target_axes
630-
for target_axis in target_axes
631-
}
632-
source_singletons = [
633-
axis
634-
for axis, dim in enumerate(self.source_shape)
635-
if axis not in mapped_source_axes and _dim_equals(dim, 1)
636-
]
637-
target_singletons = [
638-
axis
639-
for axis, dim in enumerate(self.target_shape)
640-
if axis not in mapped_target_axes and _dim_equals(dim, 1)
641-
]
642-
643-
if len(source_singletons) == len(target_singletons):
644-
pairs = zip(source_singletons, target_singletons)
645-
elif len(source_singletons) == 1:
646-
pairs = zip(source_singletons * len(target_singletons), target_singletons)
647-
elif len(target_singletons) == 1:
648-
pairs = zip(source_singletons, target_singletons * len(source_singletons))
649-
else:
650-
pairs = zip(source_singletons, target_singletons)
651-
652-
for source_axis, target_axis in pairs:
653-
source_to_target_axes[source_axis].append(target_axis)
654-
655-
@staticmethod
656-
def _preserves_source_axis_order(
657-
source_shape: Sequence[_Dim],
658-
source_to_target_axes: Sequence[Sequence[int]],
659-
) -> bool:
660-
target_axes = [
661-
target_axis
662-
for source_axis, axes in enumerate(source_to_target_axes)
663-
if not _dim_equals(source_shape[source_axis], 1)
664-
for target_axis in axes
665-
]
666-
return target_axes == sorted(target_axes)
667-
668435
@staticmethod
669436
def _map_dims(
670437
source_dims: Iterable[int],
@@ -786,30 +553,6 @@ def _is_valid_reduction(
786553
group_to_axes[group].issubset(normalized_dims) for group in selected_groups
787554
)
788555

789-
@staticmethod
790-
def _is_valid_reduction_or_singleton(
791-
normalized_dims: Iterable[int],
792-
axis_to_groups: Sequence[Sequence[int]],
793-
) -> bool:
794-
"""Return whether dims cover complete groups, allowing singleton
795-
axes.
796-
"""
797-
normalized_dims = set(normalized_dims)
798-
if not normalized_dims:
799-
return False
800-
801-
group_to_axes: dict[int, set[int]] = defaultdict(set)
802-
selected_groups: set[int] = set()
803-
for axis, groups in enumerate(axis_to_groups):
804-
for group in groups:
805-
group_to_axes[group].add(axis)
806-
if axis in normalized_dims:
807-
selected_groups.add(group)
808-
809-
return all(
810-
group_to_axes[group].issubset(normalized_dims) for group in selected_groups
811-
)
812-
813556
@classmethod
814557
def _build_groups(
815558
cls, source_shape: Sequence[_Dim], target_shape: Sequence[_Dim]

backends/arm/_passes/insert_data_layout_casts_pass.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ class InsertDataLayoutCastsPass(ArmOpTargetedPass):
3636
_concat_ops = {
3737
exir_ops.edge.aten.cat.default,
3838
exir_ops.edge.aten.concatenate.default,
39-
exir_ops.backend.tosa.CONCAT.default,
4039
}
4140
_single_input_ops = {
4241
exir_ops.edge.aten.constant_pad_nd.default,
@@ -45,12 +44,6 @@ class InsertDataLayoutCastsPass(ArmOpTargetedPass):
4544
exir_ops.edge.aten.permute_copy.default,
4645
exir_ops.edge.aten.slice_copy.Tensor,
4746
exir_ops.edge.aten.flip.default,
48-
exir_ops.backend.tosa.PAD.default,
49-
exir_ops.backend.tosa.RESHAPE.default,
50-
exir_ops.backend.tosa.TILE.default,
51-
exir_ops.backend.tosa.TRANSPOSE.default,
52-
exir_ops.backend.tosa.SLICE.default,
53-
exir_ops.backend.tosa.REVERSE.default,
5447
}
5548
target_ops = _concat_ops | _single_input_ops
5649

0 commit comments

Comments
 (0)