Index: mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h =================================================================== --- mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h +++ mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.h @@ -27,7 +27,8 @@ /// Pass to enable Armv9 Streaming SVE mode. std::unique_ptr -createEnableArmStreamingPass(const ArmStreaming mode = ArmStreaming::Default); +createEnableArmStreamingPass(const ArmStreaming mode = ArmStreaming::Default, + const bool enableZA = false); //===----------------------------------------------------------------------===// // Registration Index: mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td =================================================================== --- mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td +++ mlir/include/mlir/Dialect/ArmSME/Transforms/Passes.td @@ -33,6 +33,8 @@ "Streaming mode is internal to the function, callee " "manages PSTATE.SM on entry/exit.") )}]>, + Option<"enableZA", "enable-za", "bool", /*default=*/"false", + "Enable ZA storage array.">, ]; let dependentDialects = ["func::FuncDialect"]; } Index: mlir/lib/Dialect/ArmSME/Transforms/EnableArmStreaming.cpp =================================================================== --- mlir/lib/Dialect/ArmSME/Transforms/EnableArmStreaming.cpp +++ mlir/lib/Dialect/ArmSME/Transforms/EnableArmStreaming.cpp @@ -13,6 +13,8 @@ // * 'arm_streaming' (default) // * 'arm_locally_streaming' // +// It can also optionally enable the ZA storage array. +// // Streaming-mode is part of the interface (ABI) for functions with the // first attribute and it's the responsibility of the caller to manage // PSTATE.SM on entry/exit to functions with this attribute [3]. The LLVM @@ -49,11 +51,15 @@ static constexpr char kArmStreamingAttr[] = "arm_streaming"; static constexpr char kArmLocallyStreamingAttr[] = "arm_locally_streaming"; +static constexpr char kArmZAAttr[] = "arm_za"; namespace { struct EnableArmStreamingPass : public arm_sme::impl::EnableArmStreamingBase { - EnableArmStreamingPass(ArmStreaming mode) { this->mode = mode; } + EnableArmStreamingPass(ArmStreaming mode, bool enableZA) { + this->mode = mode; + this->enableZA = enableZA; + } void runOnOperation() override { std::string attr; switch (mode) { @@ -65,11 +71,19 @@ break; } getOperation()->setAttr(attr, UnitAttr::get(&getContext())); + + // The pass currently only supports enabling ZA when in streaming-mode, but + // ZA can be accessed by the SME LDR, STR and ZERO instructions when not in + // streaming-mode (see section B1.1.1, IDGNQM of spec [1]). It may be worth + // supporting this later. + if (enableZA) + getOperation()->setAttr(kArmZAAttr, UnitAttr::get(&getContext())); } }; } // namespace std::unique_ptr -mlir::arm_sme::createEnableArmStreamingPass(const ArmStreaming mode) { - return std::make_unique(mode); +mlir::arm_sme::createEnableArmStreamingPass(const ArmStreaming mode, + const bool enableZA) { + return std::make_unique(mode, enableZA); } Index: mlir/test/Dialect/ArmSME/enable-arm-streaming.mlir =================================================================== --- mlir/test/Dialect/ArmSME/enable-arm-streaming.mlir +++ mlir/test/Dialect/ArmSME/enable-arm-streaming.mlir @@ -1,8 +1,11 @@ // RUN: mlir-opt %s -enable-arm-streaming -verify-diagnostics | FileCheck %s // RUN: mlir-opt %s -enable-arm-streaming=mode=locally -verify-diagnostics | FileCheck %s -check-prefix=CHECK-LOCALLY +// RUN: mlir-opt %s -enable-arm-streaming=enable-za -verify-diagnostics | FileCheck %s -check-prefix=CHECK-ENABLE-ZA // CHECK-LABEL: @arm_streaming // CHECK-SAME: attributes {arm_streaming} // CHECK-LOCALLY-LABEL: @arm_streaming // CHECK-LOCALLY-SAME: attributes {arm_locally_streaming} +// CHECK-ENABLE-ZA-LABEL: @arm_streaming +// CHECK-ENABLE-ZA-SAME: attributes {arm_streaming, arm_za} func.func @arm_streaming() { return }