Skip to content

Commit 898df4b

Browse files
[flang] Skip opt-bufferization when memory effect does not have an associated value (#140781)
Memory effects on the volatile memory resource may not be attached to a particular source, in which case the value of an effect will be null. This caused this test case to crash in the optimized bufferization pass's safety analysis because it assumes it can get the SSA value modified by the memory effect. This is because memory effects on the volatile resource indicate that the operation must not be reordered with respect to other volatile operations, but there is not a material ssa value that can be pointed to. This patch changes the safety checks such that memory effects which do not have associated values are not safe for optimized bufferization.
1 parent 9cac4bf commit 898df4b

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

flang/lib/Optimizer/HLFIR/Transforms/OptimizedBufferization.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -608,6 +608,12 @@ ElementalAssignBufferization::findMatch(hlfir::ElementalOp elemental) {
608608
return std::nullopt;
609609
}
610610

611+
if (effect.getValue() == nullptr) {
612+
LLVM_DEBUG(llvm::dbgs()
613+
<< "side-effect with no value, cannot analyze further\n");
614+
return std::nullopt;
615+
}
616+
611617
// allow if and only if the reads are from the elemental indices, in order
612618
// => each iteration doesn't read values written by other iterations
613619
// don't allow reads from a different value which may alias: fir alias
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// RUN: fir-opt --pass-pipeline="builtin.module(func.func(opt-bufferization))" %s | FileCheck %s
2+
3+
// Ensure optimized bufferization preserves the semantics of volatile arrays
4+
func.func @minimal_volatile_test() {
5+
%c1 = arith.constant 1 : index
6+
%c200 = arith.constant 200 : index
7+
8+
// Create a volatile array
9+
%1 = fir.address_of(@_QMtestEarray) : !fir.ref<!fir.array<200xf32>>
10+
%2 = fir.shape %c200 : (index) -> !fir.shape<1>
11+
%3 = fir.volatile_cast %1 : (!fir.ref<!fir.array<200xf32>>) -> !fir.ref<!fir.array<200xf32>, volatile>
12+
%4:2 = hlfir.declare %3(%2) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QMtestEarray"} : (!fir.ref<!fir.array<200xf32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<200xf32>, volatile>, !fir.ref<!fir.array<200xf32>, volatile>)
13+
14+
// Create an elemental operation that negates each element
15+
%5 = hlfir.elemental %2 unordered : (!fir.shape<1>) -> !hlfir.expr<200xf32> {
16+
^bb0(%arg1: index):
17+
%6 = hlfir.designate %4#0 (%arg1) : (!fir.ref<!fir.array<200xf32>, volatile>, index) -> !fir.ref<f32, volatile>
18+
%7 = fir.load %6 : !fir.ref<f32, volatile>
19+
%8 = arith.negf %7 : f32
20+
hlfir.yield_element %8 : f32
21+
}
22+
23+
// Assign the result back to the volatile array
24+
hlfir.assign %5 to %4#0 : !hlfir.expr<200xf32>, !fir.ref<!fir.array<200xf32>, volatile>
25+
hlfir.destroy %5 : !hlfir.expr<200xf32>
26+
27+
return
28+
}
29+
30+
fir.global @_QMtestEarray : !fir.array<200xf32>
31+
32+
// CHECK-LABEL: func.func @minimal_volatile_test() {
33+
// CHECK: %[[VAL_0:.*]] = arith.constant 200 : index
34+
// CHECK: %[[VAL_1:.*]] = fir.address_of(@_QMtestEarray) : !fir.ref<!fir.array<200xf32>>
35+
// CHECK: %[[VAL_2:.*]] = fir.shape %[[VAL_0]] : (index) -> !fir.shape<1>
36+
// CHECK: %[[VAL_3:.*]] = fir.volatile_cast %[[VAL_1]] : (!fir.ref<!fir.array<200xf32>>) -> !fir.ref<!fir.array<200xf32>, volatile>
37+
// CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]](%[[VAL_2]]) {fortran_attrs = #fir.var_attrs<volatile>, uniq_name = "_QMtestEarray"} : (!fir.ref<!fir.array<200xf32>, volatile>, !fir.shape<1>) -> (!fir.ref<!fir.array<200xf32>, volatile>, !fir.ref<!fir.array<200xf32>, volatile>)
38+
// CHECK: %[[VAL_5:.*]] = hlfir.elemental %[[VAL_2]] unordered : (!fir.shape<1>) -> !hlfir.expr<200xf32> {
39+
// CHECK: ^bb0(%[[VAL_6:.*]]: index):
40+
// CHECK: %[[VAL_7:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_6]]) : (!fir.ref<!fir.array<200xf32>, volatile>, index) -> !fir.ref<f32, volatile>
41+
// CHECK: %[[VAL_8:.*]] = fir.load %[[VAL_7]] : !fir.ref<f32, volatile>
42+
// CHECK: %[[VAL_9:.*]] = arith.negf %[[VAL_8]] : f32
43+
// CHECK: hlfir.yield_element %[[VAL_9]] : f32
44+
// CHECK: }
45+
// CHECK: hlfir.assign %[[VAL_5]] to %[[VAL_4]]#0 : !hlfir.expr<200xf32>, !fir.ref<!fir.array<200xf32>, volatile>
46+
// CHECK: hlfir.destroy %[[VAL_5]] : !hlfir.expr<200xf32>
47+
// CHECK: return
48+
// CHECK: }
49+
// CHECK: fir.global @_QMtestEarray : !fir.array<200xf32>

0 commit comments

Comments
 (0)