[flang-commits] [flang] 69ee5a5 - [flang][hlfir] Add hlfir.copy_in and hlfir.copy_out operations
Jean Perier via flang-commits
flang-commits at lists.llvm.org
Wed Jan 25 00:51:59 PST 2023
Author: Jean Perier
Date: 2023-01-25T09:50:52+01:00
New Revision: 69ee5a53e58dd8018dc50d728c8d4c1254385009
URL: https://github.com/llvm/llvm-project/commit/69ee5a53e58dd8018dc50d728c8d4c1254385009
DIFF: https://github.com/llvm/llvm-project/commit/69ee5a53e58dd8018dc50d728c8d4c1254385009.diff
LOG: [flang][hlfir] Add hlfir.copy_in and hlfir.copy_out operations
These operations implement the optional copy of a non contiguous
variable into a temporary before a call, and the copy back from the
temporary after the call.
Differential Revision: https://reviews.llvm.org/D142342
Added:
flang/test/HLFIR/copy-in-out.fir
Modified:
flang/include/flang/Optimizer/Dialect/FIRTypes.td
flang/include/flang/Optimizer/HLFIR/HLFIROps.td
flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
Removed:
################################################################################
diff --git a/flang/include/flang/Optimizer/Dialect/FIRTypes.td b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
index 4dbb61179a994..75694071818dc 100644
--- a/flang/include/flang/Optimizer/Dialect/FIRTypes.td
+++ b/flang/include/flang/Optimizer/Dialect/FIRTypes.td
@@ -561,6 +561,7 @@ def fir_VoidType : FIR_Type<"Void", "void"> {
// Whether a type is a BaseBoxType
def IsBaseBoxTypePred
: CPred<"$_self.isa<::fir::BaseBoxType>()">;
+def fir_BaseBoxType : Type<IsBaseBoxTypePred, "fir.box or fir.class type">;
// Generalized FIR and standard dialect types representing intrinsic types
def AnyIntegerLike : TypeConstraint<Or<[SignlessIntegerLike.predicate,
diff --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index 82bfb2a83f396..3228685122834 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -523,4 +523,72 @@ def hlfir_DestroyOp : hlfir_Op<"destroy", []> {
let assemblyFormat = "$expr attr-dict `:` qualified(type($expr))";
}
+def hlfir_CopyInOp : hlfir_Op<"copy_in", []> {
+ let summary = "copy a variable into a contiguous temporary if it is not contiguous";
+ let description = [{
+ Copy a variable into a contiguous temporary if the variable is not
+ an absent optional and is not contiguous at runtime. When a copy is made this
+ operation returns the temporary as first result, otherwise, it returns the
+ potentially absent variable storage. The second result indicates if a copy
+ was made.
+
+ This operation is meant to be used in combination with the hlfir.copy_out
+ operation that deletes the temporary if it was created and copies the data
+ back if needed.
+ This operation allows passing non contiguous arrays to contiguous dummy
+ arguments, which is possible in Fortran procedure references.
+
+ To deal with the optional case, an extra boolean value can be pass to the
+ operation. In such cases, the copy-in will only be done if "var_is_present"
+ is true and, when it is false, the original value will be returned instead.
+ }];
+
+ let arguments = (ins fir_BaseBoxType:$var,
+ Optional<I1>:$var_is_present);
+
+ let results = (outs fir_BaseBoxType, I1);
+
+ let assemblyFormat = [{
+ $var (`handle_optional` $var_is_present^)?
+ attr-dict `:` functional-type(operands, results)
+ }];
+
+ let builders = [
+ OpBuilder<(ins "mlir::Value":$var, "mlir::Value":$var_is_present)>
+ ];
+
+ let extraClassDeclaration = [{
+ /// Get the resulting copied-in fir.box or fir.class.
+ mlir::Value getCopiedIn() {
+ return getResult(0);
+ }
+
+ /// Get the result indicating if a copy was made.
+ mlir::Value getWasCopied() {
+ return getResult(1);
+ }
+ }];
+}
+
+def hlfir_CopyOutOp : hlfir_Op<"copy_out", []> {
+ let summary = "copy out a variable after a copy in";
+ let description = [{
+ If the variable was copied in a temporary in the related hlfir.copy_in,
+ optionally copy back the temporary value to it (that may have been
+ modified between the hlfir.copy_in and hlfir.copy_out). Then deallocate
+ the temporary.
+ The copy back is done if $var is provided and $was_copied is true.
+ The deallocation of $temp is done if $was_copied is true.
+ }];
+
+ let arguments = (ins fir_BaseBoxType:$temp,
+ I1:$was_copied,
+ Optional<fir_BaseBoxType>:$var);
+
+ let assemblyFormat = [{
+ $temp `,` $was_copied (`to` $var^)?
+ attr-dict `:` functional-type(operands, results)
+ }];
+}
+
#endif // FORTRAN_DIALECT_HLFIR_OPS
diff --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index ecdc490f204ff..56cb542bcdcf4 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -515,5 +515,15 @@ void hlfir::NullOp::build(mlir::OpBuilder &builder,
fir::ReferenceType::get(builder.getNoneType()));
}
+//===----------------------------------------------------------------------===//
+// CopyInOp
+//===----------------------------------------------------------------------===//
+
+void hlfir::CopyInOp::build(mlir::OpBuilder &builder,
+ mlir::OperationState &odsState, mlir::Value var,
+ mlir::Value var_is_present) {
+ return build(builder, odsState, var.getType(), var, var_is_present);
+}
+
#define GET_OP_CLASSES
#include "flang/Optimizer/HLFIR/HLFIROps.cpp.inc"
diff --git a/flang/test/HLFIR/copy-in-out.fir b/flang/test/HLFIR/copy-in-out.fir
new file mode 100644
index 0000000000000..be24dcc975fe6
--- /dev/null
+++ b/flang/test/HLFIR/copy-in-out.fir
@@ -0,0 +1,27 @@
+// Test hlfir.copy_in and hlfir.copy_out operation parse, verify (no errors),
+// and unparse.
+
+// RUN: fir-opt %s | fir-opt | FileCheck %s
+
+func.func @test_copy_in(%box: !fir.box<!fir.array<?xf64>>, %is_present: i1) {
+ %0:2 = hlfir.copy_in %box : (!fir.box<!fir.array<?xf64>>) -> (!fir.box<!fir.array<?xf64>>, i1)
+ %1:2 = hlfir.copy_in %box handle_optional %is_present : (!fir.box<!fir.array<?xf64>>, i1) -> (!fir.box<!fir.array<?xf64>>, i1)
+ return
+}
+// CHECK-LABEL: func.func @test_copy_in(
+// CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf64>>,
+// CHECK-SAME: %[[VAL_1:.*]]: i1
+// CHECK: %[[VAL_2:.*]]:2 = hlfir.copy_in %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>) -> (!fir.box<!fir.array<?xf64>>, i1)
+// CHECK: %[[VAL_3:.*]]:2 = hlfir.copy_in %[[VAL_0]] handle_optional %[[VAL_1]] : (!fir.box<!fir.array<?xf64>>, i1) -> (!fir.box<!fir.array<?xf64>>, i1)
+
+func.func @test_copy_out(%box: !fir.box<!fir.array<?xf64>>, %temp: !fir.box<!fir.array<?xf64>>, %was_copied: i1) {
+ hlfir.copy_out %temp, %was_copied : (!fir.box<!fir.array<?xf64>>, i1) -> ()
+ hlfir.copy_out %temp, %was_copied to %box : (!fir.box<!fir.array<?xf64>>, i1, !fir.box<!fir.array<?xf64>>) -> ()
+ return
+}
+// CHECK-LABEL: func.func @test_copy_out(
+// CHECK-SAME: %[[VAL_0:[^:]*]]: !fir.box<!fir.array<?xf64>>,
+// CHECK-SAME: %[[VAL_1:.*]]: !fir.box<!fir.array<?xf64>>,
+// CHECK-SAME: %[[VAL_2:.*]]: i1) {
+// CHECK: hlfir.copy_out %[[VAL_1]], %[[VAL_2]] : (!fir.box<!fir.array<?xf64>>, i1) -> ()
+// CHECK: hlfir.copy_out %[[VAL_1]], %[[VAL_2]] to %[[VAL_0]] : (!fir.box<!fir.array<?xf64>>, i1, !fir.box<!fir.array<?xf64>>) -> ()
More information about the flang-commits
mailing list