Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class LLVM_Attr<string name, string attrMnemonic,

def LLVM_AddressSpaceAttr :
LLVM_Attr<"AddressSpace", "address_space", [
LLVM_LLVMAddrSpaceAttrInterface,
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
]> {
let summary = "LLVM address space";
Expand Down
8 changes: 8 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMAttrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ class TBAANodeAttr : public Attribute {
using cconv::CConv;
using linkage::Linkage;
using tailcallkind::TailCallKind;

namespace detail {
/// Checks whether the given type is an LLVM type that can be loaded or stored.
bool isValidLoadStoreImpl(Type type, ptr::AtomicOrdering ordering,
std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError);
} // namespace detail
} // namespace LLVM
} // namespace mlir

Expand Down
18 changes: 18 additions & 0 deletions mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,24 @@ def LLVM_DIRecursiveTypeAttrInterface
];
}

def LLVM_LLVMAddrSpaceAttrInterface :
AttrInterface<"LLVMAddrSpaceAttrInterface"> {
let description = [{
An interface for attributes that represent LLVM address spaces.
Implementing attributes should provide access to the address space value
as an unsigned integer.
}];
let cppNamespace = "::mlir::LLVM";
let methods = [
InterfaceMethod<
/*description=*/"Returns the address space as an unsigned integer.",
/*retTy=*/"unsigned",
/*methodName=*/"getAddressSpace",
/*args=*/(ins)
>
];
}

