[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