Skip to content

Commit f84c4cc

Browse files
[flang] Skip optimized bufferization on volatile refs
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 which 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 to indicate that that memory effects on volatile resources are not safe for optimized bufferization.
1 parent 30c9909 commit f84c4cc

File tree

2 files changed

+56
-0
lines changed

2 files changed

+56
-0
lines changed

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

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

611+
// Don't allow any reads to or writes from volatile memory
612+
if (mlir::isa<mlir::MemoryEffects::Read, mlir::MemoryEffects::Write>(
613+
effect.getEffect()) &&
614+
mlir::isa<fir::VolatileMemoryResource>(effect.getResource())) {
615+
return std::nullopt;
616+
}
617+
611618
// allow if and only if the reads are from the elemental indices, in order
612619
// => each iteration doesn't read values written by other iterations
613620
// 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)