From e08a5335cde92a1274a09d5102eeb8f38666e634 Mon Sep 17 00:00:00 2001 From: Zhendong404 Date: Fri, 4 Sep 2026 09:29:25 +0800 Subject: [PATCH 1/3] docs(vmi): clarify signless vcvt semantics --- docs/isa/vmi-isa/06-convert.md | 5 ++--- ptodsl/docs/user_guide/14-vmi-virtual-instruction-set.md | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/docs/isa/vmi-isa/06-convert.md b/docs/isa/vmi-isa/06-convert.md index 55159250eb..cb9ac3f202 100644 --- a/docs/isa/vmi-isa/06-convert.md +++ b/docs/isa/vmi-isa/06-convert.md @@ -58,9 +58,9 @@ | Attribute | Values | Valid for | Description | |---|---|---|---| | `rounding` | `"R"` (nearest-even), `"A"` (away-from-zero), `"H"` (half-up), `"Z"` (toward-zero); for the `bf16x2→f4x2` contract pair the allowed set is `"R"`,`"A"`,`"F"` (floor), `"C"` (ceil), `"Z"` (toward-zero) — `"H"` is **rejected** | fp narrowing | Rounding mode | - | `saturate` | `"SAT"`, `"NOSAT"` | required for fp-narrow / int-narrow; for fp→si / fp→ui the requirement follows the vcvt contract's `requiresSat` (e.g. `f16→s8` required, `f16→s32` **forbidden** — no overflow possible; same-width `bf16→f16` required, same-width `f16→bf16` **forbidden**); the `bf16x2→f4x2` narrow has `requiresSat=false` — any `saturate` is **forbidden** | `SAT` clamps to ±max of the destination type; `NOSAT` performs a direct bit truncation of the result representation. | + | `saturate` | `"SAT"`, `"NOSAT"` | required for fp-narrow / int-narrow; for fp→si / fp→ui the requirement follows the vcvt contract's `requiresSat` (e.g. `f16→s8` required, `f16→s32` **forbidden** — no overflow possible; same-width `bf16→f16` required, same-width `f16→bf16` **forbidden**); the `bf16x2→f4x2` narrow has `requiresSat=false` — any `saturate` is **forbidden** | For signed destinations, `SAT` clamps to `[min, max]`; for unsigned or signless destinations, it clamps to `[0, max]`. `NOSAT` performs a direct bit truncation of the result representation. | -- **datatypes:** Source and destination from `{f32, f16, bf16, fp8_e4m3, fp8_e5m2, i32, i16, i8, ui32, ui16, ui8}`; packed carrier types `{!pto.bf16x2, !pto.f4E1M2x2, !pto.f4E2M1x2}` for the bf16x2↔f4x2 fp-to-fp pair (see contract `lookupVMIFpToFpContract`). `bf16x2` is **conversion-only** — it may not appear as a compute element type (`vfadd`/`vfmul`/`vcmp`/...). +- **datatypes:** Source and destination from `{f32, f16, bf16, fp8_e4m3, fp8_e5m2, i32, i16, i8, si32, si16, si8, ui32, ui16, ui8}`; packed carrier types `{!pto.bf16x2, !pto.f4E1M2x2, !pto.f4E2M1x2}` for the bf16x2↔f4x2 fp-to-fp pair (see contract `lookupVMIFpToFpContract`). `bf16x2` is **conversion-only** — it may not appear as a compute element type (`vfadd`/`vfmul`/`vcmp`/...). Signless `iN` is treated as unsigned; use `siN` for signed conversion semantics. - **lowering to `pto.mi`:** | Conversion | Physical lowering | `#mi` | `dep` | @@ -128,7 +128,6 @@ - **notes:** - `vcvt` **does not change lane count** — `src.L == dst.L` always. The physical register count `K` changes because `bitwidth(T)` changes. - - Integer signedness is determined by the **element type**. - The `part`/`parity`/`width` axes are lowering-only; the user never writes `EVEN`/`ODD`/`P0..P3`. - Radix-4 (8↔32) is **not** a stacked predicate chain and **not** a UB diff --git a/ptodsl/docs/user_guide/14-vmi-virtual-instruction-set.md b/ptodsl/docs/user_guide/14-vmi-virtual-instruction-set.md index bfb21dd8f2..407a292962 100644 --- a/ptodsl/docs/user_guide/14-vmi-virtual-instruction-set.md +++ b/ptodsl/docs/user_guide/14-vmi-virtual-instruction-set.md @@ -881,8 +881,8 @@ group_max = pto.vmi.vcmax( Converts the element type of `source` to the target element type. PTODSL infers the result vector type from the source lane count/layout and `to_dtype`. -For int→int widening, the source element type must carry signedness -(e.g. `si8`/`ui8`/`si16`/`ui16`); signless integers are rejected. +For `vcvt`, signless integer types (`i8`/`i16`/`i32`) are treated as +unsigned. Use `siN` types for signed conversion semantics. **Parameters**: From 256a410fc9d3929cab306756209ed39b9404738d Mon Sep 17 00:00:00 2001 From: Zhendong404 Date: Fri, 4 Sep 2026 09:29:25 +0800 Subject: [PATCH 2/3] fix(vmi): preserve compact VL4 widening layout --- lib/PTO/Transforms/VMILayoutAssignment.cpp | 30 ++++++++++ .../vmi_new/vmi_to_vpto_extui_compact_vl4.pto | 56 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 test/lit/vmi_new/vmi_to_vpto_extui_compact_vl4.pto diff --git a/lib/PTO/Transforms/VMILayoutAssignment.cpp b/lib/PTO/Transforms/VMILayoutAssignment.cpp index 186e0b7eff..9488692d70 100644 --- a/lib/PTO/Transforms/VMILayoutAssignment.cpp +++ b/lib/PTO/Transforms/VMILayoutAssignment.cpp @@ -29,6 +29,8 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TypeSwitch.h" +#include + namespace mlir { namespace pto { #define GEN_PASS_DEF_VMILAYOUTASSIGNMENT @@ -693,6 +695,34 @@ struct LayoutSolver { WalkResult addExtensionConstraint(CastOp castOp, Operation *op) { auto sourceType = cast(castOp.getSource().getType()); auto resultType = cast(castOp.getResult().getType()); + + // A four-lane byte/halfword -> ui32 widening is a compact group-slot + // operation. Seed the result with the group-slot carrier so propagation + // selects the existing group-slot extension lowering (and avoids creating + // an unsupported group-slot -> dense lane-stride ensure_layout). + if constexpr (std::is_same_v) { + auto sourceInteger = dyn_cast(sourceType.getElementType()); + auto resultInteger = dyn_cast(resultType.getElementType()); + unsigned sourceBits = + pto::getPTOStorageElemBitWidth(sourceType.getElementType()); + unsigned resultBits = + pto::getPTOStorageElemBitWidth(resultType.getElementType()); + bool compactUI32Widen = + sourceType.getElementCount() == 4 && sourceInteger && resultInteger && + !sourceType.getLayoutAttr() && !resultType.getLayoutAttr() && + (resultInteger.isUnsigned() || resultInteger.isSignless()) && + (sourceBits == 8 || sourceBits == 16) && + resultBits == 32; + if (compactUI32Widen) { + VMILayoutAttr compactLayout = + VMILayoutAttr::getGroupSlots(ctx, /*numGroups=*/4, + /*slots=*/mlir::pto::kValue8); + return *constraintResult(setPreferredLayout( + castOp.getResult(), compactLayout, op, + DataLayoutSeedPhase::CompactCast)); + } + } + FailureOr fact = VMILayoutSupport().getPreferredCastLayoutFact(sourceType, resultType); if (failed(fact)) { diff --git a/test/lit/vmi_new/vmi_to_vpto_extui_compact_vl4.pto b/test/lit/vmi_new/vmi_to_vpto_extui_compact_vl4.pto new file mode 100644 index 0000000000..2d18a5fc5d --- /dev/null +++ b/test/lit/vmi_new/vmi_to_vpto_extui_compact_vl4.pto @@ -0,0 +1,56 @@ +// Copyright (c) 2026 Huawei Technologies Co., Ltd. +// This program is free software, you can redistribute it and/or modify it under +// the terms and conditions of the CANN Open Software License Agreement Version 2.0 +// (the "License"). Please refer to the License for details. You may not use +// this file except in compliance with the License. THIS SOFTWARE IS PROVIDED ON +// AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +// or implied. See the License for the specific language governing permissions and +// limitations under the License. See LICENSE in the root of the software repository +// for the full text of the License. + +// RUN: pto-test-opt %s -vmi-lower-unified-to-legacy -vmi-mask-granularity-assignment -vmi-layout-assignment | FileCheck %s --check-prefix=ASSIGN +// RUN: pto-test-opt %s -vmi-lower-unified-to-legacy -vmi-mask-granularity-assignment -vmi-layout-assignment -vmi-to-vpto | FileCheck %s --check-prefix=LOWER + +module { + func.func @extui_compact_vl4( + %src: !pto.ptr, %dst: !pto.ptr, %off: index) { + %c1 = arith.constant 1 : index + %value = pto.vmi.vload %src[%off], %c1 {group = 4} + : !pto.ptr -> !pto.vmi.vreg<4xi8> + %wide = pto.vmi.vcvt %value + : !pto.vmi.vreg<4xi8> -> !pto.vmi.vreg<4xui32> + pto.vmi.vstore %wide, %dst[%off], %c1 {group = 4} + : !pto.vmi.vreg<4xui32>, !pto.ptr + return + } + + func.func @extui_compact_vl4_i16( + %src: !pto.ptr, %dst: !pto.ptr, %off: index) { + %c1 = arith.constant 1 : index + %value = pto.vmi.vload %src[%off], %c1 {group = 4} + : !pto.ptr -> !pto.vmi.vreg<4xi16> + %wide = pto.vmi.vcvt %value + : !pto.vmi.vreg<4xi16> -> !pto.vmi.vreg<4xui32> + pto.vmi.vstore %wide, %dst[%off], %c1 {group = 4} + : !pto.vmi.vreg<4xui32>, !pto.ptr + return + } +} + +// ASSIGN-LABEL: func.func @extui_compact_vl4( +// ASSIGN: %[[WIDE:.*]] = pto.vmi.extui %{{.*}} : !pto.vmi.vreg<4xi8, #pto.vmi.layout> -> !pto.vmi.vreg<4xui32, #pto.vmi.layout> + +// ASSIGN-LABEL: func.func @extui_compact_vl4_i16( +// ASSIGN: %[[WIDE16:.*]] = pto.vmi.extui %{{.*}} : !pto.vmi.vreg<4xi16, #pto.vmi.layout> -> !pto.vmi.vreg<4xui32, #pto.vmi.layout> + +// LOWER-LABEL: func.func @extui_compact_vl4( +// LOWER-COUNT-2: pto.vzunpack +// LOWER: pto.vstus +// LOWER-NOT: pto.vmi. +// LOWER-NOT: unrealized_conversion_cast + +// LOWER-LABEL: func.func @extui_compact_vl4_i16( +// LOWER: pto.vzunpack +// LOWER: pto.vstus +// LOWER-NOT: pto.vmi. +// LOWER-NOT: unrealized_conversion_cast From ff89671a3b4d244553d48130cf5732dd554c20e2 Mon Sep 17 00:00:00 2001 From: Zhendong404 Date: Sat, 5 Sep 2026 00:06:56 +0800 Subject: [PATCH 3/3] ci: repair GitHub mirror build checks - Refresh the ptoas-vmi pyproject patch for the current requires-python floor. - Set legacy CMake policies before fetching cann-cmake and default the third-party directory into the writable CMake binary tree when unset. --- CMakeLists.txt | 4 ++-- cmake/fetch_cann_cmake.cmake | 9 +++++++-- packaging/ptoas-vmi/pyproject.toml.patch | 19 +++++++++++++------ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3a777acbf..ab1deb95a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,8 +8,6 @@ cmake_minimum_required(VERSION 3.20.0) -include(cmake/fetch_cann_cmake.cmake) - # CANN/Ascend CMake packages used by downstream PTOAS builds may still use the # pre-CMake-3.30 FetchContent_Populate() pattern. Keep that # compatibility path enabled so CMake 4.x developer warnings do not become @@ -29,6 +27,8 @@ if(POLICY CMP0175) set(CMAKE_POLICY_DEFAULT_CMP0175 OLD) endif() +include(cmake/fetch_cann_cmake.cmake) + # Standard Python build backends pass environment variables through to CMake # but do not synthesize project-specific cache arguments. Accept the existing # LLVM_BUILD_DIR convention directly so `pip wheel .` and `pip install .` can diff --git a/cmake/fetch_cann_cmake.cmake b/cmake/fetch_cann_cmake.cmake index 8a79b55e12..48b4bf0c42 100644 --- a/cmake/fetch_cann_cmake.cmake +++ b/cmake/fetch_cann_cmake.cmake @@ -1,4 +1,3 @@ -# ----------------------------------------------------------------------------------------------------------- # Copyright (c) 2026 Huawei Technologies Co., Ltd. # This program is free software, you can redistribute it and/or modify it under the terms and conditions of # CANN Open Software License Agreement Version 2.0 (the "License"). @@ -6,9 +5,15 @@ # THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -# ----------------------------------------------------------------------------------------------------------- if(NOT PROJECT_SOURCE_DIR) + # Standalone builds may configure without a pre-seeded CANN third-party + # directory (e.g. CI). Keep FetchContent's declared SOURCE_DIR inside the + # writable CMake binary tree instead of resolving an empty variable to the + # filesystem root. Script-mode packaging still requires an explicit path. + if(NOT CANN_3RD_LIB_PATH AND CMAKE_BINARY_DIR) + set(CANN_3RD_LIB_PATH "${CMAKE_BINARY_DIR}/cann-3rd-lib") + endif() # Temporary test pin for cann/cmake MR !277. Revert this URL/ref pair # after validation and switch to the released cann/cmake tag once MR !277 # is merged. diff --git a/packaging/ptoas-vmi/pyproject.toml.patch b/packaging/ptoas-vmi/pyproject.toml.patch index f2f71ec41c..0d78bead16 100644 --- a/packaging/ptoas-vmi/pyproject.toml.patch +++ b/packaging/ptoas-vmi/pyproject.toml.patch @@ -1,7 +1,9 @@ diff --git a/pyproject.toml b/pyproject.toml --- a/pyproject.toml +++ b/pyproject.toml -@@ -18,7 +18,7 @@ build-backend = "scikit_build_core.build" +@@ -16,11 +16,11 @@ + build-backend = "scikit_build_core.build" + [project] -name = "ptoas" -dynamic = ["version"] @@ -10,20 +12,25 @@ diff --git a/pyproject.toml b/pyproject.toml +version = "0.1.6" +description = "PTO Assembler & Optimizer with VMI support" readme = "README.md" - requires-python = ">=3.10" +-requires-python = ">=3.7" ++requires-python = ">=3.10" license = "Apache-2.0" -@@ -43,4 +43,5 @@ cmake.version = "CMakeLists.txt" + dependencies = [ + "numpy", +@@ -43,6 +43,7 @@ ninja.version = ">=1.10" build.verbose = false editable.mode = "redirect" +sdist.inclusion-mode = "manual" install.components = ["PTOAS_Python"] -@@ -53,3 +54,4 @@ TileOps = "lib/TileOps" + + [tool.scikit-build.wheel.packages] +@@ -53,8 +54,5 @@ + [tool.scikit-build.cmake.define] PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", default = "" } +PTOAS_CLI_VERSION_LABEL = "vmi" - -@@ -56,4 +58,0 @@ PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", default = "" } + -[tool.scikit-build.metadata.version] -provider = "scikit_build_core.metadata.regex" -input = "CMakeLists.txt"