Skip to content

Commit e621690

Browse files
authored
[MLIR][LLVM] Improve atomic verifier to properly support larger types (llvm#92120)
This commit extends the verifier for atomics to properly verify larger types. Beforehand, the verifier strictly rejected larger integer types, while it now consults the data layout to determine if their bitsize is a power of two. This behavior reflects what LLVM's verifier is checking for.
1 parent d7bb072 commit e621690

File tree

3 files changed

+35
-22
lines changed

3 files changed

+35
-22
lines changed

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

+16-21
Original file line numberDiff line numberDiff line change
@@ -839,34 +839,28 @@ void LoadOp::getEffects(
839839
}
840840

841841
/// Returns true if the given type is supported by atomic operations. All
842-
/// integer and float types with limited bit width are supported. Additionally,
843-
/// depending on the operation pointers may be supported as well.
844-
static bool isTypeCompatibleWithAtomicOp(Type type, bool isPointerTypeAllowed) {
845-
if (llvm::isa<LLVMPointerType>(type))
846-
return isPointerTypeAllowed;
847-
848-
std::optional<unsigned> bitWidth;
849-
if (auto floatType = llvm::dyn_cast<FloatType>(type)) {
842+
/// integer, float, and pointer types with a power-of-two bitsize and a minimal
843+
/// size of 8 bits are supported.
844+
static bool isTypeCompatibleWithAtomicOp(Type type,
845+
const DataLayout &dataLayout) {
846+
if (!isa<IntegerType, LLVMPointerType>(type))
850847
if (!isCompatibleFloatingPointType(type))
851848
return false;
852-
bitWidth = floatType.getWidth();
853-
}
854-
if (auto integerType = llvm::dyn_cast<IntegerType>(type))
855-
bitWidth = integerType.getWidth();
856-
// The type is neither an integer, float, or pointer type.
857-
if (!bitWidth)
849+
850+
llvm::TypeSize bitWidth = dataLayout.getTypeSizeInBits(type);
851+
if (bitWidth.isScalable())
858852
return false;
859-
return *bitWidth == 8 || *bitWidth == 16 || *bitWidth == 32 ||
860-
*bitWidth == 64;
853+
// Needs to be at least 8 bits and a power of two.
854+
return bitWidth >= 8 && (bitWidth & (bitWidth - 1)) == 0;
861855
}
862856

863857
/// Verifies the attributes and the type of atomic memory access operations.
864858
template <typename OpTy>
865859
LogicalResult verifyAtomicMemOp(OpTy memOp, Type valueType,
866860
ArrayRef<AtomicOrdering> unsupportedOrderings) {
867861
if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
868-
if (!isTypeCompatibleWithAtomicOp(valueType,
869-
/*isPointerTypeAllowed=*/true))
862+
DataLayout dataLayout = DataLayout::closest(memOp);
863+
if (!isTypeCompatibleWithAtomicOp(valueType, dataLayout))
870864
return memOp.emitOpError("unsupported type ")
871865
<< valueType << " for atomic access";
872866
if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
@@ -2694,7 +2688,8 @@ LogicalResult AtomicRMWOp::verify() {
26942688
if (!mlir::LLVM::isCompatibleFloatingPointType(valType))
26952689
return emitOpError("expected LLVM IR floating point type");
26962690
} else if (getBinOp() == AtomicBinOp::xchg) {
2697-
if (!isTypeCompatibleWithAtomicOp(valType, /*isPointerTypeAllowed=*/true))
2691+
DataLayout dataLayout = DataLayout::closest(*this);
2692+
if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
26982693
return emitOpError("unexpected LLVM IR type for 'xchg' bin_op");
26992694
} else {
27002695
auto intType = llvm::dyn_cast<IntegerType>(valType);
@@ -2741,8 +2736,8 @@ LogicalResult AtomicCmpXchgOp::verify() {
27412736
if (!ptrType)
27422737
return emitOpError("expected LLVM IR pointer type for operand #0");
27432738
auto valType = getVal().getType();
2744-
if (!isTypeCompatibleWithAtomicOp(valType,
2745-
/*isPointerTypeAllowed=*/true))
2739+
DataLayout dataLayout = DataLayout::closest(*this);
2740+
if (!isTypeCompatibleWithAtomicOp(valType, dataLayout))
27462741
return emitOpError("unexpected LLVM IR type");
27472742
if (getSuccessOrdering() < AtomicOrdering::monotonic ||
27482743
getFailureOrdering() < AtomicOrdering::monotonic)

mlir/test/Dialect/LLVMIR/invalid.mlir

+14
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,13 @@ func.func @load_unsupported_type(%ptr : !llvm.ptr) {
160160

161161
// -----
162162

163+
func.func @load_unsupported_type(%ptr : !llvm.ptr) {
164+
// expected-error@below {{unsupported type 'i33' for atomic access}}
165+
%1 = llvm.load %ptr atomic monotonic {alignment = 16 : i64} : !llvm.ptr -> i33
166+
}
167+
168+
// -----
169+
163170
func.func @load_unaligned_atomic(%ptr : !llvm.ptr) {
164171
// expected-error@below {{expected alignment for atomic access}}
165172
%1 = llvm.load %ptr atomic monotonic : !llvm.ptr -> f32
@@ -195,6 +202,13 @@ func.func @store_unsupported_type(%val : i1, %ptr : !llvm.ptr) {
195202

196203
// -----
197204

205+
func.func @store_unsupported_type(%val : i48, %ptr : !llvm.ptr) {
206+
// expected-error@below {{unsupported type 'i48' for atomic access}}
207+
llvm.store %val, %ptr atomic monotonic {alignment = 16 : i64} : i48, !llvm.ptr
208+
}
209+
210+
// -----
211+
198212
func.func @store_unaligned_atomic(%val : f32, %ptr : !llvm.ptr) {
199213
// expected-error@below {{expected alignment for atomic access}}
200214
llvm.store %val, %ptr atomic monotonic : f32, !llvm.ptr

mlir/test/Dialect/LLVMIR/roundtrip.mlir

+5-1
Original file line numberDiff line numberDiff line change
@@ -385,15 +385,19 @@ func.func @atomic_load(%ptr : !llvm.ptr) {
385385
%0 = llvm.load %ptr atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> f32
386386
// CHECK: llvm.load volatile %{{.*}} atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr -> f32
387387
%1 = llvm.load volatile %ptr atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : !llvm.ptr -> f32
388+
// CHECK: llvm.load %{{.*}} atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> i128
389+
%2 = llvm.load %ptr atomic monotonic {alignment = 4 : i64} : !llvm.ptr -> i128
388390
llvm.return
389391
}
390392

391393
// CHECK-LABEL: @atomic_store
392-
func.func @atomic_store(%val : f32, %ptr : !llvm.ptr) {
394+
func.func @atomic_store(%val : f32, %large_val : i256, %ptr : !llvm.ptr) {
393395
// CHECK: llvm.store %{{.*}}, %{{.*}} atomic monotonic {alignment = 4 : i64} : f32, !llvm.ptr
394396
llvm.store %val, %ptr atomic monotonic {alignment = 4 : i64} : f32, !llvm.ptr
395397
// CHECK: llvm.store volatile %{{.*}}, %{{.*}} atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : f32, !llvm.ptr
396398
llvm.store volatile %val, %ptr atomic syncscope("singlethread") monotonic {alignment = 16 : i64} : f32, !llvm.ptr
399+
// CHECK: llvm.store %{{.*}}, %{{.*}} atomic monotonic {alignment = 4 : i64} : i256, !llvm.ptr
400+
llvm.store %large_val, %ptr atomic monotonic {alignment = 4 : i64} : i256, !llvm.ptr
397401
llvm.return
398402
}
399403

0 commit comments

Comments
 (0)