From 0de17c9e0fe6d1a40e2a485bb6f94cd198f67974 Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 00:50:40 +0000 Subject: [PATCH 1/8] [llvm] add build script for internal llvm --- scripts/build_internal_flydsl.sh | 151 +++++++++++++++++++++++ scripts/build_internal_llvm.sh | 149 ++++++++++++++++++++++ thirdparty/internal-llvm-build-info.json | 6 + thirdparty/llvm-build-info.json | 5 + 4 files changed, 311 insertions(+) create mode 100755 scripts/build_internal_flydsl.sh create mode 100755 scripts/build_internal_llvm.sh create mode 100644 thirdparty/internal-llvm-build-info.json create mode 100644 thirdparty/llvm-build-info.json diff --git a/scripts/build_internal_flydsl.sh b/scripts/build_internal_flydsl.sh new file mode 100755 index 000000000..84d557a37 --- /dev/null +++ b/scripts/build_internal_flydsl.sh @@ -0,0 +1,151 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 FlyDSL Project Contributors +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +BASE_DIR="$(cd "${REPO_ROOT}/.." && pwd)" + +# --------------------------------------------------------------------------- +# Build directory (default: build-fly-internal/, overridable via FLY_BUILD_DIR) +# --------------------------------------------------------------------------- +BUILD_DIR="${FLY_BUILD_DIR:-${REPO_ROOT}/build-fly-internal}" +if [[ "${BUILD_DIR}" != /* ]]; then + BUILD_DIR="${REPO_ROOT}/${BUILD_DIR}" +fi + +# --------------------------------------------------------------------------- +# Parallelism: default $(nproc), overridable via -jN argument +# --------------------------------------------------------------------------- +PARALLEL_JOBS=$(nproc) +for arg in "$@"; do + if [[ "$arg" =~ ^-j([0-9]+)$ ]]; then + PARALLEL_JOBS="${BASH_REMATCH[1]}" + fi +done + +# --------------------------------------------------------------------------- +# Discover MLIR_PATH +# --------------------------------------------------------------------------- +# Read LLVM commit short hash for internal build path matching +LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/internal-llvm-build-info.json" +LLVM_SHORT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['llvm_hash'][:8])") + +if [ -z "${MLIR_PATH:-}" ]; then + candidates=( + "${BASE_DIR}/llvm-project-internal/mlir_install-${LLVM_SHORT}" + "${BASE_DIR}/llvm-project-flydsl/build-flydsl/mlir_install" + "${BASE_DIR}/llvm-project/build-flydsl/mlir_install" + "${BASE_DIR}/llvm-project/mlir_install" + ) + for p in "${candidates[@]}"; do + if [ -d "${p}/lib/cmake/mlir" ]; then + echo "Auto-detected MLIR_PATH: ${p}" + export MLIR_PATH="${p}" + break + fi + done +fi + +if [ -z "${MLIR_PATH:-}" ]; then + echo "Error: MLIR_PATH not set and could not be auto-detected." >&2 + echo "Build LLVM/MLIR first: bash scripts/build_llvm.sh" >&2 + echo "Or set: export MLIR_PATH=/path/to/mlir_install" >&2 + exit 1 +fi + +# --------------------------------------------------------------------------- +# CMake generator: prefer Ninja, fall back to Unix Makefiles. +# If a CMakeCache.txt already exists, reuse its generator to avoid mismatch. +# --------------------------------------------------------------------------- +_CMAKE_CACHE="${BUILD_DIR}/CMakeCache.txt" +if [ -f "${_CMAKE_CACHE}" ]; then + CACHED_GENERATOR=$(awk '/^CMAKE_GENERATOR:INTERNAL=/{sub(/^CMAKE_GENERATOR:INTERNAL=/, ""); print; exit}' "${_CMAKE_CACHE}" || true) + if [ -n "${CACHED_GENERATOR}" ]; then + GENERATOR="${CACHED_GENERATOR}" + fi +else + GENERATOR="Unix Makefiles" + if command -v ninja &> /dev/null; then + GENERATOR="Ninja" + fi +fi + +echo "==============================================" +echo "FlyDSL Build" +echo " REPO_ROOT: ${REPO_ROOT}" +echo " BUILD_DIR: ${BUILD_DIR}" +echo " MLIR_PATH: ${MLIR_PATH}" +echo " PARALLEL: -j${PARALLEL_JOBS}" +echo " GENERATOR: ${GENERATOR}" +echo " HIP_PLATFORM: ${HIP_PLATFORM:-amd (default)}" +echo "==============================================" + +# --------------------------------------------------------------------------- +# Initialize git submodules if needed +# --------------------------------------------------------------------------- +if [ ! -f "${REPO_ROOT}/thirdparty/dlpack/include/dlpack/dlpack.h" ]; then + echo "Initializing git submodules..." + git -C "${REPO_ROOT}" submodule update --init --recursive +fi + +# --------------------------------------------------------------------------- +# Remove editable-install symlink that would cause CopyFlyPythonSources to +# overwrite the freshly built _mlir_libs with files from a different build. +# --------------------------------------------------------------------------- +_EDITABLE_MLIR_LINK="${REPO_ROOT}/python/flydsl/_mlir" +if [ -L "${_EDITABLE_MLIR_LINK}" ]; then + echo "Removing editable-install symlink: ${_EDITABLE_MLIR_LINK}" + rm -f "${_EDITABLE_MLIR_LINK}" +fi + +# --------------------------------------------------------------------------- +# CMake configure +# --------------------------------------------------------------------------- +NANOBIND_DIR=$(python3 -c "import nanobind; import os; print(os.path.dirname(nanobind.__file__) + '/cmake')" 2>/dev/null || true) + +mkdir -p "${BUILD_DIR}" +cd "${BUILD_DIR}" + +# HIP_PLATFORM: required by /opt/rocm/lib/cmake/hip/hip-config.cmake. +# The shipped hip-config.cmake has `if("OFF") ... set(hip_HIPCONFIG_EXECUTABLE) ...` +# so it cannot auto-detect the platform and relies on HIP_PLATFORM being +# provided as a CMake cache variable or environment variable. +HIP_PLATFORM="${HIP_PLATFORM:-amd}" + +cmake_args=( + -G "${GENERATOR}" + "${REPO_ROOT}" + -DMLIR_DIR="${MLIR_PATH}/lib/cmake/mlir" + -DPython3_EXECUTABLE="$(which python3)" + -DHIP_PLATFORM="${HIP_PLATFORM}" +) +if [ -n "${NANOBIND_DIR}" ]; then + cmake_args+=(-Dnanobind_DIR="${NANOBIND_DIR}") +fi + +echo "Configuring CMake..." +cmake "${cmake_args[@]}" + +# --------------------------------------------------------------------------- +# Build +# --------------------------------------------------------------------------- +echo "Building with -j${PARALLEL_JOBS}..." +cmake --build . -j"${PARALLEL_JOBS}" + +# --------------------------------------------------------------------------- +# Done +# --------------------------------------------------------------------------- +PYTHON_PKG_DIR="${BUILD_DIR}/python_packages" + +echo "" +echo "==============================================" +echo "Build complete!" +echo "" +echo "Usage (no install):" +echo " export PYTHONPATH=${PYTHON_PKG_DIR}:\${PYTHONPATH}" +echo "" +echo "Or install as editable package:" +echo " cd ${REPO_ROOT} && pip install -e ." +echo "==============================================" diff --git a/scripts/build_internal_llvm.sh b/scripts/build_internal_llvm.sh new file mode 100755 index 000000000..3216d383f --- /dev/null +++ b/scripts/build_internal_llvm.sh @@ -0,0 +1,149 @@ +#!/bin/bash +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2025 FlyDSL Project Contributors +set -e + +# Default to downloading llvm-project in the parent directory of flydsl +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" +BASE_DIR="$(cd "${REPO_ROOT}/.." && pwd)" +# Read LLVM commit hash and repository from thirdparty/internal-llvm-build-info.json +LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/internal-llvm-build-info.json" +LLVM_COMMIT_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['llvm_hash'])") +LLVM_REMOTE_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['repository'])") +LLVM_REF="${LLVM_REF:-${LLVM_COMMIT:-$LLVM_COMMIT_DEFAULT}}" +LLVM_SHORT="${LLVM_REF:0:8}" + +LLVM_SRC_DIR="$BASE_DIR/llvm-project-internal" +LLVM_BUILD_DIR="$LLVM_SRC_DIR/build-flydsl-${LLVM_SHORT}" +LLVM_INSTALL_DIR="${LLVM_INSTALL_DIR:-$LLVM_SRC_DIR/mlir_install-${LLVM_SHORT}}" +LLVM_INSTALL_TGZ="${LLVM_INSTALL_TGZ:-$LLVM_SRC_DIR/mlir_install-${LLVM_SHORT}.tgz}" +LLVM_PACKAGE_INSTALL="${LLVM_PACKAGE_INSTALL:-1}" + +echo "Base directory: $BASE_DIR" +echo "LLVM Source: $LLVM_SRC_DIR" +echo "LLVM Build: $LLVM_BUILD_DIR" +echo "LLVM Install: $LLVM_INSTALL_DIR" +echo "LLVM Tarball: $LLVM_INSTALL_TGZ" +echo "LLVM Ref: $LLVM_REF" + +# 1. Clone LLVM +LLVM_REMOTE="${LLVM_REMOTE:-$LLVM_REMOTE_DEFAULT}" + +if [ ! -d "$LLVM_SRC_DIR" ]; then + echo "Preparing llvm-project checkout for ${LLVM_REF} ..." + git init "$LLVM_SRC_DIR" + pushd "$LLVM_SRC_DIR" + git remote add origin "$LLVM_REMOTE" +else + pushd "$LLVM_SRC_DIR" +fi + +if [[ "$LLVM_REF" =~ ^[0-9a-fA-F]{40}$ ]]; then + if ! git cat-file -e "${LLVM_REF}^{commit}" 2>/dev/null; then + echo "Fetching commit ${LLVM_REF} ..." + git fetch --depth 1 origin "${LLVM_REF}" + fi + git checkout -f "${LLVM_REF}" +else + echo "Fetching ref ${LLVM_REF} ..." + git fetch --depth 1 origin "${LLVM_REF}" + git checkout -f FETCH_HEAD +fi +LLVM_COMMIT_RESOLVED=$(git rev-parse HEAD) +popd +echo "LLVM Commit: $LLVM_COMMIT_RESOLVED" + +# 2. Create Build Directory +mkdir -p "$LLVM_BUILD_DIR" +cd "$LLVM_BUILD_DIR" + +# 3. Configure CMake +echo "Configuring LLVM..." + +# Install dependencies for Python bindings +echo "Installing Python dependencies..." +pip install nanobind numpy pybind11 + +# Check for ninja +GENERATOR="Unix Makefiles" +if command -v ninja &>/dev/null; then + GENERATOR="Ninja" + echo "Using Ninja generator." +else + echo "Ninja not found. Using Unix Makefiles (this might be slower)." +fi + +# Build only MLIR and necessary Clang tools, targeting native architecture, in Release mode +# Explicitly set nanobind directory if found to help CMake locate it +NANOBIND_DIR=$(python3 -c "import nanobind; import os; print(os.path.dirname(nanobind.__file__) + '/cmake')") + +cmake -G "$GENERATOR" \ + -S "$LLVM_SRC_DIR/llvm" \ + -B "$LLVM_BUILD_DIR" \ + -DLLVM_ENABLE_PROJECTS="mlir;clang;lld" \ + -DLLVM_TARGETS_TO_BUILD="${LLVM_TARGETS_TO_BUILD:-X86;NVPTX;AMDGPU}" \ + -DLLVM_ENABLE_RUNTIMES="compiler-rt" \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_STANDARD=17 \ + -DLLVM_ENABLE_ASSERTIONS=ON \ + -DLLVM_INSTALL_UTILS=ON \ + -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ + -DMLIR_BINDINGS_PYTHON_NB_DOMAIN=mlir \ + -DPython3_EXECUTABLE=$(which python3) \ + -Dnanobind_DIR="$NANOBIND_DIR" \ + -DBUILD_SHARED_LIBS=OFF \ + -DLLVM_BUILD_LLVM_DYLIB=OFF \ + -DLLVM_LINK_LLVM_DYLIB=OFF \ + -DMLIR_INCLUDE_TESTS=OFF \ + -DHIP_PLATFORM=amd \ + -DCMAKE_INSTALL_RPATH="\$ORIGIN" + +# 4. Build +PARALLEL_JOBS=$(($(nproc) / 2)) +for arg in "$@"; do + if [[ "$arg" =~ ^-j([0-9]+)$ ]]; then + PARALLEL_JOBS="${BASH_REMATCH[1]}" + elif [[ "$arg" == "--no-install" ]]; then + LLVM_PACKAGE_INSTALL=0 + fi +done +echo "Starting build with ${PARALLEL_JOBS} parallel jobs..." +cmake --build . -j${PARALLEL_JOBS} + +if [[ "${LLVM_PACKAGE_INSTALL}" == "1" ]]; then + echo "==============================================" + echo "Installing MLIR/LLVM to a clean prefix..." + rm -rf "${LLVM_INSTALL_DIR}" + mkdir -p "${LLVM_INSTALL_DIR}" + cmake --install "${LLVM_BUILD_DIR}" --prefix "${LLVM_INSTALL_DIR}" + + if [[ ! -d "${LLVM_INSTALL_DIR}/lib/cmake/mlir" ]]; then + echo "Error: install prefix missing lib/cmake/mlir: ${LLVM_INSTALL_DIR}" >&2 + exit 1 + fi + + echo "Creating tarball..." + # The install tree may still have files whose mtimes change (e.g. Python bytecode caches), + # which can cause GNU tar to exit(1) with "file changed as we read it". Treat those as + # non-fatal for packaging. + tar --warning=no-file-changed --warning=no-file-removed --ignore-failed-read \ + -C "$(dirname "${LLVM_INSTALL_DIR}")" \ + -czf "${LLVM_INSTALL_TGZ}" "$(basename "${LLVM_INSTALL_DIR}")" +fi + +echo "==============================================" +echo "LLVM/MLIR build completed successfully!" +echo "" +echo "To configure flydsl, use:" +echo "cmake .. -DMLIR_DIR=$LLVM_BUILD_DIR/lib/cmake/mlir" +if [[ "${LLVM_PACKAGE_INSTALL}" == "1" ]]; then + echo "" + echo "Packaged install prefix:" + echo " ${LLVM_INSTALL_DIR}" + echo "Use with:" + echo " export MLIR_PATH=${LLVM_INSTALL_DIR}" + echo "Tarball:" + echo " ${LLVM_INSTALL_TGZ}" +fi +echo "==============================================" diff --git a/thirdparty/internal-llvm-build-info.json b/thirdparty/internal-llvm-build-info.json new file mode 100644 index 000000000..980f84209 --- /dev/null +++ b/thirdparty/internal-llvm-build-info.json @@ -0,0 +1,6 @@ +{ + "repository": "https://github.com/AMD-Lightning-Internal/llvm-project.git", + "llvm_hash": "bb14ae08181afd90001877331f5515aa844e647e", + "branch": "amd-staging" +} + diff --git a/thirdparty/llvm-build-info.json b/thirdparty/llvm-build-info.json new file mode 100644 index 000000000..e1b5bb5ea --- /dev/null +++ b/thirdparty/llvm-build-info.json @@ -0,0 +1,5 @@ +{ + "llvm_hash": "7f77ca0dbda4abbf9af06537b2c475f20ccd6007", + "repository": "https://github.com/llvm/llvm-project.git" +} + From b62cf91c57d18e1614fc3edb3e228499459b5d99 Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 02:16:42 +0000 Subject: [PATCH 2/8] [llvm] adapt FlyDSL to internal LLVM API changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update build scripts to read repo/commit from internal-llvm-build-info.json and tag build/install directories with the commit short hash. Fix C++ API breakage introduced by the internal LLVM: - OpaqueProperties → PropertyRef in inferReturnTypes - Buffer op aux parameter from Value → Attribute - Atomic buffer ops now require explicit result Type - MFMA blgp parameter from IntegerAttr → MFMAPermB enum - MFMA scale cbsz/blgp from IntegerAttr → MatrixFormat enum - WMMA modC from raw uint16_t → WMMACModifier enum - WMMA scale params from raw casts → typed ROCDL enums - TDM cachePolicy from uint32_t → Attribute - DenseMapInfo: remove sentinel keys (tombstone-free hashing) Co-Authored-By: Claude --- lib/Conversion/FlyToROCDL/FlyToROCDL.cpp | 8 ++-- lib/Dialect/Fly/IR/FlyOps.cpp | 2 +- .../Transforms/PromoteRegMemToVectorSSA.cpp | 12 +++--- lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp | 23 ++++++------ lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp | 4 +- lib/Dialect/FlyROCDL/CDNA4/MmaAtom.cpp | 18 ++++----- lib/Dialect/FlyROCDL/GFX1250/CopyAtom.cpp | 2 +- lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp | 12 ++---- lib/Dialect/FlyROCDL/GFX1250/MmaAtomScale.cpp | 37 +++++++++---------- lib/Dialect/FlyROCDL/Ops.cpp | 2 +- 10 files changed, 57 insertions(+), 63 deletions(-) diff --git a/lib/Conversion/FlyToROCDL/FlyToROCDL.cpp b/lib/Conversion/FlyToROCDL/FlyToROCDL.cpp index 698564cc9..fe7098a76 100644 --- a/lib/Conversion/FlyToROCDL/FlyToROCDL.cpp +++ b/lib/Conversion/FlyToROCDL/FlyToROCDL.cpp @@ -378,10 +378,11 @@ class PtrLoadOpLowering : public OpConversionPattern { if (isTargetAddressSpace(flyPtrTy.getAddressSpace())) { BufferFatPtr bp(flyPtrTy, ptr); Value zero = arith::ConstantIntOp::create(rewriter, loc, 0, 32); + auto auxAttr = rewriter.getI32IntegerAttr(0); ArrayAttr noAttrs; Value loaded = ROCDL::RawPtrBufferLoadOp::create( rewriter, loc, loadTy, bp.bufferRsrc(rewriter, loc), bp.swizzleByteOffset(rewriter, loc), - zero, zero, noAttrs, noAttrs, noAttrs); + zero, auxAttr, noAttrs, noAttrs, noAttrs); rewriter.replaceOp(op, loaded); return success(); } else { @@ -423,10 +424,11 @@ class PtrStoreOpLowering : public OpConversionPattern { if (isTargetAddressSpace(flyPtrTy.getAddressSpace())) { BufferFatPtr bp(flyPtrTy, ptr); Value zero = arith::ConstantIntOp::create(rewriter, loc, 0, 32); + auto auxAttr = rewriter.getI32IntegerAttr(0); ArrayAttr noAttrs; ROCDL::RawPtrBufferStoreOp::create(rewriter, loc, value, bp.bufferRsrc(rewriter, loc), - bp.swizzleByteOffset(rewriter, loc), zero, zero, noAttrs, - noAttrs, noAttrs); + bp.swizzleByteOffset(rewriter, loc), zero, auxAttr, + noAttrs, noAttrs, noAttrs); rewriter.eraseOp(op); return success(); } else { diff --git a/lib/Dialect/Fly/IR/FlyOps.cpp b/lib/Dialect/Fly/IR/FlyOps.cpp index 41b02b1b9..94632765a 100644 --- a/lib/Dialect/Fly/IR/FlyOps.cpp +++ b/lib/Dialect/Fly/IR/FlyOps.cpp @@ -191,7 +191,7 @@ Type applyOffsetOnTensorLike(LayoutBuilder &builder, Type tensorLike llvm::LogicalResult OP::inferReturnTypes( \ mlir::MLIRContext *context, std::optional<::mlir::Location> location, \ mlir::ValueRange operands, mlir::DictionaryAttr attributes, \ - mlir::OpaqueProperties properties, mlir::RegionRange regions, \ + mlir::PropertyRef properties, mlir::RegionRange regions, \ llvm::SmallVectorImpl &inferredReturnTypes) //===----------------------------------------------------------------------===// diff --git a/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp b/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp index 7ef326586..c55738d78 100644 --- a/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp +++ b/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp @@ -27,13 +27,13 @@ using namespace mlir::fly; namespace llvm { -template <> struct DenseMapInfo : DenseMapInfo { - using Base = DenseMapInfo; - - static mlir::fly::MakePtrOp getEmptyKey() { return mlir::fly::MakePtrOp(Base::getEmptyKey()); } +template <> struct DenseMapInfo { + static unsigned getHashValue(mlir::fly::MakePtrOp op) { + return DenseMapInfo::getHashValue(op.getAsOpaquePointer()); + } - static mlir::fly::MakePtrOp getTombstoneKey() { - return mlir::fly::MakePtrOp(Base::getTombstoneKey()); + static bool isEqual(mlir::fly::MakePtrOp lhs, mlir::fly::MakePtrOp rhs) { + return lhs == rhs; } }; diff --git a/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp b/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp index 4b16116cb..299fb9a7c 100644 --- a/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp +++ b/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp @@ -89,7 +89,7 @@ FailureOr CopyOpCDNA3BufferCopyType::emitAtomCallSSA(OpBuilder &builder, }; // raw buffer load/store cachepolicy (0=cached, 2=nt) - Value aux = arith::ConstantIntOp::create(builder, loc, getCacheModifier(), 32); + auto aux = builder.getI32IntegerAttr(getCacheModifier()); ArrayAttr noAttrs; auto srcMemTy = srcTyArg ? dyn_cast(srcTyArg) : fly::MemRefType(); @@ -321,8 +321,9 @@ LogicalResult CopyOpCDNA3BufferCopyLDSType::emitAtomCall(OpBuilder &builder, Loc Value srcOff = bp.swizzleByteOffset(builder, loc); ArrayAttr noAttrs; + auto auxAttr = builder.getI32IntegerAttr(0); ROCDL::RawPtrBufferLoadLdsOp::create(builder, loc, srcRsrc, dst, size, srcOff, soffset, immOffset, - zero, noAttrs, noAttrs, noAttrs); + auxAttr, noAttrs, noAttrs, noAttrs); return success(); } @@ -428,7 +429,7 @@ FailureOr CopyOpCDNA3BufferAtomicType::emitAtomCallSSA(OpBuilder &builder soffset = arith::DivUIOp::create(builder, loc, bits, eight); } - Value zero = arith::ConstantIntOp::create(builder, loc, 0, 32); + auto auxAttr = builder.getI32IntegerAttr(0); ArrayAttr noAttrs; AtomicOp op = getAtomicOp().getValue(); @@ -437,22 +438,22 @@ FailureOr CopyOpCDNA3BufferAtomicType::emitAtomCallSSA(OpBuilder &builder case AtomicOp::Add: if (!isFloat) return failure(); - ROCDL::RawPtrBufferAtomicFaddOp::create(builder, loc, src, dstRsrc, dstOff, soffset, zero, - noAttrs, noAttrs, noAttrs); + ROCDL::RawPtrBufferAtomicFaddOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, + soffset, auxAttr, noAttrs, noAttrs, noAttrs); break; case AtomicOp::Max: if (isFloat) - ROCDL::RawPtrBufferAtomicFmaxOp::create(builder, loc, src, dstRsrc, dstOff, soffset, zero, - noAttrs, noAttrs, noAttrs); + ROCDL::RawPtrBufferAtomicFmaxOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, + soffset, auxAttr, noAttrs, noAttrs, noAttrs); else - ROCDL::RawPtrBufferAtomicSmaxOp::create(builder, loc, src, dstRsrc, dstOff, soffset, zero, - noAttrs, noAttrs, noAttrs); + ROCDL::RawPtrBufferAtomicSmaxOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, + soffset, auxAttr, noAttrs, noAttrs, noAttrs); break; case AtomicOp::Min: if (isFloat) return failure(); - ROCDL::RawPtrBufferAtomicUminOp::create(builder, loc, src, dstRsrc, dstOff, soffset, zero, - noAttrs, noAttrs, noAttrs); + ROCDL::RawPtrBufferAtomicUminOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, + soffset, auxAttr, noAttrs, noAttrs, noAttrs); break; default: return failure(); diff --git a/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp b/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp index 25be7ceab..12e755879 100644 --- a/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp +++ b/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp @@ -169,8 +169,8 @@ FailureOr MmaOpCDNA3_MFMAType::emitAtomCallSSA(OpBuilder &builder, Locati #define DISPATCH_MFMA_SSA(M_, K_, PRED, OP) \ if (m == M_ && n == M_ && k == K_ && (PRED)) { \ - auto zeroAttr = builder.getI32IntegerAttr(0); \ - return ROCDL::OP::create(builder, loc, accTy, a, b, c, zeroAttr, zeroAttr, zeroAttr) \ + return ROCDL::OP::create(builder, loc, accTy, a, b, c, (uint32_t)0, (uint32_t)0, \ + ROCDL::MFMAPermB::none) \ .getResult(); \ } diff --git a/lib/Dialect/FlyROCDL/CDNA4/MmaAtom.cpp b/lib/Dialect/FlyROCDL/CDNA4/MmaAtom.cpp index c96cca662..01ee8eb8d 100644 --- a/lib/Dialect/FlyROCDL/CDNA4/MmaAtom.cpp +++ b/lib/Dialect/FlyROCDL/CDNA4/MmaAtom.cpp @@ -237,21 +237,19 @@ FailureOr MmaOpCDNA4_MFMAScaleType::emitAtomCallSSA(OpBuilder &builder, L Value scaleB = LLVM::ExtractValueOp::create( builder, loc, atomVal, ArrayRef{*getFieldIndex(AtomStateField::ScaleB)}); - auto cbszAttr = builder.getI32IntegerAttr(*aTypeCode); - auto blgpAttr = builder.getI32IntegerAttr(*bTypeCode); - auto opselAAttr = builder.getI32IntegerAttr(getOpselA()); - auto opselBAttr = builder.getI32IntegerAttr(getOpselB()); + auto cbsz = static_cast(*aTypeCode); + auto blgp = static_cast(*bTypeCode); + uint32_t opselA = getOpselA(); + uint32_t opselB = getOpselB(); if (m == 16 && n == 16 && k == 128) { - return ROCDL::mfma_scale_f32_16x16x128_f8f6f4::create(builder, loc, accTy, a, b, c, cbszAttr, - blgpAttr, opselAAttr, scaleA, opselBAttr, - scaleB) + return ROCDL::mfma_scale_f32_16x16x128_f8f6f4::create(builder, loc, accTy, a, b, c, cbsz, blgp, + opselA, scaleA, opselB, scaleB) .getResult(); } if (m == 32 && n == 32 && k == 64) { - return ROCDL::mfma_scale_f32_32x32x64_f8f6f4::create(builder, loc, accTy, a, b, c, cbszAttr, - blgpAttr, opselAAttr, scaleA, opselBAttr, - scaleB) + return ROCDL::mfma_scale_f32_32x32x64_f8f6f4::create(builder, loc, accTy, a, b, c, cbsz, blgp, + opselA, scaleA, opselB, scaleB) .getResult(); } diff --git a/lib/Dialect/FlyROCDL/GFX1250/CopyAtom.cpp b/lib/Dialect/FlyROCDL/GFX1250/CopyAtom.cpp index 676be7155..434d198e5 100644 --- a/lib/Dialect/FlyROCDL/GFX1250/CopyAtom.cpp +++ b/lib/Dialect/FlyROCDL/GFX1250/CopyAtom.cpp @@ -503,7 +503,7 @@ LogicalResult CopyOpGFX1250TDMType::emitAtomCall(OpBuilder &builder, Location lo vector::FromElementsOp::create(builder, loc, VectorType::get({8}, builder.getI32Type()), ValueRange{zero, zero, zero, zero, zero, zero, zero, zero}); - uint32_t cachePolicy = static_cast(getCacheModifier()); + auto cachePolicy = builder.getI32IntegerAttr(static_cast(getCacheModifier())); ArrayAttr noAliasScopes; if (isLoad) ROCDL::TensorLoadToLDSOp::create(builder, loc, dgroup0, dgroup1, dg2, dg3, dg4, cachePolicy, diff --git a/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp b/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp index 224cf74c9..777615506 100644 --- a/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp +++ b/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp @@ -238,24 +238,20 @@ static FailureOr emitWmmaSSA(OpBuilder &builder, Location loc, VectorType bool clamp = false) { Value res; if constexpr (Variant == WmmaVariant::ModsAllReuse) { - // Float path: no sign/clamp operands. - res = WmmaOp::create(builder, loc, accTy, - /*signA=*/false, a, /*signB=*/false, b, - /*modC=*/(uint16_t)0, c) + res = WmmaOp::create(builder, loc, accTy, a, b, + ROCDL::WMMACModifier::none, c, + /*reuseA=*/false, /*reuseB=*/false) .getResult(); } else if constexpr (Variant == WmmaVariant::ModsC) { - // fp8 path: no sign/clamp operands. res = WmmaOp::create(builder, loc, accTy, a, b, - /*modC=*/(uint16_t)0, c, + ROCDL::WMMACModifier::none, c, /*reuseA=*/false, /*reuseB=*/false) .getResult(); } else if constexpr (Variant == WmmaVariant::ModsABClamp) { - // iu8: sign + reuse + clamp controls. res = WmmaOp::create(builder, loc, accTy, signA, a, signB, b, c, /*reuseA=*/false, /*reuseB=*/false, clamp) .getResult(); } else { - // IU form (e.g. iu4): sign/clamp controls but no reuseA/reuseB operands. static_assert(Variant == WmmaVariant::ModsIUClamp); res = WmmaOp::create(builder, loc, accTy, signA, a, signB, b, c, clamp).getResult(); } diff --git a/lib/Dialect/FlyROCDL/GFX1250/MmaAtomScale.cpp b/lib/Dialect/FlyROCDL/GFX1250/MmaAtomScale.cpp index fa2bdce5b..b4d173409 100644 --- a/lib/Dialect/FlyROCDL/GFX1250/MmaAtomScale.cpp +++ b/lib/Dialect/FlyROCDL/GFX1250/MmaAtomScale.cpp @@ -240,20 +240,20 @@ FailureOr MmaOpGFX1250_WMMAScaleType::emitAtomCallSSA(OpBuilder &builder, // the atom's compile-time params. block-16 selects the V_WMMA_SCALE16 form // (i64 scale operands); block-32 the V_WMMA_SCALE form (i32 scale operands). bool block16 = getBlockSize() == 16; + auto modC = static_cast(getModC()); + auto scaleAType = static_cast(getOpselA()); + auto scaleBType = static_cast(getOpselB()); + auto fmtScale0 = static_cast(0); + if (m == 32 && n == 16 && k == 128) { - // fp4-only form; no fmtA/fmtB operands. if (block16) return ROCDL::wmma_scale16_f32_32x16x128_f4::create( - builder, loc, accTy, a, b, /*modC=*/(uint16_t)getModC(), c, - /*scaleAType=*/(uint32_t)getOpselA(), /*fmtScaleA=*/(uint32_t)0, scaleA, - /*scaleBType=*/(uint32_t)getOpselB(), /*fmtScaleB=*/(uint32_t)0, scaleB, - /*reuseA=*/getReuseA(), /*reuseB=*/getReuseB()) + builder, loc, accTy, a, b, modC, c, scaleAType, fmtScale0, scaleA, scaleBType, + fmtScale0, scaleB, getReuseA(), getReuseB()) .getResult(); - return ROCDL::wmma_scale_f32_32x16x128_f4::create( - builder, loc, accTy, a, b, /*modC=*/(uint16_t)getModC(), c, - /*scaleAType=*/(uint32_t)getOpselA(), /*fmtScaleA=*/(uint32_t)0, scaleA, - /*scaleBType=*/(uint32_t)getOpselB(), /*fmtScaleB=*/(uint32_t)0, scaleB, - /*reuseA=*/getReuseA(), /*reuseB=*/getReuseB()) + return ROCDL::wmma_scale_f32_32x16x128_f4::create(builder, loc, accTy, a, b, modC, c, + scaleAType, fmtScale0, scaleA, scaleBType, + fmtScale0, scaleB, getReuseA(), getReuseB()) .getResult(); } @@ -262,20 +262,17 @@ FailureOr MmaOpGFX1250_WMMAScaleType::emitAtomCallSSA(OpBuilder &builder, if (!aFmt || !bFmt) return failure(); + auto fmtA = static_cast(*aFmt); + auto fmtB = static_cast(*bFmt); + if (block16) return ROCDL::wmma_scale16_f32_16x16x128_f8f6f4::create( - builder, loc, accTy, /*fmtA=*/*aFmt, a, /*fmtB=*/*bFmt, b, - /*modC=*/(uint16_t)getModC(), c, - /*scaleAType=*/(uint32_t)getOpselA(), /*fmtScaleA=*/(uint32_t)0, scaleA, - /*scaleBType=*/(uint32_t)getOpselB(), /*fmtScaleB=*/(uint32_t)0, scaleB, - /*reuseA=*/getReuseA(), /*reuseB=*/getReuseB()) + builder, loc, accTy, fmtA, a, fmtB, b, modC, c, scaleAType, fmtScale0, scaleA, + scaleBType, fmtScale0, scaleB, getReuseA(), getReuseB()) .getResult(); return ROCDL::wmma_scale_f32_16x16x128_f8f6f4::create( - builder, loc, accTy, /*fmtA=*/*aFmt, a, /*fmtB=*/*bFmt, b, - /*modC=*/(uint16_t)getModC(), c, - /*scaleAType=*/(uint32_t)getOpselA(), /*fmtScaleA=*/(uint32_t)0, scaleA, - /*scaleBType=*/(uint32_t)getOpselB(), /*fmtScaleB=*/(uint32_t)0, scaleB, - /*reuseA=*/getReuseA(), /*reuseB=*/getReuseB()) + builder, loc, accTy, fmtA, a, fmtB, b, modC, c, scaleAType, fmtScale0, scaleA, + scaleBType, fmtScale0, scaleB, getReuseA(), getReuseB()) .getResult(); } diff --git a/lib/Dialect/FlyROCDL/Ops.cpp b/lib/Dialect/FlyROCDL/Ops.cpp index a7440b4bc..c33db625d 100644 --- a/lib/Dialect/FlyROCDL/Ops.cpp +++ b/lib/Dialect/FlyROCDL/Ops.cpp @@ -15,7 +15,7 @@ using namespace mlir::fly_rocdl; LogicalResult GetBufferRsrcOp::inferReturnTypes(MLIRContext *context, std::optional location, ValueRange operands, DictionaryAttr attributes, - OpaqueProperties properties, RegionRange regions, + PropertyRef properties, RegionRange regions, SmallVectorImpl &inferredReturnTypes) { auto ptrTy = dyn_cast(operands[0].getType()); if (!ptrTy) From 83f3185b2b26fad07e46fd903e448eef310f4bae Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 03:37:28 +0000 Subject: [PATCH 3/8] [llvm] merge LLVM build info into single JSON config Consolidate internal-llvm-build-info.json and llvm-hash.txt into a single thirdparty/llvm-build-info.json with "upstream" and "internal" entries. Build scripts select by key name: - build_llvm.sh reads ['upstream'] - build_internal_llvm.sh / build_internal_flydsl.sh read ['internal'] Update CI workflows (build-whl, flydsl, build-custom-llvm-tools) to use llvm-build-info.json for cache keys and commit lookups. Co-Authored-By: Claude --- .github/workflows/build-custom-llvm-tools.yaml | 2 +- .github/workflows/build-whl.yaml | 4 ++-- .github/workflows/flydsl.yaml | 2 +- scripts/build_internal_flydsl.sh | 4 ++-- scripts/build_internal_llvm.sh | 8 ++++---- scripts/build_llvm.sh | 6 +++--- thirdparty/internal-llvm-build-info.json | 6 ------ thirdparty/llvm-build-info.json | 15 ++++++++++++--- thirdparty/llvm-hash.txt | 1 - 9 files changed, 25 insertions(+), 23 deletions(-) delete mode 100644 thirdparty/internal-llvm-build-info.json delete mode 100644 thirdparty/llvm-hash.txt diff --git a/.github/workflows/build-custom-llvm-tools.yaml b/.github/workflows/build-custom-llvm-tools.yaml index 618240848..fa87307f5 100644 --- a/.github/workflows/build-custom-llvm-tools.yaml +++ b/.github/workflows/build-custom-llvm-tools.yaml @@ -86,7 +86,7 @@ jobs: REF="$(python3 -c "import json; print(json.load(open('${CONFIG}'))['llvm_ref'])")" LLVM_REMOTE="$(python3 -c "import json; print(json.load(open('${CONFIG}')).get('llvm_remote', '${LLVM_REMOTE}'))")" else - REF="$(tr -d '[:space:]' < flydsl/thirdparty/llvm-hash.txt)" + REF="$(python3 -c "import json; print(json.load(open('flydsl/thirdparty/llvm-build-info.json'))['upstream']['llvm_hash'])")" fi # Resolve branch/tag to commit SHA for stable cache key diff --git a/.github/workflows/build-whl.yaml b/.github/workflows/build-whl.yaml index e7d654e31..cb8560d5b 100644 --- a/.github/workflows/build-whl.yaml +++ b/.github/workflows/build-whl.yaml @@ -103,7 +103,7 @@ jobs: uses: actions/cache@v4 with: path: mlir_install.tgz - key: mlir-install-manylinux228-${{ hashFiles('flydsl/thirdparty/llvm-hash.txt', 'flydsl/scripts/build_llvm.sh', 'flydsl/CMakeLists.txt') }} + key: mlir-install-manylinux228-${{ hashFiles('flydsl/thirdparty/llvm-build-info.json', 'flydsl/scripts/build_llvm.sh', 'flydsl/CMakeLists.txt') }} - name: Use cached MLIR install tarball if: steps.mlir-cache.outputs.cache-hit == 'true' @@ -163,7 +163,7 @@ jobs: SUMMARY_RELEASE_TYPE: ${{ inputs.release_type }} SUMMARY_WHEEL_DIR: dist run: | - SUMMARY_LLVM_COMMIT="$(tr -d '[:space:]' < flydsl/thirdparty/llvm-hash.txt)" + SUMMARY_LLVM_COMMIT="$(python3 -c "import json; print(json.load(open('flydsl/thirdparty/llvm-build-info.json'))['upstream']['llvm_hash'])")" export SUMMARY_LLVM_COMMIT python3 flydsl/scripts/generate_summary.py build diff --git a/.github/workflows/flydsl.yaml b/.github/workflows/flydsl.yaml index 2d038cefb..de6eb4983 100644 --- a/.github/workflows/flydsl.yaml +++ b/.github/workflows/flydsl.yaml @@ -147,7 +147,7 @@ jobs: uses: actions/cache/restore@v4 with: path: mlir_install.tgz - key: mlir-install-${{ runner.os }}-${{ runner.arch }}-${{ env.MLIR_CACHE_VERSION }}-${{ hashFiles('flydsl-test/thirdparty/llvm-hash.txt', 'flydsl-test/scripts/build_llvm.sh') }} + key: mlir-install-${{ runner.os }}-${{ runner.arch }}-${{ env.MLIR_CACHE_VERSION }}-${{ hashFiles('flydsl-test/thirdparty/llvm-build-info.json', 'flydsl-test/scripts/build_llvm.sh') }} - name: Start MLIR build container if: steps.mlir-cache.outputs.cache-hit != 'true' diff --git a/scripts/build_internal_flydsl.sh b/scripts/build_internal_flydsl.sh index 84d557a37..1eaba4ee9 100755 --- a/scripts/build_internal_flydsl.sh +++ b/scripts/build_internal_flydsl.sh @@ -29,8 +29,8 @@ done # Discover MLIR_PATH # --------------------------------------------------------------------------- # Read LLVM commit short hash for internal build path matching -LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/internal-llvm-build-info.json" -LLVM_SHORT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['llvm_hash'][:8])") +LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/llvm-build-info.json" +LLVM_SHORT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['internal']['llvm_hash'][:8])") if [ -z "${MLIR_PATH:-}" ]; then candidates=( diff --git a/scripts/build_internal_llvm.sh b/scripts/build_internal_llvm.sh index 3216d383f..2e0edc540 100755 --- a/scripts/build_internal_llvm.sh +++ b/scripts/build_internal_llvm.sh @@ -7,10 +7,10 @@ set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" BASE_DIR="$(cd "${REPO_ROOT}/.." && pwd)" -# Read LLVM commit hash and repository from thirdparty/internal-llvm-build-info.json -LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/internal-llvm-build-info.json" -LLVM_COMMIT_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['llvm_hash'])") -LLVM_REMOTE_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['repository'])") +# Read LLVM commit hash and repository from thirdparty/llvm-build-info.json (internal entry) +LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/llvm-build-info.json" +LLVM_COMMIT_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['internal']['llvm_hash'])") +LLVM_REMOTE_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['internal']['repository'])") LLVM_REF="${LLVM_REF:-${LLVM_COMMIT:-$LLVM_COMMIT_DEFAULT}}" LLVM_SHORT="${LLVM_REF:0:8}" diff --git a/scripts/build_llvm.sh b/scripts/build_llvm.sh index 3d5f3eff8..04d201fd1 100755 --- a/scripts/build_llvm.sh +++ b/scripts/build_llvm.sh @@ -13,9 +13,9 @@ LLVM_INSTALL_DIR="${LLVM_INSTALL_DIR:-$LLVM_SRC_DIR/mlir_install}" LLVM_INSTALL_TGZ="${LLVM_INSTALL_TGZ:-$LLVM_SRC_DIR/mlir_install.tgz}" LLVM_PACKAGE_INSTALL="${LLVM_PACKAGE_INSTALL:-1}" -# Read LLVM commit hash from thirdparty/llvm-hash.txt -LLVM_HASH_FILE="${REPO_ROOT}/thirdparty/llvm-hash.txt" -LLVM_COMMIT_DEFAULT=$(cat "${LLVM_HASH_FILE}" | tr -d '[:space:]') +# Read LLVM commit hash from thirdparty/llvm-build-info.json (upstream entry) +LLVM_BUILD_INFO="${REPO_ROOT}/thirdparty/llvm-build-info.json" +LLVM_COMMIT_DEFAULT=$(python3 -c "import json; print(json.load(open('${LLVM_BUILD_INFO}'))['upstream']['llvm_hash'])") LLVM_REF="${LLVM_REF:-${LLVM_COMMIT:-$LLVM_COMMIT_DEFAULT}}" echo "Base directory: $BASE_DIR" diff --git a/thirdparty/internal-llvm-build-info.json b/thirdparty/internal-llvm-build-info.json deleted file mode 100644 index 980f84209..000000000 --- a/thirdparty/internal-llvm-build-info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "repository": "https://github.com/AMD-Lightning-Internal/llvm-project.git", - "llvm_hash": "bb14ae08181afd90001877331f5515aa844e647e", - "branch": "amd-staging" -} - diff --git a/thirdparty/llvm-build-info.json b/thirdparty/llvm-build-info.json index e1b5bb5ea..94808c943 100644 --- a/thirdparty/llvm-build-info.json +++ b/thirdparty/llvm-build-info.json @@ -1,5 +1,14 @@ { - "llvm_hash": "7f77ca0dbda4abbf9af06537b2c475f20ccd6007", - "repository": "https://github.com/llvm/llvm-project.git" + "upstream": { + "repository": "https://github.com/llvm/llvm-project.git", + "llvm_hash": "e2a39f504fee836e4def9581bed817ecc327b9dc" + }, + "internal": { + "repository": "https://github.com/AMD-Lightning-Internal/llvm-project.git", + "llvm_hash": "bb14ae08181afd90001877331f5515aa844e647e" + }, + "custom1" :{ + "repository": "https://github.com/AMD-Lightning-Internal/llvm-project.git", + "branch": "" + } } - diff --git a/thirdparty/llvm-hash.txt b/thirdparty/llvm-hash.txt deleted file mode 100644 index 34f77b2e4..000000000 --- a/thirdparty/llvm-hash.txt +++ /dev/null @@ -1 +0,0 @@ -7f77ca0dbda4abbf9af06537b2c475f20ccd6007 From 87411388b223bda0bd906b15b0ee1af7ee33d302 Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 04:38:21 +0000 Subject: [PATCH 4/8] [style] clang-format C++ files touched by LLVM API adaptation Co-Authored-By: Claude --- lib/Dialect/Fly/IR/FlyOps.cpp | 5 ++--- lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp | 4 +--- lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp | 4 ++-- lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp | 2 +- lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp | 6 ++---- 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/lib/Dialect/Fly/IR/FlyOps.cpp b/lib/Dialect/Fly/IR/FlyOps.cpp index 94632765a..10ff7a42d 100644 --- a/lib/Dialect/Fly/IR/FlyOps.cpp +++ b/lib/Dialect/Fly/IR/FlyOps.cpp @@ -190,9 +190,8 @@ Type applyOffsetOnTensorLike(LayoutBuilder &builder, Type tensorLike #define FLY_INFER_RETURN_TYPES(OP) \ llvm::LogicalResult OP::inferReturnTypes( \ mlir::MLIRContext *context, std::optional<::mlir::Location> location, \ - mlir::ValueRange operands, mlir::DictionaryAttr attributes, \ - mlir::PropertyRef properties, mlir::RegionRange regions, \ - llvm::SmallVectorImpl &inferredReturnTypes) + mlir::ValueRange operands, mlir::DictionaryAttr attributes, mlir::PropertyRef properties, \ + mlir::RegionRange regions, llvm::SmallVectorImpl &inferredReturnTypes) //===----------------------------------------------------------------------===// // Constructors diff --git a/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp b/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp index c55738d78..28e73cfd6 100644 --- a/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp +++ b/lib/Dialect/Fly/Transforms/PromoteRegMemToVectorSSA.cpp @@ -32,9 +32,7 @@ template <> struct DenseMapInfo { return DenseMapInfo::getHashValue(op.getAsOpaquePointer()); } - static bool isEqual(mlir::fly::MakePtrOp lhs, mlir::fly::MakePtrOp rhs) { - return lhs == rhs; - } + static bool isEqual(mlir::fly::MakePtrOp lhs, mlir::fly::MakePtrOp rhs) { return lhs == rhs; } }; } // namespace llvm diff --git a/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp b/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp index 299fb9a7c..22ab125f8 100644 --- a/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp +++ b/lib/Dialect/FlyROCDL/CDNA3/CopyAtom.cpp @@ -444,10 +444,10 @@ FailureOr CopyOpCDNA3BufferAtomicType::emitAtomCallSSA(OpBuilder &builder case AtomicOp::Max: if (isFloat) ROCDL::RawPtrBufferAtomicFmaxOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, - soffset, auxAttr, noAttrs, noAttrs, noAttrs); + soffset, auxAttr, noAttrs, noAttrs, noAttrs); else ROCDL::RawPtrBufferAtomicSmaxOp::create(builder, loc, src.getType(), src, dstRsrc, dstOff, - soffset, auxAttr, noAttrs, noAttrs, noAttrs); + soffset, auxAttr, noAttrs, noAttrs, noAttrs); break; case AtomicOp::Min: if (isFloat) diff --git a/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp b/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp index 12e755879..698fa27d7 100644 --- a/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp +++ b/lib/Dialect/FlyROCDL/CDNA3/MmaAtom.cpp @@ -169,7 +169,7 @@ FailureOr MmaOpCDNA3_MFMAType::emitAtomCallSSA(OpBuilder &builder, Locati #define DISPATCH_MFMA_SSA(M_, K_, PRED, OP) \ if (m == M_ && n == M_ && k == K_ && (PRED)) { \ - return ROCDL::OP::create(builder, loc, accTy, a, b, c, (uint32_t)0, (uint32_t)0, \ + return ROCDL::OP::create(builder, loc, accTy, a, b, c, (uint32_t)0, (uint32_t)0, \ ROCDL::MFMAPermB::none) \ .getResult(); \ } diff --git a/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp b/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp index 777615506..ca7d87a03 100644 --- a/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp +++ b/lib/Dialect/FlyROCDL/GFX1250/MmaAtom.cpp @@ -238,13 +238,11 @@ static FailureOr emitWmmaSSA(OpBuilder &builder, Location loc, VectorType bool clamp = false) { Value res; if constexpr (Variant == WmmaVariant::ModsAllReuse) { - res = WmmaOp::create(builder, loc, accTy, a, b, - ROCDL::WMMACModifier::none, c, + res = WmmaOp::create(builder, loc, accTy, a, b, ROCDL::WMMACModifier::none, c, /*reuseA=*/false, /*reuseB=*/false) .getResult(); } else if constexpr (Variant == WmmaVariant::ModsC) { - res = WmmaOp::create(builder, loc, accTy, a, b, - ROCDL::WMMACModifier::none, c, + res = WmmaOp::create(builder, loc, accTy, a, b, ROCDL::WMMACModifier::none, c, /*reuseA=*/false, /*reuseB=*/false) .getResult(); } else if constexpr (Variant == WmmaVariant::ModsABClamp) { From 90c668933de464e2b559d0369948b3e759482ce5 Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 07:35:33 +0000 Subject: [PATCH 5/8] [compat] Wrap ROCDL ops to preserve backward-compatible Python API MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The internal LLVM update changed several ROCDL ops: operands became keyword-only attributes (aux, mask, cache_policy) and WMMA sign params were removed. Add compatibility wrappers in expr/rocdl so downstream callers (e.g. aiter) continue to work without source changes. - raw_ptr_buffer_load: accept aux as positional, convert Value/int → Attr - raw_ptr_buffer_load_lds: same aux handling - sched_barrier / sched_group_barrier: convert int mask → SchedGroupMask enum attr - tensor_load_to_lds / tensor_store_from_lds: accept cache_policy as positional - tdm_ops: pass cache_policy as keyword to underlying ROCDL ops Co-Authored-By: Claude --- python/flydsl/expr/rocdl/__init__.py | 95 +++++++++++++++++++++++++++- python/flydsl/expr/rocdl/tdm_ops.py | 15 +++-- 2 files changed, 104 insertions(+), 6 deletions(-) diff --git a/python/flydsl/expr/rocdl/__init__.py b/python/flydsl/expr/rocdl/__init__.py index 4b18f15cc..96eb9a837 100644 --- a/python/flydsl/expr/rocdl/__init__.py +++ b/python/flydsl/expr/rocdl/__init__.py @@ -54,6 +54,52 @@ mask_dsrd = 0x100 mask_dswr = 0x200 +_ods_sched_barrier = globals().get("sched_barrier") +_ods_sched_group_barrier = globals().get("sched_group_barrier") + +_SCHED_MASK_INT_TO_KW = { + 0x000: "none", + 0x001: "non_mem_non_sideeffect", + 0x002: "valu", + 0x004: "salu", + 0x008: "mfma_wmma", + 0x010: "all_vmem", + 0x020: "vmem_read", + 0x040: "vmem_write", + 0x080: "all_ds", + 0x100: "ds_read", + 0x200: "ds_write", + 0x400: "transcendental", + 0x800: "ldsdma", +} + + +def _mask_to_attr(mask): + """Convert an int or keyword mask to a SchedGroupMask attribute.""" + from ..._mlir import ir as _ir + + if isinstance(mask, _ir.Attribute): + return mask + if isinstance(mask, str): + return _ir.Attribute.parse(f"#rocdl") + val = int(mask) + if val == 0: + return _ir.Attribute.parse("#rocdl") + parts = [kw for bit, kw in _SCHED_MASK_INT_TO_KW.items() if bit and val & bit] + if not parts: + return _ir.Attribute.parse("#rocdl") + return _ir.Attribute.parse(f"#rocdl") + + +@dsl_loc_tracing +def sched_barrier(mask, **kw): + return _ods_sched_barrier(_mask_to_attr(mask), **kw) + + +@dsl_loc_tracing +def sched_group_barrier(mask, size, group_id, **kw): + return _ods_sched_group_barrier(_mask_to_attr(mask), size, group_id, **kw) + @dsl_loc_tracing def sched_mfma(cnt): @@ -573,11 +619,30 @@ def perm_b32(src_hi, src_lo, sel, **kw): @dsl_loc_tracing -def raw_ptr_buffer_load_lds(rsrc, lds_ptr, size, voffset, soffset, offset, aux, **kw): +def raw_ptr_buffer_load(res, rsrc, offset, soffset, aux=None, **kw): + from ..._mlir import ir as _ir + from ..._mlir.dialects.rocdl import raw_ptr_buffer_load as _op + + if aux is not None and not isinstance(aux, _ir.Attribute): + if isinstance(aux, int): + aux = _ir.IntegerAttr.get(_ir.IntegerType.get_signless(32), aux) + else: + aux = None + return _op(res=res, rsrc=_to_ir(rsrc), offset=_to_ir(offset), soffset=_to_ir(soffset), aux=aux, **kw) + + +@dsl_loc_tracing +def raw_ptr_buffer_load_lds(rsrc, lds_ptr, size, voffset, soffset, offset, aux=None, **kw): + from ..._mlir import ir as _ir from ..._mlir.dialects.rocdl import raw_ptr_buffer_load_lds as _op + if aux is not None and not isinstance(aux, _ir.Attribute): + if isinstance(aux, int): + aux = _ir.IntegerAttr.get(_ir.IntegerType.get_signless(32), aux) + else: + aux = None return _op( - _to_ir(rsrc), _to_ir(lds_ptr), _to_ir(size), _to_ir(voffset), _to_ir(soffset), _to_ir(offset), _to_ir(aux), **kw + _to_ir(rsrc), _to_ir(lds_ptr), _to_ir(size), _to_ir(voffset), _to_ir(soffset), _to_ir(offset), aux=aux, **kw ) @@ -592,6 +657,32 @@ def buffer_load_to_lds(rsrc, lds_ptr, voffset, size_bytes=4, soffset=0, offset=0 return raw_ptr_buffer_load_lds(rsrc, lds_ptr, size_bytes, voffset, soffset, offset, 0, **kw) +@dsl_loc_tracing +def tensor_load_to_lds(dgroup0, dgroup1, dgroup2, dgroup3, dgroup4, cache_policy=None, **kw): + from ..._mlir import ir as _ir + from ..._mlir.dialects.rocdl import tensor_load_to_lds as _op + + if cache_policy is not None and not isinstance(cache_policy, _ir.Attribute): + if isinstance(cache_policy, int): + cache_policy = _ir.IntegerAttr.get(_ir.IntegerType.get_signless(32), cache_policy) + else: + cache_policy = None + return _op(dgroup0, dgroup1, dgroup2, dgroup3, dgroup4, cache_policy=cache_policy, **kw) + + +@dsl_loc_tracing +def tensor_store_from_lds(dgroup0, dgroup1, dgroup2, dgroup3, dgroup4, cache_policy=None, **kw): + from ..._mlir import ir as _ir + from ..._mlir.dialects.rocdl import tensor_store_from_lds as _op + + if cache_policy is not None and not isinstance(cache_policy, _ir.Attribute): + if isinstance(cache_policy, int): + cache_policy = _ir.IntegerAttr.get(_ir.IntegerType.get_signless(32), cache_policy) + else: + cache_policy = None + return _op(dgroup0, dgroup1, dgroup2, dgroup3, dgroup4, cache_policy=cache_policy, **kw) + + @dsl_loc_tracing def ds_bpermute(res, index, src, **kw): from ..._mlir.dialects.rocdl import ds_bpermute as _op diff --git a/python/flydsl/expr/rocdl/tdm_ops.py b/python/flydsl/expr/rocdl/tdm_ops.py index bea968c74..995924f9e 100644 --- a/python/flydsl/expr/rocdl/tdm_ops.py +++ b/python/flydsl/expr/rocdl/tdm_ops.py @@ -70,6 +70,13 @@ ] +def _cache_policy_attr(val): + """Convert an int cache-policy to an IntegerAttr for TDM ops.""" + if val is None or isinstance(val, ir.Attribute): + return val + return ir.IntegerAttr.get(ir.IntegerType.get_signless(32), int(val)) + + # --------------------------------------------------------------------------- # Pure-Python helpers (compile-time, no IR emission) # --------------------------------------------------------------------------- @@ -769,7 +776,7 @@ def tensor_load_gather( _raw(desc.dgroup2), _raw(desc.dgroup3), dg4, - cache_policy, + cache_policy=_cache_policy_attr(cache_policy), ) @@ -794,7 +801,7 @@ def tensor_store_gather( _raw(desc.dgroup2), _raw(desc.dgroup3), dg4, - cache_policy, + cache_policy=_cache_policy_attr(cache_policy), ) @@ -1110,7 +1117,7 @@ def tensor_load_2d( dg2 = _raw(_zero_dgroup_v4i32()) dg3 = _raw(_zero_dgroup_v4i32()) dg4 = _raw(_zero_dgroup_v8i32()) - rocdl.tensor_load_to_lds(_raw(desc.dgroup0), _raw(desc.dgroup1), dg2, dg3, dg4, cache_policy) + rocdl.tensor_load_to_lds(_raw(desc.dgroup0), _raw(desc.dgroup1), dg2, dg3, dg4, cache_policy=_cache_policy_attr(cache_policy)) @dsl_loc_tracing @@ -1130,7 +1137,7 @@ def tensor_store_2d( dg2 = _raw(_zero_dgroup_v4i32()) dg3 = _raw(_zero_dgroup_v4i32()) dg4 = _raw(_zero_dgroup_v8i32()) - rocdl.tensor_store_from_lds(_raw(desc.dgroup0), _raw(desc.dgroup1), dg2, dg3, dg4, cache_policy) + rocdl.tensor_store_from_lds(_raw(desc.dgroup0), _raw(desc.dgroup1), dg2, dg3, dg4, cache_policy=_cache_policy_attr(cache_policy)) @dsl_loc_tracing From 300f90b3811fe357743739e5de7276e617dcecbf Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 08:04:22 +0000 Subject: [PATCH 6/8] [compat] Convert WMMA int params to ROCDL enum attributes The internal LLVM update changed WMMA op parameters (fmtA, fmtB, modC, scaleAType, scaleBType, fmtScaleA, fmtScaleB) from plain integers to typed ROCDL enum attributes. Add int-to-enum conversion in the existing wmma_scale_f32_16x16x128_f8f6f4, wmma_scale_f32_32x16x128_f4, and wmma_f32_16x16x128_fp8_fp8 wrappers so downstream callers passing ints continue to work. Co-Authored-By: Claude --- python/flydsl/expr/rocdl/__init__.py | 62 ++++++++++++++++++++++------ 1 file changed, 49 insertions(+), 13 deletions(-) diff --git a/python/flydsl/expr/rocdl/__init__.py b/python/flydsl/expr/rocdl/__init__.py index 96eb9a837..d798836ec 100644 --- a/python/flydsl/expr/rocdl/__init__.py +++ b/python/flydsl/expr/rocdl/__init__.py @@ -247,6 +247,42 @@ def mfma_scale_f32_16x16x128_f8f6f4(result_type, operands): ).result +_WMMA_FMT_INT_TO_KW = {0: "fp8_e4m3", 1: "fp8_e5m2", 2: "fp6_e2m3", 3: "fp6_e3m2", 4: "fp4_e2m1"} +_WMMA_MODC_INT_TO_KW = {0: "none", 1: "neg", 2: "abs", 3: "neg_abs"} +_WMMA_SCALE_TYPE_INT_TO_KW = {0: "row0", 1: "row1"} +_WMMA_SCALE_FMT_INT_TO_KW = {0: "e8", 1: "e5m3", 2: "e4m3"} + + +def _wmma_attr(val, mapping, attr_name): + """Convert an int to a parsed ROCDL enum attribute for WMMA ops.""" + from ..._mlir import ir as _ir + + if val is None or isinstance(val, _ir.Attribute): + return val + if isinstance(val, bool): + return val + kw = mapping.get(int(val)) + if kw is None: + return val + return _ir.Attribute.parse(f"#rocdl<{attr_name} {kw}>") + + +def _wmma_fmt(val): + return _wmma_attr(val, _WMMA_FMT_INT_TO_KW, "matrix_format") + + +def _wmma_modc(val): + return _wmma_attr(val, _WMMA_MODC_INT_TO_KW, "wmma_c_modifier") + + +def _wmma_scale_type(val): + return _wmma_attr(val, _WMMA_SCALE_TYPE_INT_TO_KW, "wmma_matrix_scale") + + +def _wmma_scale_fmt(val): + return _wmma_attr(val, _WMMA_SCALE_FMT_INT_TO_KW, "wmma_matrix_scale_format") + + @dsl_loc_tracing def wmma_scale_f32_16x16x128_f8f6f4( result_type, @@ -293,13 +329,13 @@ def wmma_scale_f32_16x16x128_f8f6f4( c_v, sA, sB, - fmtA=fmtA, - fmtB=fmtB, - modC=modC, - scaleAType=scaleAType, - fmtScaleA=fmtScaleA, - scaleBType=scaleBType, - fmtScaleB=fmtScaleB, + fmtA=_wmma_fmt(fmtA), + fmtB=_wmma_fmt(fmtB), + modC=_wmma_modc(modC), + scaleAType=_wmma_scale_type(scaleAType), + fmtScaleA=_wmma_scale_fmt(fmtScaleA), + scaleBType=_wmma_scale_type(scaleBType), + fmtScaleB=_wmma_scale_fmt(fmtScaleB), reuseA=reuseA, reuseB=reuseB, ).result @@ -345,11 +381,11 @@ def wmma_scale_f32_32x16x128_f4( c_v, sA, sB, - modC=modC, - scaleAType=scaleAType, - fmtScaleA=fmtScaleA, - scaleBType=scaleBType, - fmtScaleB=fmtScaleB, + modC=_wmma_modc(modC), + scaleAType=_wmma_scale_type(scaleAType), + fmtScaleA=_wmma_scale_fmt(fmtScaleA), + scaleBType=_wmma_scale_type(scaleBType), + fmtScaleB=_wmma_scale_fmt(fmtScaleB), reuseA=reuseA, reuseB=reuseB, ).result @@ -369,7 +405,7 @@ def wmma_f32_16x16x128_fp8_fp8(result_type, a, b, c, *, modC=0, reuseA=False, re a_v = _unwrap_mfma_operand(a) b_v = _unwrap_mfma_operand(b) c_v = _unwrap_mfma_operand(c) - return _ods_wmma_f32_16x16x128_fp8_fp8(result_type, a_v, b_v, c_v, modC=modC, reuseA=reuseA, reuseB=reuseB).result + return _ods_wmma_f32_16x16x128_fp8_fp8(result_type, a_v, b_v, c_v, modC=_wmma_modc(modC), reuseA=reuseA, reuseB=reuseB).result @dsl_loc_tracing From 912575be28d7f485e73557b1eb4b7cc0c3ab4ede Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 09:33:23 +0000 Subject: [PATCH 7/8] =?UTF-8?q?[compat]=20Fix=20buffer=5Fops=20aux=20param?= =?UTF-8?q?:=20Value=20=E2=86=92=20keyword=20Attribute?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RawPtrBufferLoadOp/StoreOp aux changed from a positional Value operand to a keyword-only Attribute in the internal LLVM update. Convert the cache_modifier int to IntegerAttr and pass as keyword. Co-Authored-By: Claude --- kernels/common/buffer_ops.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/kernels/common/buffer_ops.py b/kernels/common/buffer_ops.py index 625f4ca88..f7c57e924 100644 --- a/kernels/common/buffer_ops.py +++ b/kernels/common/buffer_ops.py @@ -555,11 +555,11 @@ def buffer_load( if not isinstance(soffset.type, ir.IntegerType) or soffset.type.width != 32: op = std_arith.IndexCastOp(T.i32(), soffset) soffset = _unwrap_value(op.result) - aux_flags = _create_i32_constant(cache_modifier) + aux_attr = ir.IntegerAttr.get(ir.IntegerType.get_signless(32), cache_modifier) if cache_modifier else None # Emit buffer load load_op = rocdl.RawPtrBufferLoadOp( - result_type, rsrc, offset, soffset, aux_flags # soffset (scalar byte offset) # aux (cache modifiers) + result_type, rsrc, offset, soffset, aux=aux_attr ) return load_op.result @@ -642,9 +642,9 @@ def buffer_store( if not isinstance(soffset.type, ir.IntegerType) or soffset.type.width != 32: op = std_arith.IndexCastOp(T.i32(), soffset) soffset = _unwrap_value(op.result) - aux_flags = _create_i32_constant(cache_modifier) + aux_attr = ir.IntegerAttr.get(ir.IntegerType.get_signless(32), cache_modifier) if cache_modifier else None # Emit buffer store rocdl.RawPtrBufferStoreOp( - data, rsrc, offset, soffset, aux_flags # soffset (scalar byte offset) # aux (cache modifiers) + data, rsrc, offset, soffset, aux=aux_attr ) From c35d21ae3f6f089b9a0afc04e155847c528c8147 Mon Sep 17 00:00:00 2001 From: jli-melchior Date: Wed, 29 Jul 2026 12:48:11 +0000 Subject: [PATCH 8/8] =?UTF-8?q?[compat]=20Fix=20global=5Fprefetch=20scope?= =?UTF-8?q?=20param:=20positional=20=E2=86=92=20keyword?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit global_prefetch's second param changed from positional `scope` to keyword-only `cache_policy` in the LLVM binding regeneration. l2_prefetch_tile was the only call site missed — fix it to use cache_policy=_cache_policy_attr(scope), consistent with the tensor_load_to_lds/tensor_store_from_lds fixes in the same file. Co-Authored-By: Claude --- python/flydsl/expr/rocdl/tdm_ops.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/flydsl/expr/rocdl/tdm_ops.py b/python/flydsl/expr/rocdl/tdm_ops.py index 995924f9e..9d31fd904 100644 --- a/python/flydsl/expr/rocdl/tdm_ops.py +++ b/python/flydsl/expr/rocdl/tdm_ops.py @@ -1231,4 +1231,4 @@ def l2_prefetch_tile( # NOTE: rocdl.global_prefetch lowers to llvm.amdgcn.global.prefetch, which # requires LLVM ISel support for gfx1250 global_prefetch_b8. If the LLVM # build lacks this pattern, the instruction will be silently dropped. - rocdl.global_prefetch(ptr_val, scope) + rocdl.global_prefetch(ptr_val, cache_policy=_cache_policy_attr(scope))