diff --git a/src/xtc/backends/mlir/MlirTarget/MlirCTarget.py b/src/xtc/backends/mlir/MlirTarget/MlirCTarget.py index 4e681694..c28a1979 100644 --- a/src/xtc/backends/mlir/MlirTarget/MlirCTarget.py +++ b/src/xtc/backends/mlir/MlirTarget/MlirCTarget.py @@ -32,6 +32,7 @@ from xtc.itf.graph import Graph from .MlirTarget import MlirTarget +from .cpu_lowering import cpu_frontend_lowering from ..MlirConfig import MlirConfig from ..MlirProgram import RawMlirProgram @@ -265,31 +266,10 @@ def __init__( self._mlir_program = mlir_program def _lowering_pipeline(self) -> list[str]: - pipeline = [ - "canonicalize", - "cse", - "sccp", - ] - if "sdist" in self._mlir_program.mlir_extensions: - pipeline += [ - "sdist-lower-distribution", - "convert-sdist-to-std", - "cse", - "canonicalize", - "convert-sdist-utils-to-std", - ] - pipeline += [ - # From complex control to the soup of basic blocks - "expand-strided-metadata", - "convert-linalg-to-loops", - "lower-affine", - "convert-vector-to-scf{full-unroll=true}", - "scf-forall-to-parallel", - "convert-scf-to-openmp", - "canonicalize", - "cse", - "sccp", - # "convert-scf-to-cf", + return cpu_frontend_lowering( + self._mlir_program.mlir_extensions, uplift_fma=False + ) + [ + # convert-scf-to-cf is intentionally skipped: the C emitter keeps scf "canonicalize", "cse", "sccp", @@ -299,7 +279,6 @@ def _lowering_pipeline(self) -> list[str]: "cse", "sccp", ] - return pipeline def run(self) -> None: pm = PassManager(context=self._mlir_program.mlir_context) diff --git a/src/xtc/backends/mlir/MlirTarget/MlirLLVMTarget.py b/src/xtc/backends/mlir/MlirTarget/MlirLLVMTarget.py index b98997fa..13c7f8fa 100644 --- a/src/xtc/backends/mlir/MlirTarget/MlirLLVMTarget.py +++ b/src/xtc/backends/mlir/MlirTarget/MlirLLVMTarget.py @@ -33,6 +33,7 @@ from xtc.itf.graph import Graph from .MlirTarget import MlirTarget +from .cpu_lowering import cpu_frontend_lowering from ..MlirConfig import MlirConfig from ..MlirProgram import RawMlirProgram @@ -277,32 +278,9 @@ def __init__( self._mlir_program = mlir_program def _lowering_pipeline(self) -> list[str]: - pipeline = [ - "canonicalize", - "cse", - "sccp", - ] - if "sdist" in self._mlir_program.mlir_extensions: - pipeline += [ - "sdist-lower-distribution", - "convert-sdist-to-std", - "cse", - "canonicalize", - "convert-sdist-utils-to-std", - ] - pipeline += [ - # From complex control to the soup of basic blocks - "math-uplift-to-fma", - "expand-strided-metadata", - "convert-linalg-to-loops", - "lower-affine", - "func.func(lower-vector-mask)", - "convert-vector-to-scf{full-unroll=true}", - "scf-forall-to-parallel", - "convert-scf-to-openmp", - "canonicalize", - "cse", - "sccp", + return cpu_frontend_lowering( + self._mlir_program.mlir_extensions, uplift_fma=True + ) + [ "convert-scf-to-cf", "canonicalize", "cse", @@ -330,7 +308,6 @@ def _lowering_pipeline(self) -> list[str]: "cse", "sccp", ] - return pipeline def run(self) -> None: pm = PassManager(context=self._mlir_program.mlir_context) diff --git a/src/xtc/backends/mlir/MlirTarget/cpu_lowering.py b/src/xtc/backends/mlir/MlirTarget/cpu_lowering.py new file mode 100644 index 00000000..ec01d10b --- /dev/null +++ b/src/xtc/backends/mlir/MlirTarget/cpu_lowering.py @@ -0,0 +1,43 @@ +# +# SPDX-License-Identifier: BSD-3-Clause +# Copyright (c) 2024-2026 The XTC Project Authors +# + + +def cpu_frontend_lowering(mlir_extensions: list[str], *, uplift_fma: bool) -> list[str]: + """Shared CPU lowering prefix for the LLVM and C targets. + + Lowers linalg/vector down to scf, before the target-specific transformations. + + Args: + mlir_extensions: extensions required by the program + uplift_fma: whether to uplift ``mul``+``add`` to ``fma`` + + Returns: + The ordered list of pass names for the shared front-end lowering. + """ + pipeline = ["canonicalize", "cse", "sccp"] + if "sdist" in mlir_extensions: + pipeline += [ + "sdist-lower-distribution", + "convert-sdist-to-std", + "cse", + "canonicalize", + "convert-sdist-utils-to-std", + ] + if uplift_fma: + pipeline.append("math-uplift-to-fma") + pipeline += [ + # From complex control to the soup of basic blocks + "expand-strided-metadata", + "convert-linalg-to-loops", + "lower-affine", + "func.func(lower-vector-mask)", + "convert-vector-to-scf{full-unroll=true}", + "scf-forall-to-parallel", + "convert-scf-to-openmp", + "canonicalize", + "cse", + "sccp", + ] + return pipeline