[llvm-branch-commits] [llvm] [2/7][PISA] Add PISA IR intrinsics and address-space utilities (PR #214096)

Michal Paszkowski via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Aug 20 05:10:37 PDT 2026


https://github.com/michalpaszkowski updated https://github.com/llvm/llvm-project/pull/214096

>From cfa6e07e3b49b63a9b676829225a771143fb82ca Mon Sep 17 00:00:00 2001
From: Michal Paszkowski <michal.paszkowski at intel.com>
Date: Fri, 31 Jul 2026 03:04:47 -0700
Subject: [PATCH] Add PISA IR intrinsics and address-space utilities

This patch adds the PISA IR intrinsics definitions, address space
utilities, and basic tests.
---
 llvm/include/llvm/IR/CMakeLists.txt           |   1 +
 llvm/include/llvm/IR/Intrinsics.td            |   1 +
 llvm/include/llvm/IR/IntrinsicsPISA.td        | 252 ++++++++++++++++++
 llvm/include/llvm/IR/PISAIntrinsicUtils.h     |  72 +++++
 llvm/include/llvm/Support/PISAAddrSpace.h     |  59 ++++
 llvm/lib/IR/CMakeLists.txt                    |   1 +
 llvm/lib/IR/Intrinsics.cpp                    |   2 +
 llvm/lib/IR/PISAIntrinsicUtils.cpp            | 121 +++++++++
 .../CodeGen/PISA/intrinsics-address-space.ll  |  20 ++
 .../CodeGen/PISA/intrinsics-attributes.ll     |  24 ++
 llvm/test/CodeGen/PISA/intrinsics.ll          |  19 ++
 11 files changed, 572 insertions(+)
 create mode 100644 llvm/include/llvm/IR/IntrinsicsPISA.td
 create mode 100644 llvm/include/llvm/IR/PISAIntrinsicUtils.h
 create mode 100644 llvm/include/llvm/Support/PISAAddrSpace.h
 create mode 100644 llvm/lib/IR/PISAIntrinsicUtils.cpp
 create mode 100644 llvm/test/CodeGen/PISA/intrinsics-address-space.ll
 create mode 100644 llvm/test/CodeGen/PISA/intrinsics-attributes.ll
 create mode 100644 llvm/test/CodeGen/PISA/intrinsics.ll

diff --git a/llvm/include/llvm/IR/CMakeLists.txt b/llvm/include/llvm/IR/CMakeLists.txt
index 5a7676b968589..1d6658030215a 100644
--- a/llvm/include/llvm/IR/CMakeLists.txt
+++ b/llvm/include/llvm/IR/CMakeLists.txt
@@ -26,4 +26,5 @@ tablegen(LLVM IntrinsicsWebAssembly.h -gen-intrinsic-enums -intrinsic-prefix=was
 tablegen(LLVM IntrinsicsX86.h -gen-intrinsic-enums -intrinsic-prefix=x86)
 tablegen(LLVM IntrinsicsXCore.h -gen-intrinsic-enums -intrinsic-prefix=xcore)
 tablegen(LLVM IntrinsicsVE.h -gen-intrinsic-enums -intrinsic-prefix=ve)
+tablegen(LLVM IntrinsicsPISA.h -gen-intrinsic-enums -intrinsic-prefix=pisa)
 add_public_tablegen_target(intrinsics_gen)
diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td
index 083b933e77d16..4e2a820101457 100644
--- a/llvm/include/llvm/IR/Intrinsics.td
+++ b/llvm/include/llvm/IR/Intrinsics.td
@@ -3225,5 +3225,6 @@ include "llvm/IR/IntrinsicsSPIRV.td"
 include "llvm/IR/IntrinsicsVE.td"
 include "llvm/IR/IntrinsicsDirectX.td"
 include "llvm/IR/IntrinsicsLoongArch.td"
+include "llvm/IR/IntrinsicsPISA.td"
 
 #endif // TEST_INTRINSICS_SUPPRESS_DEFS
diff --git a/llvm/include/llvm/IR/IntrinsicsPISA.td b/llvm/include/llvm/IR/IntrinsicsPISA.td
new file mode 100644
index 0000000000000..ba3dab8cecf90
--- /dev/null
+++ b/llvm/include/llvm/IR/IntrinsicsPISA.td
@@ -0,0 +1,252 @@
+//===- IntrinsicsPISA.td - Defines PISA intrinsics ---------*- tablegen -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines all of the PISA-specific intrinsics.
+//
+//===----------------------------------------------------------------------===//
+
+// Pointer type definitions.
+def pisa_global_ptr_ty   : LLVMQualPointerType<1>;  // (global)*
+def pisa_constant_ptr_ty : LLVMQualPointerType<2>;  // (constant)*
+def pisa_shared_ptr_ty   : LLVMQualPointerType<3>;  // (shared)*
+def pisa_generic_ptr_ty  : LLVMQualPointerType<0>;  // (generic)*
+
+// Base classes.
+class PISAIntrinsic<list<LLVMType> ret_types, list<LLVMType> param_types = [],
+                    list<IntrinsicProperty> intr_properties = [], string name = "">
+    : Intrinsic<ret_types, param_types, intr_properties, name> {
+  let TargetPrefix = "pisa";
+}
+
+class PISADefaultAttrsIntrinsic<list<LLVMType> ret_types, list<LLVMType> param_types = [],
+                                list<IntrinsicProperty> intr_properties = [], string name = "">
+    : DefaultAttrsIntrinsic<ret_types, param_types, intr_properties, name> {
+  let TargetPrefix = "pisa";
+}
+
+class PISAIntrinsicClang<list<LLVMType> RetTypes, list<LLVMType> ParamTypes = [],
+                         list<IntrinsicProperty> IntrProperties = [], string ClangName, string Name = "">
+    : PISAIntrinsic<RetTypes, ParamTypes, IntrProperties, Name>,
+      ClangBuiltin<!strconcat("__builtin_pisa_", ClangName)>;
+
+class PISADefaultAttrsIntrinsicClang<list<LLVMType> RetTypes, list<LLVMType> ParamTypes = [],
+                                     list<IntrinsicProperty> IntrProperties = [],
+                                     string ClangName, string Name = "">
+    : PISADefaultAttrsIntrinsic<RetTypes, ParamTypes, IntrProperties, Name>,
+      ClangBuiltin<!strconcat("__builtin_pisa_", ClangName)>;
+
+// Multiclass for XYZ dimension variants.
+multiclass PISAIntrinsicXYZ<list<LLVMType> RetTypes, list<LLVMType> ParamTypes = [],
+                            list<IntrinsicProperty> IntrProperties = [], string ClangName> {
+  def _x : PISADefaultAttrsIntrinsicClang<RetTypes, ParamTypes, IntrProperties, !strconcat(ClangName, "_x")>;
+  def _y : PISADefaultAttrsIntrinsicClang<RetTypes, ParamTypes, IntrProperties, !strconcat(ClangName, "_y")>;
+  def _z : PISADefaultAttrsIntrinsicClang<RetTypes, ParamTypes, IntrProperties, !strconcat(ClangName, "_z")>;
+}
+
+// Constants.
+defvar MAX_WORK_DIM = 3;
+defvar MAX_LOCAL_SIZE = 65536;
+defvar MAX_SUB_GROUP_SIZE = 32;
+
+// Helper classes for common ArgInfo patterns.
+class RoundingModeArgInfo<ArgIndex idx> : ArgInfo<idx, [ArgName<"round">, ImmArgPrinter<"printRoundingMode">]>;
+class SaturationArgInfo<ArgIndex idx>   : ArgInfo<idx, [ArgName<"saturation">]>;
+class NanPropagateArgInfo<ArgIndex idx> : ArgInfo<idx, [ArgName<"nanp">]>;
+
+// Helper class for barrier intrinsics.
+class PISAIntrinsicBarrier<string ClangName, list<LLVMType> param_types = []>
+    : PISAIntrinsicClang<[], param_types, [IntrNoMem, IntrHasSideEffects, IntrConvergent], ClangName>;
+
+// Helper class for unary float operations with rounding mode.
+class PISAUnaryRndIntrinsic
+    : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, llvm_i8_ty], [IntrNoMem, ImmArg<ArgIndex<1>>]>;
+
+// Helper class for binary float operations with rounding mode.
+class PISABinaryRndIntrinsic
+    : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i8_ty],
+                                [IntrNoMem, ImmArg<ArgIndex<2>>]>;
+
+// Helper class for float operations with rounding mode + saturation flag.
+class PISAFloatIntrinsic<LLVMType ret_ty, list<LLVMType> operand_types>
+    : PISADefaultAttrsIntrinsic<[ret_ty], [], []> {
+  defvar num_params = !size(operand_types);
+  let ParamTypes = !listconcat(
+    operand_types,
+    [llvm_i8_ty, // rounding mode
+     llvm_i1_ty] // saturation flag
+  );
+  let IntrProperties = [
+    IntrNoMem,
+    ImmArg<ArgIndex<num_params>>,
+    ImmArg<ArgIndex<!add(num_params, 1)>>,
+    RoundingModeArgInfo<ArgIndex<num_params>>,
+    SaturationArgInfo<ArgIndex<!add(num_params, 1)>>
+  ];
+}
+
+
+//===----------------------------------------------------------------------===//
+// 1. Special Registers
+//===----------------------------------------------------------------------===//
+
+defm int_pisa_local_id             : PISAIntrinsicXYZ<[llvm_i32_ty], [], [IntrNoMem, Range<RetIndex, 0, MAX_LOCAL_SIZE>], "local_id">;
+defm int_pisa_local_size           : PISAIntrinsicXYZ<[llvm_i32_ty], [], [IntrNoMem, Range<RetIndex, 1, !add(MAX_LOCAL_SIZE, 1)>], "local_size">;
+defm int_pisa_enqueued_local_size  : PISAIntrinsicXYZ<[llvm_i32_ty], [], [IntrNoMem, Range<RetIndex, 1, !add(MAX_LOCAL_SIZE, 1)>],
+                                                       "enqueued_local_size">;
+defm int_pisa_group_id             : PISAIntrinsicXYZ<[llvm_i32_ty], [], [IntrNoMem], "group_id">;
+defm int_pisa_group_count          : PISAIntrinsicXYZ<[llvm_i32_ty], [], [IntrNoMem], "group_count">;
+defm int_pisa_global_size          : PISAIntrinsicXYZ<[llvm_i64_ty], [], [IntrNoMem], "global_size">;
+defm int_pisa_global_offset        : PISAIntrinsicXYZ<[llvm_i64_ty], [], [IntrNoMem], "global_offset">;
+
+def int_pisa_lane_id         : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [],
+                                   [IntrNoMem, Range<RetIndex, 0, MAX_SUB_GROUP_SIZE>], "lane_id">;
+def int_pisa_subgroup_size   : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [],
+                                   [IntrNoMem, Range<RetIndex, MAX_SUB_GROUP_SIZE, !add(MAX_SUB_GROUP_SIZE, 1)>],
+                                   "subgroup_size">;
+def int_pisa_work_dim        : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [],
+                                   [IntrNoMem, Range<RetIndex, 1, !add(MAX_WORK_DIM, 1)>], "work_dim">;
+
+def int_pisa_activemask          : PISAIntrinsicClang<[llvm_i32_ty], [], [IntrNoMem, IntrConvergent], "activemask">;
+
+//===----------------------------------------------------------------------===//
+// 2. Integer Arithmetic
+//===----------------------------------------------------------------------===//
+
+def int_pisa_dp4a_uu : PISADefaultAttrsIntrinsic<[llvm_i32_ty],
+                           [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+                           [IntrNoMem, IntrWillReturn, ImmArg<ArgIndex<3>>,
+                            SaturationArgInfo<ArgIndex<3>>]>;
+def int_pisa_dp4a_us : PISADefaultAttrsIntrinsic<[llvm_i32_ty],
+                           [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+                           [IntrNoMem, IntrWillReturn, ImmArg<ArgIndex<3>>,
+                            SaturationArgInfo<ArgIndex<3>>]>;
+def int_pisa_dp4a_su : PISADefaultAttrsIntrinsic<[llvm_i32_ty],
+                           [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+                           [IntrNoMem, IntrWillReturn, ImmArg<ArgIndex<3>>,
+                            SaturationArgInfo<ArgIndex<3>>]>;
+def int_pisa_dp4a_ss : PISADefaultAttrsIntrinsic<[llvm_i32_ty],
+                           [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+                           [IntrNoMem, IntrWillReturn, ImmArg<ArgIndex<3>>,
+                            SaturationArgInfo<ArgIndex<3>>]>;
+
+def int_pisa_smad : PISADefaultAttrsIntrinsic<[llvm_anyint_ty],
+                        [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
+
+//===----------------------------------------------------------------------===//
+// 3. Floating Point
+//===----------------------------------------------------------------------===//
+
+def int_pisa_fabs   : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_pisa_frcp   : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_pisa_frsqrt : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_pisa_frc    : PISADefaultAttrsIntrinsicClang<[llvm_float_ty], [llvm_float_ty], [IntrNoMem], "frcf">;
+
+def int_pisa_fmin_sat : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+                              [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
+                              [IntrNoMem, Commutative, ImmArg<ArgIndex<2>>,
+                               NanPropagateArgInfo<ArgIndex<2>>]>;
+def int_pisa_fmax_sat : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+                              [LLVMMatchType<0>, LLVMMatchType<0>, llvm_i1_ty],
+                              [IntrNoMem, Commutative, ImmArg<ArgIndex<2>>,
+                               NanPropagateArgInfo<ArgIndex<2>>]>;
+
+// Float operations with rounding mode + saturation flag.
+def int_pisa_fadd    : PISAFloatIntrinsic<llvm_anyfloat_ty, [LLVMMatchType<0>, LLVMMatchType<0>]>;
+def int_pisa_fsub    : PISAFloatIntrinsic<llvm_anyfloat_ty, [LLVMMatchType<0>, LLVMMatchType<0>]>;
+def int_pisa_fmul    : PISAFloatIntrinsic<llvm_anyfloat_ty, [LLVMMatchType<0>, LLVMMatchType<0>]>;
+def int_pisa_fma     : PISAFloatIntrinsic<llvm_anyfloat_ty, [LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>]>;
+
+// Binary float operations with explicit rounding mode.
+def int_pisa_fdiv_rnd : PISABinaryRndIntrinsic;
+def int_pisa_pow_rnd  : PISABinaryRndIntrinsic;
+
+// Unary float operations with explicit rounding mode.
+def int_pisa_fsqrt_rnd  : PISAUnaryRndIntrinsic;
+def int_pisa_frnd_rnd   : PISAUnaryRndIntrinsic;
+def int_pisa_frcp_rnd   : PISAUnaryRndIntrinsic;
+def int_pisa_sin_rnd    : PISAUnaryRndIntrinsic;
+def int_pisa_cos_rnd    : PISAUnaryRndIntrinsic;
+def int_pisa_tanh_rnd   : PISAUnaryRndIntrinsic;
+def int_pisa_exp_rnd    : PISAUnaryRndIntrinsic;
+def int_pisa_exp2_rnd   : PISAUnaryRndIntrinsic;
+def int_pisa_log_rnd    : PISAUnaryRndIntrinsic;
+def int_pisa_log2_rnd   : PISAUnaryRndIntrinsic;
+def int_pisa_log10_rnd  : PISAUnaryRndIntrinsic;
+
+//===----------------------------------------------------------------------===//
+// 4. Logic and Shift
+//===----------------------------------------------------------------------===//
+
+def int_pisa_bfi  : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty],
+                        [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem], "bfi">;
+def int_pisa_ubfe : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty],
+                        [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem], "ubfe">;
+def int_pisa_sbfe : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty],
+                        [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem], "sbfe">;
+def int_pisa_bfn  : PISADefaultAttrsIntrinsic<[llvm_anyint_ty],
+                        [llvm_i8_ty, LLVMMatchType<0>, LLVMMatchType<0>, LLVMMatchType<0>],
+                        [IntrNoMem, ImmArg<ArgIndex<0>>]>;
+
+//===----------------------------------------------------------------------===//
+// 5. Data Movement and Conversion
+//===----------------------------------------------------------------------===//
+
+// Conversions with explicit rounding mode (metadata).
+def int_pisa_fptosi_md : PISADefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_metadata_ty], [IntrNoMem]>;
+def int_pisa_fptoui_md : PISADefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_metadata_ty], [IntrNoMem]>;
+
+// Conversions with explicit rounding mode (i8 immediate).
+def int_pisa_fptosi_rnd : PISADefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i8_ty],
+                              [IntrNoMem, ImmArg<ArgIndex<1>>]>;
+def int_pisa_fptoui_rnd : PISADefaultAttrsIntrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i8_ty],
+                              [IntrNoMem, ImmArg<ArgIndex<1>>]>;
+
+// Conversions with rounding mode + saturation flag.
+def int_pisa_sitofp : PISAFloatIntrinsic<llvm_anyfloat_ty, [llvm_anyint_ty]>;
+def int_pisa_uitofp : PISAFloatIntrinsic<llvm_anyfloat_ty, [llvm_anyint_ty]>;
+def int_pisa_ftrunc : PISAFloatIntrinsic<llvm_anyfloat_ty, [llvm_anyfloat_ty]>;
+
+// Address space checks.
+def int_pisa_isaddr_private : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [pisa_generic_ptr_ty], [IntrNoMem], "isaddr_private">;
+def int_pisa_isaddr_shared  : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [pisa_generic_ptr_ty], [IntrNoMem], "isaddr_shared">;
+def int_pisa_isaddr_global  : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [pisa_generic_ptr_ty], [IntrNoMem], "isaddr_global">;
+
+//===----------------------------------------------------------------------===//
+// 6. Subgroup Communication
+//===----------------------------------------------------------------------===//
+
+def int_pisa_shfl : PISADefaultAttrsIntrinsic<[llvm_i32_ty],
+                        [llvm_i8_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i32_ty, llvm_i1_ty],
+                        [IntrNoMem, IntrConvergent, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<5>>,
+                         ArgInfo<ArgIndex<0>, [ArgName<"mode">, ImmArgPrinter<"printSHFLMode">]>,
+                         ArgInfo<ArgIndex<5>, [ArgName<"sg">]>]>;
+def int_pisa_ired : PISADefaultAttrsIntrinsic<[llvm_anyint_ty],
+                        [llvm_i8_ty, LLVMMatchType<0>, llvm_i32_ty, LLVMMatchType<0>],
+                        [IntrNoMem, IntrConvergent, ImmArg<ArgIndex<0>>,
+                         ArgInfo<ArgIndex<0>, [ArgName<"op">, ImmArgPrinter<"printIRedOp">]>]>;
+def int_pisa_fred : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+                        [llvm_i8_ty, LLVMMatchType<0>, llvm_i32_ty, LLVMMatchType<0>, llvm_i1_ty],
+                        [IntrNoMem, IntrConvergent, ImmArg<ArgIndex<0>>, ImmArg<ArgIndex<4>>,
+                         ArgInfo<ArgIndex<0>, [ArgName<"op">, ImmArgPrinter<"printFRedOp">]>,
+                         NanPropagateArgInfo<ArgIndex<4>>]>;
+def int_pisa_redfirstidx : PISADefaultAttrsIntrinsicClang<[llvm_i32_ty], [llvm_i32_ty],
+                               [IntrNoMem, IntrConvergent], "redfirstidx">;
+
+//===----------------------------------------------------------------------===//
+// 7. Memory and Atomics
+//===----------------------------------------------------------------------===//
+
+def int_pisa_cas_fatom : PISADefaultAttrsIntrinsic<[llvm_anyfloat_ty],
+                             [llvm_anyptr_ty, LLVMMatchType<0>, LLVMMatchType<0>, llvm_i8_ty],
+                             [IntrHasSideEffects, ImmArg<ArgIndex<3>>]>;
+
+//===----------------------------------------------------------------------===//
+// 8. Synchronization
+//===----------------------------------------------------------------------===//
+
+def int_pisa_workgroup_barrier : PISAIntrinsicBarrier<"workgroup_barrier">;
diff --git a/llvm/include/llvm/IR/PISAIntrinsicUtils.h b/llvm/include/llvm/IR/PISAIntrinsicUtils.h
new file mode 100644
index 0000000000000..76a4bd17a9781
--- /dev/null
+++ b/llvm/include/llvm/IR/PISAIntrinsicUtils.h
@@ -0,0 +1,72 @@
+//===-- PISAIntrinsicUtils.h ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_IR_PISAINTRINSICUTILS_H
+#define LLVM_IR_PISAINTRINSICUTILS_H
+#include "llvm/ADT/StringRef.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsPISA.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace pisa {
+
+// The enum values must match the Clang preprocessor definitions in
+// lib/Frontend/InitPreprocessor.cpp.
+namespace MemoryScope {
+enum : unsigned {
+  none = 255,
+  system = 0,    // __MEMORY_SCOPE_SYSTEM
+  gpu = 1,       // __MEMORY_SCOPE_DEVICE
+  workgroup = 2, // __MEMORY_SCOPE_WRKGRP
+  subgroup = 3,  // __MEMORY_SCOPE_WVFRNT
+  total_scopes
+};
+} // namespace MemoryScope
+
+namespace IRedOp {
+enum : unsigned {
+  SUM = 0,
+  SMIN = 1,
+  SMAX = 2,
+  UMIN = 3,
+  UMAX = 4,
+  AND = 5,
+  OR = 6,
+  XOR = 7,
+  ABSMAX = 8,
+  Last
+};
+} // namespace IRedOp
+
+namespace FRedOp {
+enum : unsigned { MIN = 0, MAX = 1, ABSMAX = 2, Last };
+} // namespace FRedOp
+
+namespace SHFLMode {
+enum : unsigned { UP = 0, DOWN = 1, XOR = 2, IDX = 3, Last };
+} // namespace SHFLMode
+
+// Print a string corresponding to various immediate arguments to OS.
+//
+// If the value is invalid/unsupported, the functions print nothing; no errors
+// are raised. This is because these functions may be called during printing of
+// invalid IR, which should not crash the compiler. Other code (like the PISA
+// Verifier) is responsible for reporting errors on invalid IR.
+
+LLVM_ABI void printMemoryOrdering(raw_ostream &OS, const Constant *ImmArgVal);
+LLVM_ABI void printRoundingMode(raw_ostream &OS, const Constant *ImmArgVal);
+LLVM_ABI void printIRedOp(raw_ostream &OS, const Constant *ImmArgVal);
+LLVM_ABI void printFRedOp(raw_ostream &OS, const Constant *ImmArgVal);
+LLVM_ABI void printSHFLMode(raw_ostream &OS, const Constant *ImmArgVal);
+
+} // namespace pisa
+} // namespace llvm
+#endif // LLVM_IR_PISAINTRINSICUTILS_H
diff --git a/llvm/include/llvm/Support/PISAAddrSpace.h b/llvm/include/llvm/Support/PISAAddrSpace.h
new file mode 100644
index 0000000000000..426904f9bc7b7
--- /dev/null
+++ b/llvm/include/llvm/Support/PISAAddrSpace.h
@@ -0,0 +1,59 @@
+//===-- PISAAddrSpace.h ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_PISAADDRSPACE_H
+#define LLVM_SUPPORT_PISAADDRSPACE_H
+
+namespace llvm {
+
+namespace PISAAS {
+enum class AddressSpace : unsigned {
+  GENERIC = 0,
+  GLOBAL = 1,
+  CONSTANT = 2,
+  SHARED = 3,
+  PRIVATE = 4,
+};
+
+// DWARFAddressSpace for PISA, this will be emitted as DW_AT_address_class
+// attribute for variables and parameters.
+enum class DWARF_AddressSpace : unsigned {
+  DWARF_ADDR_global_shared = 0,
+  DWARF_ADDR_shared_local = 1,
+  DWARF_ADDR_private = 2,
+};
+
+constexpr int mapToDWARFAddrSpace(unsigned LLVMAddrSpace) {
+  int dwarfAddrSpace = -1;
+
+  switch (static_cast<AddressSpace>(LLVMAddrSpace)) {
+  case AddressSpace::PRIVATE:
+    dwarfAddrSpace = static_cast<int>(DWARF_AddressSpace::DWARF_ADDR_private);
+    break;
+  case AddressSpace::GLOBAL:
+  case AddressSpace::CONSTANT:
+    dwarfAddrSpace =
+        static_cast<int>(DWARF_AddressSpace::DWARF_ADDR_global_shared);
+    break;
+  case AddressSpace::SHARED:
+    dwarfAddrSpace =
+        static_cast<int>(DWARF_AddressSpace::DWARF_ADDR_shared_local);
+    break;
+  default:
+    // default is generic space, do not emit anything
+    break;
+  }
+
+  return dwarfAddrSpace;
+}
+
+} // end namespace PISAAS
+
+} // end namespace llvm
+
+#endif // LLVM_SUPPORT_PISAADDRSPACE_H
diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt
index 3037f01083308..85d235cacdfde 100644
--- a/llvm/lib/IR/CMakeLists.txt
+++ b/llvm/lib/IR/CMakeLists.txt
@@ -44,6 +44,7 @@ add_llvm_component_library(LLVMCore
   Instruction.cpp
   Instructions.cpp
   IntrinsicInst.cpp
+  PISAIntrinsicUtils.cpp
   LLVMContext.cpp
   LLVMContextImpl.cpp
   LLVMRemarkStreamer.cpp
diff --git a/llvm/lib/IR/Intrinsics.cpp b/llvm/lib/IR/Intrinsics.cpp
index 266af8e06a230..b2e1337da1aec 100644
--- a/llvm/lib/IR/Intrinsics.cpp
+++ b/llvm/lib/IR/Intrinsics.cpp
@@ -23,6 +23,7 @@
 #include "llvm/IR/IntrinsicsLoongArch.h"
 #include "llvm/IR/IntrinsicsMips.h"
 #include "llvm/IR/IntrinsicsNVPTX.h"
+#include "llvm/IR/IntrinsicsPISA.h"
 #include "llvm/IR/IntrinsicsPowerPC.h"
 #include "llvm/IR/IntrinsicsR600.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
@@ -33,6 +34,7 @@
 #include "llvm/IR/IntrinsicsXCore.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/NVVMIntrinsicUtils.h"
+#include "llvm/IR/PISAIntrinsicUtils.h"
 #include "llvm/IR/Type.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MathExtras.h"
diff --git a/llvm/lib/IR/PISAIntrinsicUtils.cpp b/llvm/lib/IR/PISAIntrinsicUtils.cpp
new file mode 100644
index 0000000000000..46c72a31681e8
--- /dev/null
+++ b/llvm/lib/IR/PISAIntrinsicUtils.cpp
@@ -0,0 +1,121 @@
+//===-- PISAIntrinsicUtils.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/PISAIntrinsicUtils.h"
+#include "llvm/Support/AtomicOrdering.h"
+
+using namespace llvm;
+using namespace llvm::pisa;
+
+void pisa::printMemoryOrdering(raw_ostream &OS, const Constant *ImmArgVal) {
+  auto *CI = cast<ConstantInt>(ImmArgVal);
+  auto AO = static_cast<AtomicOrdering>(CI->getZExtValue());
+  if (static_cast<unsigned>(AO) > static_cast<unsigned>(AtomicOrdering::LAST))
+    return; // invalid value, print nothing
+  OS << toIRString(AO);
+}
+
+void pisa::printRoundingMode(raw_ostream &OS, const Constant *ImmArgVal) {
+  auto *CI = cast<ConstantInt>(ImmArgVal);
+  int64_t Val = CI->getSExtValue();
+  switch (static_cast<RoundingMode>(Val)) {
+  default:
+    // invalid/unsupported value, print nothing
+    break;
+  case RoundingMode::TowardZero:
+    OS << ".rz";
+    break;
+  case RoundingMode::NearestTiesToEven:
+    OS << ".re";
+    break;
+  case RoundingMode::TowardPositive:
+    OS << ".ru";
+    break;
+  case RoundingMode::TowardNegative:
+    OS << ".rd";
+    break;
+  case RoundingMode::NearestTiesToAway:
+    OS << ".rna";
+    break;
+  case RoundingMode::Invalid:
+    OS << "none";
+    break;
+  }
+}
+
+void pisa::printIRedOp(raw_ostream &OS, const Constant *ImmArgVal) {
+  auto *CI = cast<ConstantInt>(ImmArgVal);
+  int64_t Val = CI->getSExtValue();
+  switch (Val) {
+  case IRedOp::SUM:
+    OS << ".sum";
+    break;
+  case IRedOp::SMIN:
+    OS << ".smin";
+    break;
+  case IRedOp::SMAX:
+    OS << ".smax";
+    break;
+  case IRedOp::UMIN:
+    OS << ".umin";
+    break;
+  case IRedOp::UMAX:
+    OS << ".umax";
+    break;
+  case IRedOp::AND:
+    OS << ".and";
+    break;
+  case IRedOp::OR:
+    OS << ".or";
+    break;
+  case IRedOp::XOR:
+    OS << ".xor";
+    break;
+  case IRedOp::ABSMAX:
+    OS << ".absmax";
+    break;
+  }
+  // invalid value, print nothing
+}
+
+void pisa::printFRedOp(raw_ostream &OS, const Constant *ImmArgVal) {
+  auto *CI = cast<ConstantInt>(ImmArgVal);
+  int64_t Val = CI->getSExtValue();
+  switch (Val) {
+  case FRedOp::MIN:
+    OS << ".min";
+    break;
+  case FRedOp::MAX:
+    OS << ".max";
+    break;
+  case FRedOp::ABSMAX:
+    OS << ".absmax";
+    break;
+  }
+  // invalid value, print nothing
+}
+
+void pisa::printSHFLMode(raw_ostream &OS, const Constant *ImmArgVal) {
+  auto *CI = cast<ConstantInt>(ImmArgVal);
+  int64_t Val = CI->getSExtValue();
+  switch (Val) {
+  case SHFLMode::UP:
+    OS << ".up";
+    break;
+  case SHFLMode::DOWN:
+    OS << ".down";
+    break;
+  case SHFLMode::XOR:
+    OS << ".xor";
+    break;
+  case SHFLMode::IDX:
+    OS << ".idx";
+    break;
+  }
+  // invalid value, print nothing
+}
diff --git a/llvm/test/CodeGen/PISA/intrinsics-address-space.ll b/llvm/test/CodeGen/PISA/intrinsics-address-space.ll
new file mode 100644
index 0000000000000..45a31eed4d5d9
--- /dev/null
+++ b/llvm/test/CodeGen/PISA/intrinsics-address-space.ll
@@ -0,0 +1,20 @@
+; The PISA address-space query intrinsics take a generic (addrspace 0) pointer
+; and return an i32 predicate. Verify they round-trip through the IR verifier
+; and that the pointer operand type is preserved.
+
+; RUN: opt -S < %s | FileCheck %s
+
+define void @test(ptr %p) {
+; CHECK-LABEL: define void @test(ptr %p)
+  %g = call i32 @llvm.pisa.isaddr.global(ptr %p)
+; CHECK: call i32 @llvm.pisa.isaddr.global(ptr %p)
+  %s = call i32 @llvm.pisa.isaddr.shared(ptr %p)
+; CHECK: call i32 @llvm.pisa.isaddr.shared(ptr %p)
+  %pr = call i32 @llvm.pisa.isaddr.private(ptr %p)
+; CHECK: call i32 @llvm.pisa.isaddr.private(ptr %p)
+  ret void
+}
+
+; CHECK: declare i32 @llvm.pisa.isaddr.global(ptr)
+; CHECK: declare i32 @llvm.pisa.isaddr.private(ptr)
+; CHECK: declare i32 @llvm.pisa.isaddr.shared(ptr)
diff --git a/llvm/test/CodeGen/PISA/intrinsics-attributes.ll b/llvm/test/CodeGen/PISA/intrinsics-attributes.ll
new file mode 100644
index 0000000000000..58ececb5d47cf
--- /dev/null
+++ b/llvm/test/CodeGen/PISA/intrinsics-attributes.ll
@@ -0,0 +1,24 @@
+; Verify that the PISA work-item / control intrinsics are materialized with the
+; attributes declared in IntrinsicsPISA.td.
+
+; RUN: opt -S < %s | FileCheck %s
+
+define void @test() {
+; CHECK-LABEL: define void @test()
+  %lane = call i32 @llvm.pisa.lane.id()
+  %sg = call i32 @llvm.pisa.subgroup.size()
+  %wd = call i32 @llvm.pisa.work.dim()
+  %am = call i32 @llvm.pisa.activemask()
+  call void @llvm.pisa.workgroup.barrier()
+  ret void
+}
+
+; CHECK: declare i32 @llvm.pisa.activemask() [[CONVMEM:#[0-9]+]]
+; CHECK: declare range(i32 0, 32) i32 @llvm.pisa.lane.id() [[NOMEM:#[0-9]+]]
+; CHECK: declare range(i32 32, 33) i32 @llvm.pisa.subgroup.size() [[NOMEM]]
+; CHECK: declare range(i32 1, 4) i32 @llvm.pisa.work.dim() [[NOMEM]]
+; CHECK: declare void @llvm.pisa.workgroup.barrier() [[CONV:#[0-9]+]]
+
+; CHECK-DAG: attributes [[CONVMEM]] = { convergent nounwind memory(none) }
+; CHECK-DAG: attributes [[NOMEM]] = { nocallback nofree nosync nounwind willreturn memory(none) }
+; CHECK-DAG: attributes [[CONV]] = { convergent nounwind }
diff --git a/llvm/test/CodeGen/PISA/intrinsics.ll b/llvm/test/CodeGen/PISA/intrinsics.ll
new file mode 100644
index 0000000000000..5754c7f15183d
--- /dev/null
+++ b/llvm/test/CodeGen/PISA/intrinsics.ll
@@ -0,0 +1,19 @@
+; Verify that the PISA target intrinsics are registered in the IR layer and
+; round-trip through the verifier/assembler.
+
+; RUN: opt -S < %s | FileCheck %s
+
+define void @test() {
+; CHECK-LABEL: define void @test()
+  %lane = call i32 @llvm.pisa.lane.id()
+; CHECK: call i32 @llvm.pisa.lane.id()
+  %sgsize = call i32 @llvm.pisa.subgroup.size()
+; CHECK: call i32 @llvm.pisa.subgroup.size()
+  %wdim = call i32 @llvm.pisa.work.dim()
+; CHECK: call i32 @llvm.pisa.work.dim()
+  ret void
+}
+
+declare i32 @llvm.pisa.lane.id()
+declare i32 @llvm.pisa.subgroup.size()
+declare i32 @llvm.pisa.work.dim()



More information about the llvm-branch-commits mailing list