mirror of
https://github.com/intel/llvm.git
synced 2026-01-18 07:57:36 +08:00
[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
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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: }
|
||||
|
||||
@@ -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: }
|
||||
|
||||
Reference in New Issue
Block a user