Skip to content

Commit

Permalink
[flang][hlfir] Parse unordered attribute for elemental operations.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
vzakhari committed Jun 29, 2023
1 parent 5983b8b commit 583168e
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 15 deletions.
30 changes: 15 additions & 15 deletions flang/include/flang/Optimizer/HLFIR/HLFIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
}];
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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)}];

Expand All @@ -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;
Expand Down
33 changes: 33 additions & 0 deletions flang/test/HLFIR/element-addr.fir
Original file line number Diff line number Diff line change
Expand Up @@ -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: }
23 changes: 23 additions & 0 deletions flang/test/HLFIR/elemental.fir
Original file line number Diff line number Diff line change
Expand Up @@ -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: }

0 comments on commit 583168e

Please sign in to comment.