[flang-commits] [flang] 583168e - [flang][hlfir] Parse unordered attribute for elemental operations.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Thu Jun 29 10:36:02 PDT 2023


Author: Slava Zakharin
Date: 2023-06-29T10:35:43-07:00
New Revision: 583168ee86a72be2ed05744ae601e42ecae0d14a

URL: https://github.com/llvm/llvm-project/commit/583168ee86a72be2ed05744ae601e42ecae0d14a
DIFF: https://github.com/llvm/llvm-project/commit/583168ee86a72be2ed05744ae601e42ecae0d14a.diff

LOG: [flang][hlfir] Parse unordered attribute for elemental operations.

By default, `hlfir.elemental` and `hlfir.elemental_addr` must process
the elements in order. The `unordered` attribute may be set,
if it is safe to process the elements out of order.
This patch just adds parsing support for the new attribute.

Reviewed By: jeanPerier, tblah

Differential Revision: https://reviews.llvm.org/D154032

Added: 
    

Modified: 
    flang/include/flang/Optimizer/HLFIR/HLFIROps.td
    flang/test/HLFIR/element-addr.fir
    flang/test/HLFIR/elemental.fir

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
index 5f3f5337924310..1bb0e3f9c58599 100644
--- a/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
+++ b/flang/include/flang/Optimizer/HLFIR/HLFIROps.td
@@ -731,10 +731,9 @@ def hlfir_ElementalOp : hlfir_Op<"elemental", [RecursiveMemoryEffects, hlfir_Ele
     The shape and typeparams operands represent the extents and type
     parameters of the resulting array value.
 
-    Currently there is no way to control the iteration order of a hlfir
-    elemental operation and so operations in the body of the elemental must
-    not have side effects. If this is changed, an attribute must be added so
-    that the elemental inlining pass can skip these impure elementals.
+    The unordered attribute can be set to allow out of order processing
+    of the indices. This is safe only if the operations in the body
+    of the elemental do not have side effects.
 
 
     Example: Y + X,  with Integer :: X(10, 20), Y(10,20)
@@ -754,14 +753,15 @@ def hlfir_ElementalOp : hlfir_Op<"elemental", [RecursiveMemoryEffects, hlfir_Ele
 
   let arguments = (ins
     AnyShapeType:$shape,
-    Variadic<AnyIntegerType>:$typeparams
+    Variadic<AnyIntegerType>:$typeparams,
+    OptionalAttr<UnitAttr>:$unordered
   );
 
   let results = (outs hlfir_ExprType);
   let regions = (region SizedRegion<1>:$region);
 
   let assemblyFormat = [{
-    $shape (`typeparams` $typeparams^)?
+    $shape (`typeparams` $typeparams^)? (`unordered` $unordered^)?
     attr-dict `:` functional-type(operands, results)
     $region
     }];
@@ -775,13 +775,12 @@ def hlfir_ElementalOp : hlfir_Op<"elemental", [RecursiveMemoryEffects, hlfir_Ele
       }
       /// ElementalOpInterface implementation.
 
-      mlir::Region& getElementalRegion() {return getRegion();}
+      mlir::Region& getElementalRegion() { return getRegion(); }
       mlir::Value getElementEntity();
-      mlir::Region* getElementCleanup() {return nullptr;}
+      mlir::Region* getElementCleanup() { return nullptr; }
 
       /// Must this elemental be evaluated in order?
-      /// TODO: add attribute and set it in lowering.
-      bool isOrdered() {return true;}
+      bool isOrdered() { return !getUnordered(); }
   }];
 
   let skipDefaultBuilders = 1;
@@ -1209,7 +1208,9 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R
 
   let arguments = (ins
     fir_ShapeType:$shape,
-    Variadic<AnyIntegerType>:$typeparams);
+    Variadic<AnyIntegerType>:$typeparams,
+    OptionalAttr<UnitAttr>:$unordered
+  );
 
   let regions = (region  SizedRegion<1>:$body,
                          MaxSizedRegion<1>:$cleanup);
@@ -1219,7 +1220,7 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R
   ];
 
   let assemblyFormat = [{
-    $shape (`typeparams` $typeparams^)?
+    $shape (`typeparams` $typeparams^)? (`unordered` $unordered^)?
     attr-dict `:` type(operands) $body
     custom<YieldOpCleanup>($cleanup)}];
 
@@ -1235,13 +1236,12 @@ def hlfir_ElementalAddrOp : hlfir_Op<"elemental_addr", [Terminator, HasParent<"R
 
     /// ElementalOpInterface implementation.
 
-    mlir::Region& getElementalRegion() {return getBody();}
+    mlir::Region& getElementalRegion() { return getBody(); }
     mlir::Value getElementEntity();
     mlir::Region* getElementCleanup();
 
     /// Must this elemental be evaluated in order?
-    /// TODO: add attribute and set it in lowering.
-    bool isOrdered() {return true;}
+    bool isOrdered() { return !getUnordered(); }
   }];
 
   let hasVerifier = 1;

