diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td index fdf0db9d3c75d..b162af55d66bb 100644 --- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td +++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td @@ -130,7 +130,7 @@ def hlfir_DeclareOp : hlfir_Op<"declare", [AttrSizedOperandSegments, let hasVerifier = 1; } -def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> { +def fir_AssignOp : hlfir_Op<"assign", [DeclareOpInterfaceMethods]> { let summary = "Assign an expression or variable value to a Fortran variable"; let description = [{ @@ -166,7 +166,7 @@ def fir_AssignOp : hlfir_Op<"assign", [MemoryEffects<[MemWrite]>]> { }]; let arguments = (ins AnyFortranEntity:$rhs, - Arg:$lhs, + AnyFortranVariable:$lhs, UnitAttr:$realloc, UnitAttr:$keep_lhs_length_if_realloc, UnitAttr:$temporary_lhs); diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp index ed301c74c9ede..b593383ff2848 100644 --- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp +++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp @@ -90,6 +90,62 @@ llvm::LogicalResult hlfir::AssignOp::verify() { return mlir::success(); } +void hlfir::AssignOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance> + &effects) { + mlir::OpOperand &rhs = getRhsMutable(); + mlir::OpOperand &lhs = getLhsMutable(); + mlir::Type rhsType = getRhs().getType(); + mlir::Type lhsType = getLhs().getType(); + if (mlir::isa(hlfir::getFortranElementType(lhsType))) { + // For derived type assignments, set unknown read/write effects since it + // is not known here if user defined finalization is needed, and also + // because allocatable components may lead to "deeper" read/write effects + // that cannot be described with this API. + effects.emplace_back(mlir::MemoryEffects::Read::get(), + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Write::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + // Read effect when RHS is a variable. + if (hlfir::isFortranVariableType(rhsType)) { + if (hlfir::isBoxAddressType(rhsType)) { + // Unknown read effect if the RHS is a descriptor since the read effect + // on the data cannot be described. + effects.emplace_back(mlir::MemoryEffects::Read::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + effects.emplace_back(mlir::MemoryEffects::Read::get(), &rhs, + mlir::SideEffects::DefaultResource::get()); + } + } + + // Write effects on LHS. + if (hlfir::isBoxAddressType(lhsType)) { + // If the LHS is a descriptor, the descriptor will be read and the data + // write cannot be described in this API (and the descriptor may be + // written to in case of realloc, which is covered by the unknown write + // effect. + effects.emplace_back(mlir::MemoryEffects::Read::get(), &lhs, + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Write::get(), + mlir::SideEffects::DefaultResource::get()); + } else { + effects.emplace_back(mlir::MemoryEffects::Write::get(), &lhs, + mlir::SideEffects::DefaultResource::get()); + } + } + + if (getRealloc()) { + // Reallocation of the data cannot be precisely described by this API. + effects.emplace_back(mlir::MemoryEffects::Free::get(), + mlir::SideEffects::DefaultResource::get()); + effects.emplace_back(mlir::MemoryEffects::Allocate::get(), + mlir::SideEffects::DefaultResource::get()); + } +} + //===----------------------------------------------------------------------===// // DeclareOp //===----------------------------------------------------------------------===// diff --git a/flang/test/HLFIR/assign-side-effects.fir b/flang/test/HLFIR/assign-side-effects.fir new file mode 100644 index 0000000000000..dfd1c5886e4fa --- /dev/null +++ b/flang/test/HLFIR/assign-side-effects.fir @@ -0,0 +1,31 @@ +// Test side effects of hlfir.assign op. +// RUN: fir-opt %s --test-side-effects --verify-diagnostics + +func.func @test1(%x: !fir.ref, %i: i32) { + // expected-remark @below {{found an instance of 'write' on a op operand, on resource ''}} + hlfir.assign %i to %x : i32, !fir.ref + return +} + +func.func @test2(%x: !fir.ref, %y: !fir.ref) { + // expected-remark @below {{found an instance of 'write' on a op operand, on resource ''}} + // expected-remark @below {{found an instance of 'read' on a op operand, on resource ''}} + hlfir.assign %y to %x : !fir.ref, !fir.ref + return +} + +func.func @test3(%x: !fir.ref>, %y: !fir.ref>) { + // expected-remark @below {{found an instance of 'write' on resource ''}} + // expected-remark @below {{found an instance of 'read' on resource ''}} + hlfir.assign %y to %x : !fir.ref>, !fir.ref> + return +} + +func.func @test4(%x: !fir.ref>>>, %y: !fir.box>) { + // expected-remark @below {{found an instance of 'read' on a op operand, on resource ''}} + // expected-remark @below {{found an instance of 'write' on resource ''}} + // expected-remark @below {{found an instance of 'free' on resource ''}} + // expected-remark @below {{found an instance of 'allocate' on resource ''}} + hlfir.assign %y to %x realloc : !fir.box>, !fir.ref>>> + return +}