Skip to content

Commit e824b62

Browse files
SusanTangithub-actions[bot]
authored andcommitted
Automerge: [flang][NFC] Characterize allocation based on MemAlloc effect instead of pattern matching (#166806)
Flang alias analysis used to find allocation site by pattern matching allocation ops in mainly FIR dialect. This MR extends the characterization to instead characterize based on whether the result of an op has MemAlloc effect.
2 parents bf914f3 + bf3b704 commit e824b62

19 files changed

+172
-96
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,7 @@ def AnyRefOfConstantSizeAggregateType : TypeConstraint<
8080
// Memory SSA operations
8181
//===----------------------------------------------------------------------===//
8282

83-
def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
84-
MemoryEffects<[MemAlloc<AutomaticAllocationScopeResource>]>]> {
83+
def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments]> {
8584
let summary = "allocate storage for a temporary on the stack given a type";
8685
let description = [{
8786
This primitive operation is used to allocate an object on the stack. A
@@ -162,7 +161,9 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
162161
Variadic<AnyIntegerType>:$shape
163162
);
164163

165-
let results = (outs fir_ReferenceType);
164+
let results =
165+
(outs Res<fir_ReferenceType,
166+
"", [MemAlloc<AutomaticAllocationScopeResource>]>:$res);
166167

167168
let hasCustomAssemblyFormat = 1;
168169
let hasVerifier = 1;
@@ -212,8 +213,7 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
212213
}];
213214
}
214215

