diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td index 7ceec72144eb5..e9ed7f1186ee5 100644 --- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td +++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td @@ -326,9 +326,10 @@ def LLVM_GEPOp : LLVM_Op<"getelementptr", [Pure, } def LLVM_LoadOp : LLVM_MemAccessOpBase<"load", - [DeclareOpInterfaceMethods, + [DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, DeclareOpInterfaceMethods]> { - dag args = (ins Arg, "", [MemRead]>:$addr, + dag args = (ins LLVM_PointerTo:$addr, OptionalAttr:$alignment, UnitAttr:$volatile_, UnitAttr:$nontemporal, @@ -399,10 +400,11 @@ def LLVM_LoadOp : LLVM_MemAccessOpBase<"load", } def LLVM_StoreOp : LLVM_MemAccessOpBase<"store", - [DeclareOpInterfaceMethods, + [DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods, DeclareOpInterfaceMethods]> { dag args = (ins LLVM_LoadableType:$value, - Arg,"",[MemWrite]>:$addr, + LLVM_PointerTo:$addr, OptionalAttr:$alignment, UnitAttr:$volatile_, UnitAttr:$nontemporal, diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp index ae01f7c462152..c3575d299b388 100644 --- a/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp +++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp @@ -812,6 +812,22 @@ Type GEPOp::getResultPtrElementType() { // LoadOp //===----------------------------------------------------------------------===// +void LoadOp::getEffects( + SmallVectorImpl> + &effects) { + effects.emplace_back(MemoryEffects::Read::get(), getAddr()); + // Volatile operations can have target-specific read-write effects on + // memory besides the one referred to by the pointer operand. + // Similarly, atomic operations that are monotonic or stricter cause + // synchronization that from a language point-of-view, are arbitrary + // read-writes into memory. + if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic && + getOrdering() != AtomicOrdering::unordered)) { + effects.emplace_back(MemoryEffects::Write::get()); + effects.emplace_back(MemoryEffects::Read::get()); + } +} + /// Returns true if the given type is supported by atomic operations. All /// integer and float types with limited bit width are supported. Additionally, /// depending on the operation pointers may be supported as well. @@ -932,6 +948,22 @@ static void printLoadType(OpAsmPrinter &printer, Operation *op, Type type, // StoreOp //===----------------------------------------------------------------------===// +void StoreOp::getEffects( + SmallVectorImpl> + &effects) { + effects.emplace_back(MemoryEffects::Write::get(), getAddr()); + // Volatile operations can have target-specific read-write effects on + // memory besides the one referred to by the pointer operand. + // Similarly, atomic operations that are monotonic or stricter cause + // synchronization that from a language point-of-view, are arbitrary + // read-writes into memory. + if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic && + getOrdering() != AtomicOrdering::unordered)) { + effects.emplace_back(MemoryEffects::Write::get()); + effects.emplace_back(MemoryEffects::Read::get()); + } +} + LogicalResult StoreOp::verify() { Type valueType = getValue().getType(); return verifyAtomicMemOp(*this, valueType, diff --git a/mlir/test/Dialect/LLVMIR/canonicalize.mlir b/mlir/test/Dialect/LLVMIR/canonicalize.mlir index 3e7f689bdc03e..ed7efabb44b1a 100644 --- a/mlir/test/Dialect/LLVMIR/canonicalize.mlir +++ b/mlir/test/Dialect/LLVMIR/canonicalize.mlir @@ -191,3 +191,20 @@ llvm.func @alloca_dce() { %0 = llvm.alloca %c1_i64 x i32 : (i64) -> !llvm.ptr llvm.return } + +// ----- + +// CHECK-LABEL: func @volatile_load +llvm.func @volatile_load(%x : !llvm.ptr) { + // A volatile load may have side-effects such as a write operation to arbitrary memory. + // Make sure it is not removed. + // CHECK: llvm.load volatile + %0 = llvm.load volatile %x : !llvm.ptr -> i8 + // Same with monotonic atomics and any stricter modes. + // CHECK: llvm.load %{{.*}} atomic monotonic + %2 = llvm.load %x atomic monotonic { alignment = 1 } : !llvm.ptr -> i8 + // But not unordered! + // CHECK-NOT: llvm.load %{{.*}} atomic unordered + %3 = llvm.load %x atomic unordered { alignment = 1 } : !llvm.ptr -> i8 + llvm.return +}