def LLVM_TargetAttrInterface
: AttrInterface<"TargetAttrInterface", [DLTIQueryInterface]> {
let description = [{
Expand Down
35 changes: 14 additions & 21 deletions mlir/include/mlir/Dialect/LLVMIR/NVVMDialect.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.h"
#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/InferIntRangeInterface.h"
Expand All @@ -30,31 +31,23 @@

namespace mlir {
namespace NVVM {
/// Utility functions to compare NVVMMemorySpace with unsigned values.
inline bool operator==(unsigned as, NVVMMemorySpace memSpace) {
return as == static_cast<unsigned>(memSpace);
}
inline bool operator==(NVVMMemorySpace memSpace, unsigned as) {
return static_cast<unsigned>(memSpace) == as;
}
inline bool operator!=(unsigned as, NVVMMemorySpace memSpace) {
return as != static_cast<unsigned>(memSpace);
}
inline bool operator!=(NVVMMemorySpace memSpace, unsigned as) {
return static_cast<unsigned>(memSpace) != as;
}

// Shared memory has 128-bit alignment
constexpr int kSharedMemoryAlignmentBit = 128;

/// NVVM memory space identifiers.
enum NVVMMemorySpace {
/// Generic memory space identifier.
kGenericMemorySpace = 0,
/// Global memory space identifier.
kGlobalMemorySpace = 1,
/// Shared memory space identifier.
kSharedMemorySpace = 3,
/// Constant memory space identifier.
kConstantMemorySpace = 4,
/// Local memory space identifier.
kLocalMemorySpace = 5,
/// Tensor memory space identifier.
/// Tensor memory is available only in arch-accelerated
/// variants from sm100 onwards.
kTensorMemorySpace = 6,
/// Distributed shared memory space identifier.
/// Distributed shared memory is available only in sm90+.
kSharedClusterMemorySpace = 7,
};

/// A pair type of LLVM's Intrinsic ID and args (which are llvm values).
/// This type is returned by the getIntrinsicIDAndArgs() methods.
using IDArgPair =
Expand Down
37 changes: 36 additions & 1 deletion mlir/include/mlir/Dialect/LLVMIR/NVVMOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ include "mlir/IR/EnumAttr.td"
include "mlir/Dialect/GPU/IR/CompilationAttrInterfaces.td"
include "mlir/Dialect/LLVMIR/LLVMOpBase.td"
include "mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.td"
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Dialect/LLVMIR/BasicPtxBuilderInterface.td"
include "mlir/Interfaces/InferIntRangeInterface.td"
Expand Down Expand Up @@ -192,6 +193,40 @@ def CacheEvictionPriorityAttr : EnumAttr<NVVM_Dialect, CacheEvictionPriority,
let assemblyFormat = "$value";
}

// Memory Space enum definitions
/// Generic memory space identifier.
def MemSpaceGeneric : I32EnumCase<"Generic", 0, "generic">;
/// Global memory space identifier.
def MemSpaceGlobal : I32EnumCase<"Global", 1, "global">;
/// Shared memory space identifier.
def MemSpaceShared : I32EnumCase<"Shared", 3, "shared">;
/// Constant memory space identifier.
def MemSpaceConstant : I32EnumCase<"Constant", 4, "constant">;
/// Local memory space identifier.
def MemSpaceLocal : I32EnumCase<"Local", 5, "local">;
/// Tensor memory space identifier.
/// Tensor memory is available only in arch-accelerated
/// variants from sm100 onwards.
def MemSpaceTensor : I32EnumCase<"Tensor", 6, "tensor">;
/// Distributed shared memory space identifier.
/// Distributed shared memory is available only in sm90+.
def MemSpaceSharedCluster : I32EnumCase<"SharedCluster", 7, "shared_cluster">;

def NVVMMemorySpace : I32Enum<"NVVMMemorySpace", "NVVM Memory Space",
[MemSpaceGeneric, MemSpaceGlobal, MemSpaceShared,
MemSpaceConstant, MemSpaceLocal, MemSpaceTensor,
MemSpaceSharedCluster]> {
let cppNamespace = "::mlir::NVVM";
}

def NVVMMemorySpaceAttr :
EnumAttr<NVVM_Dialect, NVVMMemorySpace, "memory_space", [
DeclareAttrInterfaceMethods<LLVM_LLVMAddrSpaceAttrInterface>,
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
]> {
let assemblyFormat = "`<` $value `>`";
}

//===----------------------------------------------------------------------===//
// NVVM intrinsic operations
//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -3592,7 +3627,7 @@ def NVVM_MapaOp: NVVM_Op<"mapa",
string llvmBuilder = [{
int addrSpace = llvm::cast<LLVMPointerType>(op.getA().getType()).getAddressSpace();

bool isSharedMemory = addrSpace == NVVM::NVVMMemorySpace::kSharedMemorySpace;
bool isSharedMemory = addrSpace == static_cast<int> (NVVM::NVVMMemorySpace::Shared);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabianmcg is this supposed to be a static_cast<unsigned>? If not, why?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, that should be an unsigned cast, line 3628 also should be changed to unsigned.


auto intId = isSharedMemory? llvm::Intrinsic::nvvm_mapa_shared_cluster : llvm::Intrinsic::nvvm_mapa;
$res = createIntrinsicCall(builder, intId, {$a, $b});
Expand Down
10 changes: 4 additions & 6 deletions mlir/lib/Conversion/GPUToNVVM/LowerGpuOpsToNVVMOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -451,16 +451,14 @@ void mlir::configureGpuToNVVMTypeConverter(LLVMTypeConverter &converter) {
converter, [](gpu::AddressSpace space) -> unsigned {
switch (space) {
case gpu::AddressSpace::Global:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kGlobalMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Global);
case gpu::AddressSpace::Workgroup:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kSharedMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Shared);
case gpu::AddressSpace::Private:
return 0;
}
llvm_unreachable("unknown address space enum value");
return 0;
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Generic);
Copy link

Copilot AI Sep 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change modifies the control flow by adding a return statement in the default case. This could affect performance profiling data by changing the execution path from an unreachable code path to a valid return.

Copilot generated this review using guidance from repository custom instructions.
});
// Lowering for MMAMatrixType.
converter.addConversion([&](gpu::MMAMatrixType type) -> Type {
Expand Down Expand Up @@ -648,7 +646,7 @@ void mlir::populateGpuToNVVMConversionPatterns(
GPUFuncOpLoweringOptions{
/*allocaAddrSpace=*/0,
/*workgroupAddrSpace=*/
static_cast<unsigned>(NVVM::NVVMMemorySpace::kSharedMemorySpace),
static_cast<unsigned>(NVVM::NVVMMemorySpace::Shared),
StringAttr::get(&converter.getContext(),
NVVM::NVVMDialect::getKernelFuncAttrName()),
StringAttr::get(&converter.getContext(),
Expand Down
10 changes: 4 additions & 6 deletions mlir/lib/Conversion/NVGPUToNVVM/NVGPUToNVVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,16 +405,14 @@ struct ConvertNVGPUToNVVMPass
converter, [](gpu::AddressSpace space) -> unsigned {
switch (space) {
case gpu::AddressSpace::Global:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kGlobalMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Global);
case gpu::AddressSpace::Workgroup:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kSharedMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Shared);
case gpu::AddressSpace::Private:
return 0;
}
llvm_unreachable("unknown address space enum value");
return 0;
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Generic);
Copy link

Copilot AI Sep 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change modifies the control flow by adding a return statement in the default case. This could affect performance profiling data by changing the execution path from an unreachable code path to a valid return.

Copilot generated this review using guidance from repository custom instructions.
});
/// device-side async tokens cannot be materialized in nvvm. We just
/// convert them to a dummy i32 type in order to easily drop them during
Expand Down Expand Up @@ -677,7 +675,7 @@ struct NVGPUAsyncCopyLowering
adaptor.getSrcIndices());
// Intrinsics takes a global pointer so we need an address space cast.
auto srcPointerGlobalType = LLVM::LLVMPointerType::get(
op->getContext(), NVVM::NVVMMemorySpace::kGlobalMemorySpace);
op->getContext(), static_cast<unsigned>(NVVM::NVVMMemorySpace::Global));
scrPtr = LLVM::AddrSpaceCastOp::create(b, srcPointerGlobalType, scrPtr);
int64_t dstElements = adaptor.getDstElements().getZExtValue();
int64_t sizeInBytes =
Expand Down
8 changes: 3 additions & 5 deletions mlir/lib/Dialect/GPU/TransformOps/GPUTransformOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,14 @@ void transform::ApplyGPUToNVVMConversionPatternsOp::populatePatterns(
llvmTypeConverter, [](AddressSpace space) -> unsigned {
switch (space) {
case AddressSpace::Global:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kGlobalMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Global);
case AddressSpace::Workgroup:
return static_cast<unsigned>(
NVVM::NVVMMemorySpace::kSharedMemorySpace);
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Shared);
case AddressSpace::Private:
return 0;
}
llvm_unreachable("unknown address space enum value");
return 0;
return static_cast<unsigned>(NVVM::NVVMMemorySpace::Generic);
Copy link

Copilot AI Sep 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change modifies the control flow by adding a return statement in the default case. This could affect performance profiling data by changing the execution path from an unreachable code path to a valid return.

Copilot generated this review using guidance from repository custom instructions.
});
// Used in GPUToNVVM/WmmaOpsToNvvm.cpp so attaching here for now.
// TODO: We should have a single to_nvvm_type_converter.
Expand Down
14 changes: 8 additions & 6 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ void LLVMDialect::registerAttributes() {
//===----------------------------------------------------------------------===//

/// Checks whether the given type is an LLVM type that can be loaded or stored.
static bool isValidLoadStoreImpl(Type type, ptr::AtomicOrdering ordering,
std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError) {
bool LLVM::detail::isValidLoadStoreImpl(
Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError) {
if (!isLoadableType(type)) {
if (emitError)
emitError() << "type must be LLVM type with size, but got " << type;
Expand All @@ -87,14 +87,16 @@ bool AddressSpaceAttr::isValidLoad(
Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError) const {
return isValidLoadStoreImpl(type, ordering, alignment, dataLayout, emitError);
return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
emitError);
}

bool AddressSpaceAttr::isValidStore(
Type type, ptr::AtomicOrdering ordering, std::optional<int64_t> alignment,
const ::mlir::DataLayout *dataLayout,
function_ref<InFlightDiagnostic()> emitError) const {
return isValidLoadStoreImpl(type, ordering, alignment, dataLayout, emitError);
return detail::isValidLoadStoreImpl(type, ordering, alignment, dataLayout,
emitError);
}

bool AddressSpaceAttr::isValidAtomicOp(
Expand Down
6 changes: 3 additions & 3 deletions mlir/lib/Dialect/LLVMIR/IR/LLVMTypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,14 +703,14 @@ const llvm::fltSemantics &LLVMPPCFP128Type::getFloatSemantics() const {
//===----------------------------------------------------------------------===//

/// Check whether type is a compatible ptr type. These are pointer-like types
/// with no element type, no metadata, and using the LLVM AddressSpaceAttr
/// memory space.
/// with no element type, no metadata, and using the LLVM
/// LLVMAddrSpaceAttrInterface memory space.
static bool isCompatiblePtrType(Type type) {
auto ptrTy = dyn_cast<PtrLikeTypeInterface>(type);
if (!ptrTy)
return false;
return !ptrTy.hasPtrMetadata() && ptrTy.getElementType() == nullptr &&
isa<AddressSpaceAttr>(ptrTy.getMemorySpace());
isa<LLVMAddrSpaceAttrInterface>(ptrTy.getMemorySpace());
}

bool mlir::LLVM::isCompatibleOuterType(Type type) {
Expand Down
Loading
Loading