diff  --git a/flang/test/HLFIR/element-addr.fir b/flang/test/HLFIR/element-addr.fir
index c6f2b06b9f6886..73946f8b40e3db 100644
--- a/flang/test/HLFIR/element-addr.fir
+++ b/flang/test/HLFIR/element-addr.fir
@@ -81,3 +81,36 @@ func.func @test_element_addr_cleanup(%x: !fir.box<!fir.array<?x!fir.char<1,?>>>,
 // CHECK:               fir.freemem %[[VAL_11]] : !fir.heap<!fir.array<?xi32>>
 // CHECK:             }
 // CHECK:           }
+
+func.func @unordered() {
+  %c10 = arith.constant 10 : index
+  %c20 = arith.constant 20 : index
+  %0 = fir.shape %c10, %c20 : (index, index) -> !fir.shape<2>
+  hlfir.region_assign {
+    %addr = fir.undefined !fir.ref<!fir.array<10x20xf32>>
+    hlfir.yield %addr : !fir.ref<!fir.array<10x20xf32>>
+  } to {
+    hlfir.elemental_addr %0 unordered : !fir.shape<2> {
+    ^bb0(%i: index, %j: index):
+      %addr = fir.undefined !fir.ref<f32>
+      hlfir.yield %addr : !fir.ref<f32>
+    }
+  }
+  return
+}
+// CHECK-LABEL:   func.func @unordered() {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : index
+// CHECK:           %[[VAL_1:.*]] = arith.constant 20 : index
+// CHECK:           %[[VAL_2:.*]] = fir.shape %[[VAL_0]], %[[VAL_1]] : (index, index) -> !fir.shape<2>
+// CHECK:           hlfir.region_assign {
+// CHECK:             %[[VAL_3:.*]] = fir.undefined !fir.ref<!fir.array<10x20xf32>>
+// CHECK:             hlfir.yield %[[VAL_3]] : !fir.ref<!fir.array<10x20xf32>>
+// CHECK:           } to {
+// CHECK:             hlfir.elemental_addr %[[VAL_2]] unordered : !fir.shape<2> {
+// CHECK:             ^bb0(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: index):
+// CHECK:               %[[VAL_6:.*]] = fir.undefined !fir.ref<f32>
+// CHECK:               hlfir.yield %[[VAL_6]] : !fir.ref<f32>
+// CHECK:             }
+// CHECK:           }
+// CHECK:           return
+// CHECK:         }

diff  --git a/flang/test/HLFIR/elemental.fir b/flang/test/HLFIR/elemental.fir
index f87e45d0e9fce0..d4cef6705b1768 100644
--- a/flang/test/HLFIR/elemental.fir
+++ b/flang/test/HLFIR/elemental.fir
@@ -76,3 +76,26 @@ func.func @parametrized_derived_transpose(%x: !fir.box<!fir.array<?x?x!pdt>>, %n
 // CHECK:    %[[VAL_9:.*]] = hlfir.as_expr %[[VAL_8]] : (!fir.box<!fir.type<pdt(param:i32){field:f32}>>) -> !hlfir.expr<!fir.type<pdt(param:i32){field:f32}>>
 // CHECK:    hlfir.yield_element %[[VAL_9]] : !hlfir.expr<!fir.type<pdt(param:i32){field:f32}>>
 // CHECK:  }
+
+func.func @unordered() {
+  %c10 = arith.constant 10 : index
+  %c20 = arith.constant 20 : index
+  %0 = fir.shape %c10, %c20 : (index, index) -> !fir.shape<2>
+  %3 = hlfir.elemental %0 unordered : (!fir.shape<2>) -> !hlfir.expr<10x20xi32> {
+  ^bb0(%i: index, %j: index):
+    %c0 = arith.constant 0 : i32
+    hlfir.yield_element %c0 : i32
+  }
+  return
+}
+// CHECK-LABEL:   func.func @unordered() {
+// CHECK:           %[[VAL_0:.*]] = arith.constant 10 : index
+// CHECK:           %[[VAL_1:.*]] = arith.constant 20 : index
+// CHECK:           %[[VAL_2:.*]] = fir.shape %[[VAL_0]], %[[VAL_1]] : (index, index) -> !fir.shape<2>
+// CHECK:           %[[VAL_3:.*]] = hlfir.elemental %[[VAL_2]] unordered : (!fir.shape<2>) -> !hlfir.expr<10x20xi32> {
+// CHECK:           ^bb0(%[[VAL_4:.*]]: index, %[[VAL_5:.*]]: index):
+// CHECK:             %[[VAL_6:.*]] = arith.constant 0 : i32
+// CHECK:             hlfir.yield_element %[[VAL_6]] : i32
+// CHECK:           }
+// CHECK:           return
+// CHECK:         }


        


More information about the flang-commits mailing list