215-
def fir_AllocMemOp : fir_Op<"allocmem",
216-
[MemoryEffects<[MemAlloc<DefaultResource>]>, AttrSizedOperandSegments]> {
216+
def fir_AllocMemOp : fir_Op<"allocmem", [AttrSizedOperandSegments]> {
217217
let summary = "allocate storage on the heap for an object of a given type";
218218

219219
let description = [{
@@ -235,7 +235,7 @@ def fir_AllocMemOp : fir_Op<"allocmem",
235235
Variadic<AnyIntegerType>:$typeparams,
236236
Variadic<AnyIntegerType>:$shape
237237
);
238-
let results = (outs fir_HeapType);
238+
let results = (outs Res<fir_HeapType, "", [MemAlloc<DefaultResource>]>:$res);
239239

240240
let hasCustomAssemblyFormat = 1;
241241
let hasVerifier = 1;

flang/lib/Optimizer/Analysis/AliasAnalysis.cpp

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,26 @@ using namespace mlir;
2727

2828
#define DEBUG_TYPE "fir-alias-analysis"
2929

30+
// Inspect for value-scoped Allocate effects and determine whether
31+
// 'candidate' is a new allocation. Returns SourceKind::Allocate if a
32+
// MemAlloc effect is attached
33+
static fir::AliasAnalysis::SourceKind
34+
classifyAllocateFromEffects(mlir::Operation *op, mlir::Value candidate) {
35+
if (!op)
36+
return fir::AliasAnalysis::SourceKind::Unknown;
37+
auto interface = llvm::dyn_cast<mlir::MemoryEffectOpInterface>(op);
38+
if (!interface)
39+
return fir::AliasAnalysis::SourceKind::Unknown;
40+
llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4> effects;
41+
interface.getEffects(effects);
42+
for (mlir::MemoryEffects::EffectInstance &e : effects) {
43+
if (mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect()) &&
44+
e.getValue() && e.getValue() == candidate)
45+
return fir::AliasAnalysis::SourceKind::Allocate;
46+
}
47+
return fir::AliasAnalysis::SourceKind::Unknown;
48+
}
49+
3050
//===----------------------------------------------------------------------===//
3151
// AliasAnalysis: alias
3252
//===----------------------------------------------------------------------===//
@@ -535,6 +555,11 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
535555
mlir::Operation *instantiationPoint{nullptr};
536556
while (defOp && !breakFromLoop) {
537557
ty = defOp->getResultTypes()[0];
558+
// Value-scoped allocation detection via effects.
559+
if (classifyAllocateFromEffects(defOp, v) == SourceKind::Allocate) {
560+
type = SourceKind::Allocate;
561+
break;
562+
}
538563
llvm::TypeSwitch<Operation *>(defOp)
539564
.Case<hlfir::AsExprOp>([&](auto op) {
540565
v = op.getVar();
@@ -554,11 +579,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
554579
defOp = v.getDefiningOp();
555580
}
556581
})
557-
.Case<fir::AllocaOp, fir::AllocMemOp>([&](auto op) {
558-
// Unique memory allocation.
559-
type = SourceKind::Allocate;
560-
breakFromLoop = true;
561-
})
562582
.Case<fir::ConvertOp>([&](auto op) {
563583
// Skip ConvertOp's and track further through the operand.
564584
v = op->getOperand(0);
@@ -628,16 +648,23 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
628648
type = SourceKind::Global;
629649
} else {
630650
auto def = llvm::cast<mlir::Value>(boxSrc.origin.u);
631-
// TODO: Add support to fir.allocmem
632-
if (auto allocOp = def.template getDefiningOp<fir::AllocaOp>()) {
633-
v = def;
634-
defOp = v.getDefiningOp();
635-
type = SourceKind::Allocate;
636-
} else if (isDummyArgument(def)) {
637-
defOp = nullptr;
638-
v = def;
639-
} else {
640-
type = SourceKind::Indirect;
651+
bool classified = false;
652+
if (auto defDefOp = def.getDefiningOp()) {
653+
if (classifyAllocateFromEffects(defDefOp, def) ==
654+
SourceKind::Allocate) {
655+
v = def;
656+
defOp = defDefOp;
657+
type = SourceKind::Allocate;
658+
classified = true;
659+
}
660+
}
661+
if (!classified) {
662+
if (isDummyArgument(def)) {
663+
defOp = nullptr;
664+
v = def;
665+
} else {
666+
type = SourceKind::Indirect;
667+
}
641668
}
642669
}
643670
breakFromLoop = true;

flang/test/Driver/tco-emit-final-mlir.fir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,7 @@
1515

1616
func.func @_QPfoo() {
1717
%1 = fir.alloca i32
18+
%0 = arith.constant 0 : i32
19+
fir.store %0 to %1 : !fir.ref<i32>
1820
return
1921
}

flang/test/Fir/alloc.fir

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,8 +372,17 @@ func.func @alloca_unlimited_polymorphic_box() {
372372
%1 = fir.alloca !fir.class<!fir.array<?xnone>>
373373
%2 = fir.alloca !fir.box<none>
374374
%3 = fir.alloca !fir.box<!fir.array<?xnone>>
375+
// Add real uses so allocas are not trivially dead.
376+
fir.call @__use_class_none(%0) : (!fir.ref<!fir.class<none>>) -> ()
377+
fir.call @__use_class_array(%1) : (!fir.ref<!fir.class<!fir.array<?xnone>>>) -> ()
378+
fir.call @__use_box_none(%2) : (!fir.ref<!fir.box<none>>) -> ()
379+
fir.call @__use_box_array(%3) : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> ()
375380
return
376381
}
382+
func.func private @__use_class_none(!fir.ref<!fir.class<none>>) -> ()
383+
func.func private @__use_class_array(!fir.ref<!fir.class<!fir.array<?xnone>>>) -> ()
384+
func.func private @__use_box_none(!fir.ref<!fir.box<none>>) -> ()
385+
func.func private @__use_box_array(!fir.ref<!fir.box<!fir.array<?xnone>>>) -> ()
377386
// Note: allocmem of fir.box are not possible (fir::HeapType::verify does not
378387
// accept box types), so there is no equivalent of
379388
// alloca_unlimited_polymorphic_box for allocmem.

flang/test/Fir/omp-reduction-embox-codegen.fir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@ func.func @_QQmain() attributes {fir.bindc_name = "reduce"} {
2828
omp.parallel reduction(byref @test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) {
2929
omp.terminator
3030
}
31+
func.call @__use_box_i32(%4) : (!fir.ref<!fir.box<i32>>) -> ()
3132
return
3233
}
3334

35+
func.func private @__use_box_i32(!fir.ref<!fir.box<i32>>) -> ()
3436
// basically we are testing that there isn't a crash
3537
// CHECK-LABEL: define void @_QQmain
3638
// CHECK-NEXT: alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1, align 8

flang/test/Fir/pdt.fir

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,14 @@ func.func @_QTt1P.f2.offset(%0 : i32, %1 : i32) -> i32 {
9595
// end program p
9696

9797
func.func private @bar(!fir.ref<!fir.char<1,?>>)
98+
func.func private @__use_t1(!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> ()
9899

99100
// CHECK-LABEL: define void @_QPfoo(i32 %0, i32 %1)
100101
func.func @_QPfoo(%arg0 : i32, %arg1 : i32) {
101102
// CHECK: %[[size:.*]] = call i64 @_QTt1P.mem.size(i32 %0, i32 %1)
102103
// CHECK: %[[alloc:.*]] = alloca i8, i64 %[[size]]
103104
%0 = fir.alloca !fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>(%arg0, %arg1 : i32, i32)
104-
//%2 = fir.coordinate_of %0, f2 : (!fir.ref<!fir.type<_QTt1>>) -> !fir.ref<!fir.char<1,?>>
105-
%2 = fir.zero_bits !fir.ref<!fir.char<1,?>>
106-
fir.call @bar(%2) : (!fir.ref<!fir.char<1,?>>) -> ()
105+
// Keep alloca live without creating an unsupported coordinate_of on dynamic-sized field.
106+
func.call @__use_t1(%0) : (!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> ()
107107
return
108108
}

flang/test/HLFIR/inline-hlfir-copy-in.fir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func.func private @_test_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> {
7575
// CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21:.*]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
7676
// CHECK: %[[VAL_23:.*]]:3 = hlfir.associate %[[VAL_5:.*]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
7777
// CHECK: fir.call @_QFPsb(%[[VAL_22:.*]], %[[VAL_23:.*]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> ()
78-
// CHECK: hlfir.copy_out %16, %15#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> ()
78+
// CHECK: hlfir.copy_out %{{.*}}, %[[VAL_21:.*]]#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> ()
7979
// CHECK: hlfir.end_associate %[[VAL_23:.*]]#1, %[[VAL_23:.*]]#2 : !fir.ref<i32>, i1
8080
// CHECK: return
8181
// CHECK: }

flang/test/Lower/Intrinsics/c_f_pointer.f90

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,6 @@ subroutine dynamic_shape_lower(cptr, fpr, shape, lower)
153153
! CHECK: %[[VAL_2:.*]] = fir.shape %[[C_0]], %[[C_0]] : (index, index) -> !fir.shape<2>
154154
! CHECK: %[[VAL_3:.*]] = fir.embox %[[VAL_1:.*]](%[[VAL_2]]) : (!fir.ptr<!fir.array<?x?xf32>>, !fir.shape<2>) -> !fir.box<!fir.ptr<!fir.array<?x?xf32>>>
155155
! CHECK: fir.store %[[VAL_3]] to %[[VAL_0:.*]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>
156-
! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFdynamic_shape_lowerEn"}
157156
! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[ARG_0:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64>
158157
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i64>
159158
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> !fir.ptr<!fir.array<?x?xf32>>

flang/test/Lower/Intrinsics/system_clock.f90

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,9 @@ subroutine system_clock_test()
3232

3333
! CHECK-LABEL: @_QPss
3434
subroutine ss(count)
35-
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<i64>> {bindc_name = "count_max", uniq_name = "_QFssEcount_max"}
3635
! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.heap<i64> {uniq_name = "_QFssEcount_max.addr"}
3736
! CHECK: %[[V_2:[0-9]+]] = fir.zero_bits !fir.heap<i64>
3837
! CHECK: fir.store %[[V_2]] to %[[V_1]] : !fir.ref<!fir.heap<i64>>
39-
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.box<!fir.ptr<i64>> {bindc_name = "count_rate", uniq_name = "_QFssEcount_rate"}
4038
! CHECK: %[[V_4:[0-9]+]] = fir.alloca !fir.ptr<i64> {uniq_name = "_QFssEcount_rate.addr"}
4139
! CHECK: %[[V_5:[0-9]+]] = fir.zero_bits !fir.ptr<i64>
4240
! CHECK: fir.store %[[V_5]] to %[[V_4]] : !fir.ref<!fir.ptr<i64>>

flang/test/Lower/allocatables.f90

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ subroutine foodim1()
5656
! CHECK-DAG: fir.load %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
5757

5858
deallocate(x)
59-
! CHECK: %[[xAddr1:.*]] = fir.load %1 : !fir.ref<!fir.heap<!fir.array<?xf32>>>
59+
! CHECK: %[[xAddr1:.*]] = fir.load %{{.*}} : !fir.ref<!fir.heap<!fir.array<?xf32>>>
6060
! CHECK: fir.freemem %[[xAddr1]]
6161
! CHECK: %[[nullAddr1:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
6262
! CHECK: fir.store %[[nullAddr1]] to %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
@@ -67,10 +67,6 @@ subroutine foodim2()
6767
! Test lowering of local allocatable specification
6868
real, allocatable :: x(:, :)
6969
! CHECK-DAG: fir.alloca !fir.heap<!fir.array<?x?xf32>> {{{.*}}uniq_name = "_QFfoodim2Ex.addr"}
70-
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb0"}
71-
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext0"}
72-
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb1"}
73-
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext1"}
7470
end subroutine
7571

7672
! test lowering of character allocatables. Focus is placed on the length handling

0 commit comments

Comments
 (0)