Skip to content

Commit ebfdbdb

Browse files
committed
[flang][hlfir] Apply MemAlloc effect to hlfir.elemental explicitly.
Related to llvm#64866. This patch effectively disables CSE for identical hlfir.elemental operations, because it causes hlfir.destroy to be applied twice to the same temporary. Moreover, I think MemAlloc is correct for hlfir.elemental, in general. Reviewed By: tblah Differential Revision: https://reviews.llvm.org/D158565
1 parent b2a9501 commit ebfdbdb

File tree

2 files changed

+75
-1
lines changed

2 files changed

+75
-1
lines changed

flang/include/flang/Optimizer/HLFIR/HLFIROps.td

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -746,7 +746,13 @@ def hlfir_ElementalOpInterface : OpInterface<"ElementalOpInterface"> {
746746
let cppNamespace = "hlfir";
747747
}
748748

749-
def hlfir_ElementalOp : hlfir_Op<"elemental", [RecursiveMemoryEffects, hlfir_ElementalOpInterface, AttrSizedOperandSegments]> {
749+
def hlfir_ElementalOp : hlfir_Op<"elemental",
750+
// The ElementalOp, in general, causes an allocation of a temporary,
751+
// so to guarantee proper behavior of MLIR optimization passes
752+
// we explicitly set MemAlloc effect for it. On top of this,
753+
// the recursive memory effects also apply.
754+
[RecursiveMemoryEffects, MemoryEffects<[MemAlloc]>,
755+
hlfir_ElementalOpInterface, AttrSizedOperandSegments]> {
750756
let summary = "elemental expression";
751757
let description = [{
752758
Represent an elemental expression as a function of the indices.

flang/test/HLFIR/elemental-cse.fir

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Test CSE for hlfir.elemental.
2+
// RUN: fir-opt %s --cse | FileCheck %s
3+
4+
// Check that the CSE does not optimize the hlfir.elemental
5+
// without handling the associated hlfir.destroy's, otherwise,
6+
// the same temp might be freed twice causing double-free error.
7+
func.func @_QFPtest(%arg0: !fir.boxchar<1> {fir.bindc_name = "a"}) {
8+
%c1 = arith.constant 1 : index
9+
%c10 = arith.constant 10 : index
10+
%0:2 = fir.unboxchar %arg0 : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
11+
%1 = fir.convert %0#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1>>>
12+
%2 = fir.shape %c10 : (index) -> !fir.shape<1>
13+
%3:2 = hlfir.declare %1(%2) typeparams %c1 {uniq_name = "_QFFtestEa"} : (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>)
14+
%4 = fir.shape %c10 : (index) -> !fir.shape<1>
15+
%5 = hlfir.elemental %4 typeparams %c1 unordered : (!fir.shape<1>, index) -> !hlfir.expr<10x!fir.char<1>> {
16+
^bb0(%arg1: index):
17+
%14 = fir.convert %arg1 : (index) -> i32
18+
%15 = fir.convert %14 : (i32) -> i64
19+
%16 = hlfir.designate %3#0 (%15) typeparams %c1 : (!fir.ref<!fir.array<10x!fir.char<1>>>, i64, index) -> !fir.ref<!fir.char<1>>
20+
hlfir.yield_element %16 : !fir.ref<!fir.char<1>>
21+
}
22+
%6:3 = hlfir.associate %5(%4) typeparams %c1 {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.char<1>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>, i1)
23+
hlfir.end_associate %6#1, %6#2 : !fir.ref<!fir.array<10x!fir.char<1>>>, i1
24+
hlfir.destroy %5 : !hlfir.expr<10x!fir.char<1>>
25+
%9 = fir.shape %c10 : (index) -> !fir.shape<1>
26+
%10 = hlfir.elemental %9 typeparams %c1 unordered : (!fir.shape<1>, index) -> !hlfir.expr<10x!fir.char<1>> {
27+
^bb0(%arg1: index):
28+
%14 = fir.convert %arg1 : (index) -> i32
29+
%15 = fir.convert %14 : (i32) -> i64
30+
%16 = hlfir.designate %3#0 (%15) typeparams %c1 : (!fir.ref<!fir.array<10x!fir.char<1>>>, i64, index) -> !fir.ref<!fir.char<1>>
31+
hlfir.yield_element %16 : !fir.ref<!fir.char<1>>
32+
}
33+
%11:3 = hlfir.associate %10(%9) typeparams %c1 {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.char<1>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>, i1)
34+
hlfir.end_associate %11#1, %11#2 : !fir.ref<!fir.array<10x!fir.char<1>>>, i1
35+
hlfir.destroy %10 : !hlfir.expr<10x!fir.char<1>>
36+
return
37+
}
38+
39+
// CHECK-LABEL: func.func @_QFPtest(
40+
// CHECK-SAME: %[[VAL_0:.*]]: !fir.boxchar<1> {fir.bindc_name = "a"}) {
41+
// CHECK: %[[VAL_1:.*]] = arith.constant 1 : index
42+
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : index
43+
// CHECK: %[[VAL_3:.*]]:2 = fir.unboxchar %[[VAL_0]] : (!fir.boxchar<1>) -> (!fir.ref<!fir.char<1,?>>, index)
44+
// CHECK: %[[VAL_4:.*]] = fir.convert %[[VAL_3]]#0 : (!fir.ref<!fir.char<1,?>>) -> !fir.ref<!fir.array<10x!fir.char<1>>>
45+
// CHECK: %[[VAL_5:.*]] = fir.shape %[[VAL_2]] : (index) -> !fir.shape<1>
46+
// CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_4]](%[[VAL_5]]) typeparams %[[VAL_1]] {uniq_name = "_QFFtestEa"} : (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>)
47+
// CHECK: %[[VAL_7:.*]] = hlfir.elemental %[[VAL_5]] typeparams %[[VAL_1]] unordered : (!fir.shape<1>, index) -> !hlfir.expr<10x!fir.char<1>> {
48+
// CHECK: ^bb0(%[[VAL_8:.*]]: index):
49+
// CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_8]] : (index) -> i32
50+
// CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> i64
51+
// CHECK: %[[VAL_11:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_10]]) typeparams %[[VAL_1]] : (!fir.ref<!fir.array<10x!fir.char<1>>>, i64, index) -> !fir.ref<!fir.char<1>>
52+
// CHECK: hlfir.yield_element %[[VAL_11]] : !fir.ref<!fir.char<1>>
53+
// CHECK: }
54+
// CHECK: %[[VAL_12:.*]]:3 = hlfir.associate %[[VAL_7]](%[[VAL_5]]) typeparams %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.char<1>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>, i1)
55+
// CHECK: hlfir.end_associate %[[VAL_12]]#1, %[[VAL_12]]#2 : !fir.ref<!fir.array<10x!fir.char<1>>>, i1
56+
// CHECK: hlfir.destroy %[[VAL_7]] : !hlfir.expr<10x!fir.char<1>>
57+
// CHECK: %[[VAL_13:.*]] = hlfir.elemental %[[VAL_5]] typeparams %[[VAL_1]] unordered : (!fir.shape<1>, index) -> !hlfir.expr<10x!fir.char<1>> {
58+
// CHECK: ^bb0(%[[VAL_14:.*]]: index):
59+
// CHECK: %[[VAL_15:.*]] = fir.convert %[[VAL_14]] : (index) -> i32
60+
// CHECK: %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (i32) -> i64
61+
// CHECK: %[[VAL_17:.*]] = hlfir.designate %[[VAL_6]]#0 (%[[VAL_16]]) typeparams %[[VAL_1]] : (!fir.ref<!fir.array<10x!fir.char<1>>>, i64, index) -> !fir.ref<!fir.char<1>>
62+
// CHECK: hlfir.yield_element %[[VAL_17]] : !fir.ref<!fir.char<1>>
63+
// CHECK: }
64+
// CHECK: %[[VAL_18:.*]]:3 = hlfir.associate %[[VAL_13]](%[[VAL_5]]) typeparams %[[VAL_1]] {uniq_name = "adapt.valuebyref"} : (!hlfir.expr<10x!fir.char<1>>, !fir.shape<1>, index) -> (!fir.ref<!fir.array<10x!fir.char<1>>>, !fir.ref<!fir.array<10x!fir.char<1>>>, i1)
65+
// CHECK: hlfir.end_associate %[[VAL_18]]#1, %[[VAL_18]]#2 : !fir.ref<!fir.array<10x!fir.char<1>>>, i1
66+
// CHECK: hlfir.destroy %[[VAL_13]] : !hlfir.expr<10x!fir.char<1>>
67+
// CHECK: return
68+
// CHECK: }

0 commit comments

Comments
 (0)