mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[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.
This commit is contained in:
committed by
GitHub
parent
7b12a08f5e
commit
bf3b704c60
@@ -80,8 +80,7 @@ def AnyRefOfConstantSizeAggregateType : TypeConstraint<
|
||||
// Memory SSA operations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
|
||||
MemoryEffects<[MemAlloc<AutomaticAllocationScopeResource>]>]> {
|
||||
def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments]> {
|
||||
let summary = "allocate storage for a temporary on the stack given a type";
|
||||
let description = [{
|
||||
This primitive operation is used to allocate an object on the stack. A
|
||||
@@ -162,7 +161,9 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
|
||||
Variadic<AnyIntegerType>:$shape
|
||||
);
|
||||
|
||||
let results = (outs fir_ReferenceType);
|
||||
let results =
|
||||
(outs Res<fir_ReferenceType,
|
||||
"", [MemAlloc<AutomaticAllocationScopeResource>]>:$res);
|
||||
|
||||
let hasCustomAssemblyFormat = 1;
|
||||
let hasVerifier = 1;
|
||||
@@ -212,8 +213,7 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments,
|
||||
}];
|
||||
}
|
||||
|
||||
def fir_AllocMemOp : fir_Op<"allocmem",
|
||||
[MemoryEffects<[MemAlloc<DefaultResource>]>, AttrSizedOperandSegments]> {
|
||||
def fir_AllocMemOp : fir_Op<"allocmem", [AttrSizedOperandSegments]> {
|
||||
let summary = "allocate storage on the heap for an object of a given type";
|
||||
|
||||
let description = [{
|
||||
@@ -235,7 +235,7 @@ def fir_AllocMemOp : fir_Op<"allocmem",
|
||||
Variadic<AnyIntegerType>:$typeparams,
|
||||
Variadic<AnyIntegerType>:$shape
|
||||
);
|
||||
let results = (outs fir_HeapType);
|
||||
let results = (outs Res<fir_HeapType, "", [MemAlloc<DefaultResource>]>:$res);
|
||||
|
||||
let hasCustomAssemblyFormat = 1;
|
||||
let hasVerifier = 1;
|
||||
|
||||
@@ -27,6 +27,26 @@ using namespace mlir;
|
||||
|
||||
#define DEBUG_TYPE "fir-alias-analysis"
|
||||
|
||||
// Inspect for value-scoped Allocate effects and determine whether
|
||||
// 'candidate' is a new allocation. Returns SourceKind::Allocate if a
|
||||
// MemAlloc effect is attached
|
||||
static fir::AliasAnalysis::SourceKind
|
||||
classifyAllocateFromEffects(mlir::Operation *op, mlir::Value candidate) {
|
||||
if (!op)
|
||||
return fir::AliasAnalysis::SourceKind::Unknown;
|
||||
auto interface = llvm::dyn_cast<mlir::MemoryEffectOpInterface>(op);
|
||||
if (!interface)
|
||||
return fir::AliasAnalysis::SourceKind::Unknown;
|
||||
llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4> effects;
|
||||
interface.getEffects(effects);
|
||||
for (mlir::MemoryEffects::EffectInstance &e : effects) {
|
||||
if (mlir::isa<mlir::MemoryEffects::Allocate>(e.getEffect()) &&
|
||||
e.getValue() && e.getValue() == candidate)
|
||||
return fir::AliasAnalysis::SourceKind::Allocate;
|
||||
}
|
||||
return fir::AliasAnalysis::SourceKind::Unknown;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// AliasAnalysis: alias
|
||||
//===----------------------------------------------------------------------===//
|
||||
@@ -535,6 +555,11 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
|
||||
mlir::Operation *instantiationPoint{nullptr};
|
||||
while (defOp && !breakFromLoop) {
|
||||
ty = defOp->getResultTypes()[0];
|
||||
// Value-scoped allocation detection via effects.
|
||||
if (classifyAllocateFromEffects(defOp, v) == SourceKind::Allocate) {
|
||||
type = SourceKind::Allocate;
|
||||
break;
|
||||
}
|
||||
llvm::TypeSwitch<Operation *>(defOp)
|
||||
.Case<hlfir::AsExprOp>([&](auto op) {
|
||||
v = op.getVar();
|
||||
@@ -554,11 +579,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
|
||||
defOp = v.getDefiningOp();
|
||||
}
|
||||
})
|
||||
.Case<fir::AllocaOp, fir::AllocMemOp>([&](auto op) {
|
||||
// Unique memory allocation.
|
||||
type = SourceKind::Allocate;
|
||||
breakFromLoop = true;
|
||||
})
|
||||
.Case<fir::ConvertOp>([&](auto op) {
|
||||
// Skip ConvertOp's and track further through the operand.
|
||||
v = op->getOperand(0);
|
||||
@@ -628,16 +648,23 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v,
|
||||
type = SourceKind::Global;
|
||||
} else {
|
||||
auto def = llvm::cast<mlir::Value>(boxSrc.origin.u);
|
||||
// TODO: Add support to fir.allocmem
|
||||
if (auto allocOp = def.template getDefiningOp<fir::AllocaOp>()) {
|
||||
v = def;
|
||||
defOp = v.getDefiningOp();
|
||||
type = SourceKind::Allocate;
|
||||
} else if (isDummyArgument(def)) {
|
||||
defOp = nullptr;
|
||||
v = def;
|
||||
} else {
|
||||
type = SourceKind::Indirect;
|
||||
bool classified = false;
|
||||
if (auto defDefOp = def.getDefiningOp()) {
|
||||
if (classifyAllocateFromEffects(defDefOp, def) ==
|
||||
SourceKind::Allocate) {
|
||||
v = def;
|
||||
defOp = defDefOp;
|
||||
type = SourceKind::Allocate;
|
||||
classified = true;
|
||||
}
|
||||
}
|
||||
if (!classified) {
|
||||
if (isDummyArgument(def)) {
|
||||
defOp = nullptr;
|
||||
v = def;
|
||||
} else {
|
||||
type = SourceKind::Indirect;
|
||||
}
|
||||
}
|
||||
}
|
||||
breakFromLoop = true;
|
||||
|
||||
@@ -15,5 +15,7 @@
|
||||
|
||||
func.func @_QPfoo() {
|
||||
%1 = fir.alloca i32
|
||||
%0 = arith.constant 0 : i32
|
||||
fir.store %0 to %1 : !fir.ref<i32>
|
||||
return
|
||||
}
|
||||
|
||||
@@ -372,8 +372,17 @@ func.func @alloca_unlimited_polymorphic_box() {
|
||||
%1 = fir.alloca !fir.class<!fir.array<?xnone>>
|
||||
%2 = fir.alloca !fir.box<none>
|
||||
%3 = fir.alloca !fir.box<!fir.array<?xnone>>
|
||||
// Add real uses so allocas are not trivially dead.
|
||||
fir.call @__use_class_none(%0) : (!fir.ref<!fir.class<none>>) -> ()
|
||||
fir.call @__use_class_array(%1) : (!fir.ref<!fir.class<!fir.array<?xnone>>>) -> ()
|
||||
fir.call @__use_box_none(%2) : (!fir.ref<!fir.box<none>>) -> ()
|
||||
fir.call @__use_box_array(%3) : (!fir.ref<!fir.box<!fir.array<?xnone>>>) -> ()
|
||||
return
|
||||
}
|
||||
func.func private @__use_class_none(!fir.ref<!fir.class<none>>) -> ()
|
||||
func.func private @__use_class_array(!fir.ref<!fir.class<!fir.array<?xnone>>>) -> ()
|
||||
func.func private @__use_box_none(!fir.ref<!fir.box<none>>) -> ()
|
||||
func.func private @__use_box_array(!fir.ref<!fir.box<!fir.array<?xnone>>>) -> ()
|
||||
// Note: allocmem of fir.box are not possible (fir::HeapType::verify does not
|
||||
// accept box types), so there is no equivalent of
|
||||
// alloca_unlimited_polymorphic_box for allocmem.
|
||||
|
||||
@@ -28,9 +28,11 @@ func.func @_QQmain() attributes {fir.bindc_name = "reduce"} {
|
||||
omp.parallel reduction(byref @test_reduction %4 -> %arg0 : !fir.ref<!fir.box<i32>>) {
|
||||
omp.terminator
|
||||
}
|
||||
func.call @__use_box_i32(%4) : (!fir.ref<!fir.box<i32>>) -> ()
|
||||
return
|
||||
}
|
||||
|
||||
func.func private @__use_box_i32(!fir.ref<!fir.box<i32>>) -> ()
|
||||
// basically we are testing that there isn't a crash
|
||||
// CHECK-LABEL: define void @_QQmain
|
||||
// CHECK-NEXT: alloca { ptr, i64, i32, i8, i8, i8, i8 }, i64 1, align 8
|
||||
|
||||
@@ -95,14 +95,14 @@ func.func @_QTt1P.f2.offset(%0 : i32, %1 : i32) -> i32 {
|
||||
// end program p
|
||||
|
||||
func.func private @bar(!fir.ref<!fir.char<1,?>>)
|
||||
func.func private @__use_t1(!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> ()
|
||||
|
||||
// CHECK-LABEL: define void @_QPfoo(i32 %0, i32 %1)
|
||||
func.func @_QPfoo(%arg0 : i32, %arg1 : i32) {
|
||||
// CHECK: %[[size:.*]] = call i64 @_QTt1P.mem.size(i32 %0, i32 %1)
|
||||
// CHECK: %[[alloc:.*]] = alloca i8, i64 %[[size]]
|
||||
%0 = fir.alloca !fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>(%arg0, %arg1 : i32, i32)
|
||||
//%2 = fir.coordinate_of %0, f2 : (!fir.ref<!fir.type<_QTt1>>) -> !fir.ref<!fir.char<1,?>>
|
||||
%2 = fir.zero_bits !fir.ref<!fir.char<1,?>>
|
||||
fir.call @bar(%2) : (!fir.ref<!fir.char<1,?>>) -> ()
|
||||
// Keep alloca live without creating an unsupported coordinate_of on dynamic-sized field.
|
||||
func.call @__use_t1(%0) : (!fir.ref<!fir.type<_QTt1(p1:i32,p2:i32){f1:!fir.char<1,?>,f2:!fir.char<1,?>}>>) -> ()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ func.func private @_test_inline_copy_in(%arg0: !fir.box<!fir.array<?x?x?xf64>> {
|
||||
// CHECK: %[[VAL_22:.*]] = fir.box_addr %[[VAL_21:.*]]#0 : (!fir.box<!fir.array<?xf64>>) -> !fir.ref<!fir.array<?xf64>>
|
||||
// CHECK: %[[VAL_23:.*]]:3 = hlfir.associate %[[VAL_5:.*]] {adapt.valuebyref} : (i32) -> (!fir.ref<i32>, !fir.ref<i32>, i1)
|
||||
// CHECK: fir.call @_QFPsb(%[[VAL_22:.*]], %[[VAL_23:.*]]#0) fastmath<contract> : (!fir.ref<!fir.array<?xf64>>, !fir.ref<i32>) -> ()
|
||||
// CHECK: hlfir.copy_out %16, %15#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> ()
|
||||
// CHECK: hlfir.copy_out %{{.*}}, %[[VAL_21:.*]]#1 : (!fir.ref<!fir.box<!fir.array<?xf64>>>, i1) -> ()
|
||||
// CHECK: hlfir.end_associate %[[VAL_23:.*]]#1, %[[VAL_23:.*]]#2 : !fir.ref<i32>, i1
|
||||
// CHECK: return
|
||||
// CHECK: }
|
||||
|
||||
@@ -153,7 +153,6 @@ subroutine dynamic_shape_lower(cptr, fpr, shape, lower)
|
||||
! CHECK: %[[VAL_2:.*]] = fir.shape %[[C_0]], %[[C_0]] : (index, index) -> !fir.shape<2>
|
||||
! 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>>>
|
||||
! CHECK: fir.store %[[VAL_3]] to %[[VAL_0:.*]] : !fir.ref<!fir.box<!fir.ptr<!fir.array<?x?xf32>>>>
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFdynamic_shape_lowerEn"}
|
||||
! CHECK: %[[VAL_5:.*]] = fir.coordinate_of %[[ARG_0:.*]], __address : (!fir.ref<!fir.type<_QM__fortran_builtinsT__builtin_c_ptr{__address:i64}>>) -> !fir.ref<i64>
|
||||
! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_5]] : !fir.ref<i64>
|
||||
! CHECK: %[[VAL_7:.*]] = fir.convert %[[VAL_6]] : (i64) -> !fir.ptr<!fir.array<?x?xf32>>
|
||||
|
||||
@@ -32,11 +32,9 @@ end subroutine
|
||||
|
||||
! CHECK-LABEL: @_QPss
|
||||
subroutine ss(count)
|
||||
! CHECK: %[[V_0:[0-9]+]] = fir.alloca !fir.box<!fir.heap<i64>> {bindc_name = "count_max", uniq_name = "_QFssEcount_max"}
|
||||
! CHECK: %[[V_1:[0-9]+]] = fir.alloca !fir.heap<i64> {uniq_name = "_QFssEcount_max.addr"}
|
||||
! CHECK: %[[V_2:[0-9]+]] = fir.zero_bits !fir.heap<i64>
|
||||
! CHECK: fir.store %[[V_2]] to %[[V_1]] : !fir.ref<!fir.heap<i64>>
|
||||
! CHECK: %[[V_3:[0-9]+]] = fir.alloca !fir.box<!fir.ptr<i64>> {bindc_name = "count_rate", uniq_name = "_QFssEcount_rate"}
|
||||
! CHECK: %[[V_4:[0-9]+]] = fir.alloca !fir.ptr<i64> {uniq_name = "_QFssEcount_rate.addr"}
|
||||
! CHECK: %[[V_5:[0-9]+]] = fir.zero_bits !fir.ptr<i64>
|
||||
! CHECK: fir.store %[[V_5]] to %[[V_4]] : !fir.ref<!fir.ptr<i64>>
|
||||
|
||||
@@ -56,7 +56,7 @@ subroutine foodim1()
|
||||
! CHECK-DAG: fir.load %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
|
||||
deallocate(x)
|
||||
! CHECK: %[[xAddr1:.*]] = fir.load %1 : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: %[[xAddr1:.*]] = fir.load %{{.*}} : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: fir.freemem %[[xAddr1]]
|
||||
! CHECK: %[[nullAddr1:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
|
||||
! CHECK: fir.store %[[nullAddr1]] to %[[xAddrVar]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
@@ -67,10 +67,6 @@ subroutine foodim2()
|
||||
! Test lowering of local allocatable specification
|
||||
real, allocatable :: x(:, :)
|
||||
! CHECK-DAG: fir.alloca !fir.heap<!fir.array<?x?xf32>> {{{.*}}uniq_name = "_QFfoodim2Ex.addr"}
|
||||
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb0"}
|
||||
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext0"}
|
||||
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.lb1"}
|
||||
! CHECK-DAG: fir.alloca index {{{.*}}uniq_name = "_QFfoodim2Ex.ext1"}
|
||||
end subroutine
|
||||
|
||||
! test lowering of character allocatables. Focus is placed on the length handling
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
subroutine scalar_cst_len()
|
||||
character(10) :: c
|
||||
! CHECK: fir.alloca !fir.char<1,10> {{{.*}}uniq_name = "_QFscalar_cst_lenEc"}
|
||||
print *, c
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPscalar_dyn_len
|
||||
@@ -19,12 +20,14 @@ subroutine scalar_dyn_len(l)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i32
|
||||
! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i32
|
||||
! CHECK: fir.alloca !fir.char<1,?>(%[[l]] : i32) {{{.*}}uniq_name = "_QFscalar_dyn_lenEc"}
|
||||
print *, c
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPcst_array_cst_len
|
||||
subroutine cst_array_cst_len()
|
||||
character(10) :: c(20)
|
||||
! CHECK: fir.alloca !fir.array<20x!fir.char<1,10>> {{{.*}}uniq_name = "_QFcst_array_cst_lenEc"}
|
||||
print *, c(1)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPcst_array_dyn_len
|
||||
@@ -36,6 +39,7 @@ subroutine cst_array_dyn_len(l)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i32
|
||||
! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i32
|
||||
! CHECK: fir.alloca !fir.array<10x!fir.char<1,?>>(%[[l]] : i32) {{{.*}}uniq_name = "_QFcst_array_dyn_lenEc"}
|
||||
print *, c(1)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPdyn_array_cst_len
|
||||
@@ -48,6 +52,7 @@ subroutine dyn_array_cst_len(n)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index
|
||||
! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index
|
||||
! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_lenEc"}
|
||||
print *, c(1)
|
||||
end subroutine
|
||||
|
||||
! CHECK: func @_QPdyn_array_dyn_len
|
||||
@@ -63,12 +68,14 @@ subroutine dyn_array_dyn_len(l, n)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[ni]], %c0{{.*}} : index
|
||||
! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[ni]], %c0{{.*}} : index
|
||||
! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i32), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_lenEc"}
|
||||
print *, c(1)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPcst_array_cst_len_lb
|
||||
subroutine cst_array_cst_len_lb()
|
||||
character(10) :: c(11:30)
|
||||
! CHECK: fir.alloca !fir.array<20x!fir.char<1,10>> {{{.*}}uniq_name = "_QFcst_array_cst_len_lbEc"}
|
||||
print *, c(11)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPcst_array_dyn_len_lb
|
||||
@@ -80,6 +87,7 @@ subroutine cst_array_dyn_len_lb(l)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[lexpr]], %c0{{.*}} : i64
|
||||
! CHECK: %[[l:.*]] = arith.select %[[is_positive]], %[[lexpr]], %c0{{.*}} : i64
|
||||
! CHECK: fir.alloca !fir.array<10x!fir.char<1,?>>(%[[l]] : i64) {{{.*}}uniq_name = "_QFcst_array_dyn_len_lbEc"}
|
||||
print *, c(11)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPdyn_array_cst_len_lb
|
||||
@@ -94,6 +102,7 @@ subroutine dyn_array_cst_len_lb(n)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index
|
||||
! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index
|
||||
! CHECK: fir.alloca !fir.array<?x!fir.char<1,10>>, %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_cst_len_lbEc"}
|
||||
print *, c(11)
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QPdyn_array_dyn_len_lb
|
||||
@@ -111,6 +120,7 @@ subroutine dyn_array_dyn_len_lb(l, n)
|
||||
! CHECK: %[[is_positive:.*]] = arith.cmpi sgt, %[[raw_extent]], %c0{{.*}} : index
|
||||
! CHECK: %[[extent:.*]] = arith.select %[[is_positive]], %[[raw_extent]], %c0{{.*}} : index
|
||||
! CHECK: fir.alloca !fir.array<?x!fir.char<1,?>>(%[[l]] : i64), %[[extent]] {{{.*}}uniq_name = "_QFdyn_array_dyn_len_lbEc"}
|
||||
print *, c(11)
|
||||
end subroutine
|
||||
|
||||
! Test that the length of assumed length parameter is correctly deduced in lowering.
|
||||
@@ -129,4 +139,5 @@ end
|
||||
subroutine scalar_cst_neg_len()
|
||||
character(-1) :: c
|
||||
! CHECK: fir.alloca !fir.char<1,0> {{{.*}}uniq_name = "_QFscalar_cst_neg_lenEc"}
|
||||
print *, c
|
||||
end subroutine
|
||||
|
||||
@@ -35,6 +35,8 @@ subroutine local_derived()
|
||||
! CHECK-DAG: fir.alloca !fir.type<_QMdTr{x:f32}>
|
||||
type(r) :: some_r
|
||||
type(c2) :: some_c2
|
||||
print *, some_c2%ch_array(1,1)
|
||||
print *, some_r%x
|
||||
end subroutine
|
||||
|
||||
! CHECK-LABEL: func @_QMdPsaved_derived(
|
||||
|
||||
@@ -235,6 +235,7 @@ end subroutine
|
||||
subroutine unstructured_do_concurrent
|
||||
logical :: success
|
||||
do concurrent (i=1:10) local(success)
|
||||
success = .false.
|
||||
error stop "fail"
|
||||
enddo
|
||||
end
|
||||
|
||||
@@ -318,7 +318,6 @@ end subroutine s2_3
|
||||
! CHECK-LABEL: func @_QPs2_3(
|
||||
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.type<_QMarray_of_pointer_testTt{ip:!fir.box<!fir.ptr<i32>>}>>> {fir.bindc_name = "x"}) {
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
|
||||
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {bindc_name = "y", fir.target, uniq_name = "_QFs2_3Ey"}
|
||||
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.heap<!fir.array<?xi32>> {uniq_name = "_QFs2_3Ey.addr"}
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFs2_3Ey.lb0"}
|
||||
! CHECK: %[[VAL_5:.*]] = fir.alloca index {uniq_name = "_QFs2_3Ey.ext0"}
|
||||
|
||||
@@ -13,20 +13,19 @@ end subroutine forall_with_allocatable
|
||||
! CHECK-LABEL: func @_QPforall_with_allocatable(
|
||||
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
|
||||
! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {adapt.valuebyref, bindc_name = "i"}
|
||||
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xf32>>> {bindc_name = "arr", uniq_name = "_QFforall_with_allocatableEarr"}
|
||||
! CHECK: %[[VAL_3:.*]] = fir.alloca !fir.heap<!fir.array<?xf32>> {uniq_name = "_QFforall_with_allocatableEarr.addr"}
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.lb0"}
|
||||
! CHECK: %[[VAL_5:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.ext0"}
|
||||
! CHECK: %[[VAL_6:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
|
||||
! CHECK: fir.store %[[VAL_6]] to %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: %[[VAL_2:.*]] = fir.alloca !fir.heap<!fir.array<?xf32>> {uniq_name = "_QFforall_with_allocatableEarr.addr"}
|
||||
! CHECK: %[[VAL_3:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.lb0"}
|
||||
! CHECK: %[[VAL_4:.*]] = fir.alloca index {uniq_name = "_QFforall_with_allocatableEarr.ext0"}
|
||||
! CHECK: %[[VAL_5:.*]] = fir.zero_bits !fir.heap<!fir.array<?xf32>>
|
||||
! CHECK: fir.store %[[VAL_5]] to %[[VAL_2]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: %[[VAL_7:.*]] = arith.constant 5 : i32
|
||||
! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> index
|
||||
! CHECK: %[[VAL_9:.*]] = arith.constant 15 : i32
|
||||
! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
|
||||
! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index
|
||||
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_4]] : !fir.ref<index>
|
||||
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_5]] : !fir.ref<index>
|
||||
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: %[[VAL_12:.*]] = fir.load %[[VAL_3]] : !fir.ref<index>
|
||||
! CHECK: %[[VAL_13:.*]] = fir.load %[[VAL_4]] : !fir.ref<index>
|
||||
! CHECK: %[[VAL_14:.*]] = fir.load %[[VAL_2]] : !fir.ref<!fir.heap<!fir.array<?xf32>>>
|
||||
! CHECK: %[[VAL_15:.*]] = fir.shape_shift %[[VAL_12]], %[[VAL_13]] : (index, index) -> !fir.shapeshift<1>
|
||||
! CHECK: %[[VAL_16:.*]] = fir.array_load %[[VAL_14]](%[[VAL_15]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shapeshift<1>) -> !fir.array<?xf32>
|
||||
! CHECK: %[[VAL_17:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32>
|
||||
|
||||
@@ -90,7 +90,6 @@ subroutine lis(n)
|
||||
! CHECK-DAG: fir.alloca !fir.array<?x?x?xi32>, %{{.*}}, %{{.*}}, %{{.*}} {bindc_name = "a", fir.target, uniq_name = "_QFlisEa"}
|
||||
! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "r", uniq_name = "_QFlisEr"}
|
||||
! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "s", uniq_name = "_QFlisEs"}
|
||||
! CHECK-DAG: fir.alloca !fir.array<?x?xi32>, %{{.*}}, %{{.*}} {bindc_name = "t", uniq_name = "_QFlisEt"}
|
||||
integer, target :: a(n,n,n) ! operand via p
|
||||
integer :: r(n,n) ! result, unspecified locality
|
||||
integer :: s(n,n) ! shared locality
|
||||
|
||||
@@ -287,7 +287,6 @@ module polymorphic_test
|
||||
! First test is here to have a reference with non polymorphic on both sides.
|
||||
! CHECK-LABEL: func.func @_QMpolymorphic_testPpointer_assign_parent(
|
||||
! CHECK-SAME: %[[ARG0:.*]]: !fir.ref<!fir.type<_QMpolymorphic_testTp2{a:i32,b:i32,c:f32}>> {fir.bindc_name = "p", fir.target}) {
|
||||
! CHECK: %[[TP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {bindc_name = "tp", uniq_name = "_QMpolymorphic_testFpointer_assign_parentEtp"}
|
||||
! CHECK: %[[PTR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {uniq_name = "_QMpolymorphic_testFpointer_assign_parentEtp.addr"}
|
||||
! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
|
||||
! CHECK: fir.store %[[ZERO]] to %[[PTR]] : !fir.ref<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>
|
||||
@@ -302,7 +301,6 @@ module polymorphic_test
|
||||
|
||||
! CHECK-LABEL: func.func @_QMpolymorphic_testPpointer_assign_non_poly(
|
||||
! CHECK-SAME: %arg0: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "p", fir.target}) {
|
||||
! CHECK: %[[TP:.*]] = fir.alloca !fir.box<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>> {bindc_name = "tp", uniq_name = "_QMpolymorphic_testFpointer_assign_non_polyEtp"}
|
||||
! CHECK: %[[PTR:.*]] = fir.alloca !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {uniq_name = "_QMpolymorphic_testFpointer_assign_non_polyEtp.addr"}
|
||||
! CHECK: %[[ZERO:.*]] = fir.zero_bits !fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>
|
||||
! CHECK: fir.store %[[ZERO]] to %[[PTR]] : !fir.ref<!fir.ptr<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>>>
|
||||
@@ -1103,11 +1101,9 @@ module polymorphic_test
|
||||
|
||||
! CHECK-LABEL: func.func @_QMpolymorphic_testPclass_with_entry(
|
||||
! CHECK-SAME: %[[A:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "a"}) {
|
||||
! CHECK: %[[B:.*]] = fir.alloca !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {bindc_name = "b", uniq_name = "_QMpolymorphic_testFclass_with_entryEb"}
|
||||
|
||||
! CHECK-LABEL: func.func @_QMpolymorphic_testPd(
|
||||
! CHECK-SAME: %[[B:.*]]: !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {fir.bindc_name = "b"}) {
|
||||
! CHECK: %[[A:.*]] = fir.alloca !fir.class<!fir.type<_QMpolymorphic_testTp1{a:i32,b:i32}>> {bindc_name = "a", uniq_name = "_QMpolymorphic_testFclass_with_entryEa"}
|
||||
|
||||
subroutine class_array_with_entry(a)
|
||||
class(p1) :: a(:), b(:)
|
||||
|
||||
@@ -129,7 +129,6 @@ integer function test_stmt_character_with_different_length_2(c, n)
|
||||
character(n) :: argc
|
||||
character(*) :: c
|
||||
! CHECK: %[[unboxed:.*]]:2 = fir.unboxchar %[[arg0]] :
|
||||
! CHECK: fir.load %[[arg1]] : !fir.ref<i32>
|
||||
! CHECK: %[[n:.*]] = fir.load %[[arg1]] : !fir.ref<i32>
|
||||
! CHECK: %[[n_is_positive:.*]] = arith.cmpi sgt, %[[n]], %c0{{.*}} : i32
|
||||
! CHECK: %[[len:.*]] = arith.select %[[n_is_positive]], %[[n]], %c0{{.*}} : i32
|
||||
|
||||
@@ -3,13 +3,17 @@
|
||||
// Simplest transformation
|
||||
func.func @simple() {
|
||||
%0 = fir.allocmem !fir.array<42xi32>
|
||||
%c0_s = arith.constant 0 : index
|
||||
%c0_i32_s = arith.constant 0 : i32
|
||||
%ref_s = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
|
||||
%elt_s = fir.coordinate_of %ref_s, %c0_s : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32_s to %elt_s : !fir.ref<i32>
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @simple() {
|
||||
// CHECK-NEXT: fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: func.func @simple()
|
||||
// CHECK: fir.alloca !fir.array<42xi32>
|
||||
// CHECK: return
|
||||
|
||||
// Check fir.must_be_heap allocations are not moved
|
||||
func.func @must_be_heap() {
|
||||
@@ -17,7 +21,7 @@ func.func @must_be_heap() {
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @must_be_heap() {
|
||||
// CHECK-LABEL: func.func @must_be_heap()
|
||||
// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32> {fir.must_be_heap = true}
|
||||
// CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
|
||||
// CHECK-NEXT: return
|
||||
@@ -36,7 +40,7 @@ func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"}) {
|
||||
// CHECK-LABEL: func.func @dfa1(%arg0: !fir.ref<!fir.logical<4>> {fir.bindc_name = "cond"})
|
||||
// CHECK-NEXT: %[[C42:.*]] = arith.constant 42 : index
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<?xi32>, %[[C42]] {uniq_name = "_QFdfa1Earr.alloc"}
|
||||
// CHECK-NEXT: %[[LOGICAL:.*]] = fir.load %arg0 : !fir.ref<!fir.logical<4>>
|
||||
@@ -57,7 +61,7 @@ func.func @dfa2(%arg0: i1) {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @dfa2(%arg0: i1) {
|
||||
// CHECK-LABEL: func.func @dfa2(%arg0: i1)
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.allocmem !fir.array<1xi8>
|
||||
// CHECK-NEXT: scf.if %arg0 {
|
||||
// CHECK-NEXT: fir.freemem %[[MEM]] : !fir.heap<!fir.array<1xi8>>
|
||||
@@ -74,15 +78,16 @@ func.func @dfa3(%arg0: i1) {
|
||||
} else {
|
||||
fir.freemem %a : !fir.heap<!fir.array<1xi8>>
|
||||
}
|
||||
%c0_d3 = arith.constant 0 : index
|
||||
%c0_i8_d3 = arith.constant 0 : i8
|
||||
%ref_d3 = fir.convert %a : (!fir.heap<!fir.array<1xi8>>) -> !fir.ref<!fir.array<1xi8>>
|
||||
%elt_d3 = fir.coordinate_of %ref_d3, %c0_d3 : (!fir.ref<!fir.array<1xi8>>, index) -> !fir.ref<i8>
|
||||
fir.store %c0_i8_d3 to %elt_d3 : !fir.ref<i8>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @dfa3(%arg0: i1) {
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
|
||||
// CHECK-NEXT: fir.if %arg0 {
|
||||
// CHECK-NEXT: } else {
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: func.func @dfa3(%arg0: i1)
|
||||
// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
|
||||
// CHECK: return
|
||||
|
||||
func.func private @dfa3a_foo(!fir.ref<!fir.array<1xi8>>) -> ()
|
||||
func.func private @dfa3a_bar(!fir.ref<!fir.array<1xi8>>) -> ()
|
||||
@@ -101,7 +106,7 @@ func.func @dfa3a(%arg0: i1) {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @dfa3a(%arg0: i1) {
|
||||
// CHECK-LABEL: func.func @dfa3a(%arg0: i1)
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<1xi8>
|
||||
// CHECK-NEXT: %[[HEAP:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<1xi8>>) -> !fir.heap<!fir.array<1xi8>>
|
||||
// CHECK-NEXT: fir.if %arg0 {
|
||||
@@ -123,13 +128,18 @@ func.func @placement1() {
|
||||
// operand is now available
|
||||
%4 = fir.allocmem !fir.array<?xi32>, %3
|
||||
// ...
|
||||
%c0 = arith.constant 0 : index
|
||||
%c0_i32 = arith.constant 0 : i32
|
||||
%ref1 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
|
||||
%elt1 = fir.coordinate_of %ref1, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32 to %elt1 : !fir.ref<i32>
|
||||
fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement1() {
|
||||
// CHECK-LABEL: func.func @placement1()
|
||||
// CHECK-NEXT: %[[ARG:.*]] = arith.constant 3 : index
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[ARG]]
|
||||
// CHECK-NEXT: return
|
||||
// CHECK: return
|
||||
// CHECK-NEXT: }
|
||||
|
||||
// check that if there are no operands, then the alloca is placed early
|
||||
@@ -140,16 +150,21 @@ func.func @placement2() {
|
||||
%3 = arith.addi %1, %2 : index
|
||||
%4 = fir.allocmem !fir.array<42xi32>
|
||||
// ...
|
||||
%c0_p2 = arith.constant 0 : index
|
||||
%c0_i32_p2 = arith.constant 0 : i32
|
||||
%ref_p2 = fir.convert %4 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
|
||||
%elt_p2 = fir.coordinate_of %ref_p2, %c0_p2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32_p2 to %elt_p2 : !fir.ref<i32>
|
||||
fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement2() {
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NEXT: %[[ONE:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[TWO:.*]] = arith.constant 2 : index
|
||||
// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-LABEL: func.func @placement2()
|
||||
// CHECK: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
|
||||
// CHECK: %[[ONE:.*]] = arith.constant 1 : index
|
||||
// CHECK: %[[TWO:.*]] = arith.constant 2 : index
|
||||
// CHECK: %[[SUM:.*]] = arith.addi %[[ONE]], %[[TWO]] : index
|
||||
// CHECK: return
|
||||
// CHECK: }
|
||||
|
||||
// check that stack allocations which must be placed in loops use stacksave
|
||||
func.func @placement3() {
|
||||
@@ -162,12 +177,17 @@ func.func @placement3() {
|
||||
// operand is now available
|
||||
%4 = fir.allocmem !fir.array<?xi32>, %3
|
||||
// ...
|
||||
%c0 = arith.constant 0 : index
|
||||
%c0_i32 = arith.constant 0 : i32
|
||||
%ref2 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
|
||||
%elt2 = fir.coordinate_of %ref2, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32 to %elt2 : !fir.ref<i32>
|
||||
fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
|
||||
fir.result %3, %c1_i32 : index, i32
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement3() {
|
||||
// CHECK-LABEL: func.func @placement3()
|
||||
// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
|
||||
// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
|
||||
@@ -176,7 +196,7 @@ func.func @placement3() {
|
||||
// CHECK-NEXT: %[[SUM:.*]] = arith.addi %[[C1]], %[[C2]] : index
|
||||
// CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[SUM]]
|
||||
// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
|
||||
// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
|
||||
// CHECK-NEXT: fir.result
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: return
|
||||
@@ -194,12 +214,17 @@ func.func @placement4(%arg0 : i1) {
|
||||
// operand is now available
|
||||
%4 = fir.allocmem !fir.array<?xi32>, %3
|
||||
// ...
|
||||
%c0 = arith.constant 0 : index
|
||||
%c0_i32 = arith.constant 0 : i32
|
||||
%ref3 = fir.convert %4 : (!fir.heap<!fir.array<?xi32>>) -> !fir.ref<!fir.array<?xi32>>
|
||||
%elt3 = fir.coordinate_of %ref3, %c0 : (!fir.ref<!fir.array<?xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32 to %elt3 : !fir.ref<i32>
|
||||
fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
|
||||
cf.cond_br %arg0, ^bb1, ^bb2
|
||||
^bb2:
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement4(%arg0: i1) {
|
||||
// CHECK-LABEL: func.func @placement4(%arg0: i1)
|
||||
// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
|
||||
// CHECK-NEXT: %[[C10:.*]] = arith.constant 10 : index
|
||||
@@ -208,7 +233,7 @@ func.func @placement4(%arg0 : i1) {
|
||||
// CHECK-NEXT: %[[C3:.*]] = arith.constant 3 : index
|
||||
// CHECK-NEXT: %[[SP:.*]] = llvm.intr.stacksave : !llvm.ptr
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<?xi32>, %[[C3]]
|
||||
// CHECK-NEXT: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
|
||||
// CHECK: llvm.intr.stackrestore %[[SP]] : !llvm.ptr
|
||||
// CHECK-NEXT: cf.cond_br %arg0, ^bb1, ^bb2
|
||||
// CHECK-NEXT: ^bb2:
|
||||
// CHECK-NEXT: return
|
||||
@@ -230,7 +255,7 @@ func.func @placement5() {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement5() {
|
||||
// CHECK-LABEL: func.func @placement5()
|
||||
// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
|
||||
// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
|
||||
@@ -268,7 +293,7 @@ func.func @placement6(%arg0: i1) {
|
||||
fir.freemem %4 : !fir.heap<!fir.array<?xi32>>
|
||||
cf.br ^bb1
|
||||
}
|
||||
// CHECK: func.func @placement6(%arg0: i1) {
|
||||
// CHECK-LABEL: func.func @placement6(%arg0: i1)
|
||||
// CHECK-NEXT: %[[c1:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[c1_i32:.*]] = fir.convert %[[c1]] : (index) -> i32
|
||||
// CHECK-NEXT: %[[c2:.*]] = arith.constant 2 : index
|
||||
@@ -289,6 +314,11 @@ func.func @placement6(%arg0: i1) {
|
||||
// Check multiple returns, where the memory is always freed
|
||||
func.func @returns(%arg0: i1) {
|
||||
%0 = fir.allocmem !fir.array<42xi32>
|
||||
%c0_ret = arith.constant 0 : index
|
||||
%c0_i32_ret = arith.constant 0 : i32
|
||||
%ref_ret = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
|
||||
%elt_ret = fir.coordinate_of %ref_ret, %c0_ret : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32_ret to %elt_ret : !fir.ref<i32>
|
||||
cf.cond_br %arg0, ^bb1, ^bb2
|
||||
^bb1:
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
@@ -297,9 +327,9 @@ func.func @returns(%arg0: i1) {
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @returns(%[[COND:.*]]: i1) {
|
||||
// CHECK-NEXT: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2
|
||||
// CHECK-LABEL: func.func @returns(
|
||||
// CHECK: %[[ALLOC:.*]] = fir.alloca !fir.array<42xi32>
|
||||
// CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
|
||||
// CHECK-NEXT: ^bb1:
|
||||
// CHECK-NEXT: return
|
||||
// CHECK-NEXT: ^bb2:
|
||||
@@ -309,6 +339,11 @@ func.func @returns(%arg0: i1) {
|
||||
// Check multiple returns, where the memory is not freed on one branch
|
||||
func.func @returns2(%arg0: i1) {
|
||||
%0 = fir.allocmem !fir.array<42xi32>
|
||||
%c0_ret2 = arith.constant 0 : index
|
||||
%c0_i32_ret2 = arith.constant 0 : i32
|
||||
%ref_ret2 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
|
||||
%elt_ret2 = fir.coordinate_of %ref_ret2, %c0_ret2 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32_ret2 to %elt_ret2 : !fir.ref<i32>
|
||||
cf.cond_br %arg0, ^bb1, ^bb2
|
||||
^bb1:
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
@@ -316,9 +351,9 @@ func.func @returns2(%arg0: i1) {
|
||||
^bb2:
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @returns2(%[[COND:.*]]: i1) {
|
||||
// CHECK-NEXT: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32>
|
||||
// CHECK-NEXT: cf.cond_br %[[COND]], ^bb1, ^bb2
|
||||
// CHECK-LABEL: func.func @returns2(
|
||||
// CHECK: %[[ALLOC:.*]] = fir.allocmem !fir.array<42xi32>
|
||||
// CHECK: cf.cond_br %{{.*}}, ^bb1, ^bb2
|
||||
// CHECK-NEXT: ^bb1:
|
||||
// CHECK-NEXT: fir.freemem %[[ALLOC]] : !fir.heap<!fir.array<42xi32>>
|
||||
// CHECK-NEXT: return
|
||||
@@ -338,7 +373,7 @@ func.func @omp_placement1() {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @omp_placement1() {
|
||||
// CHECK-LABEL: func.func @omp_placement1()
|
||||
// CHECK-NEXT: %[[MEM:.*]] = fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NEXT: %[[MEM_CONV:.*]] = fir.convert %[[MEM]] : (!fir.ref<!fir.array<42xi32>>) -> !fir.heap<!fir.array<42xi32>>
|
||||
// CHECK-NEXT: omp.sections {
|
||||
@@ -353,19 +388,21 @@ func.func @omp_placement1() {
|
||||
// function terminated by stop statement
|
||||
func.func @stop_terminator() {
|
||||
%0 = fir.allocmem !fir.array<42xi32>
|
||||
%c0 = arith.constant 0 : index
|
||||
%c0_i32_st = arith.constant 0 : i32
|
||||
%ref4 = fir.convert %0 : (!fir.heap<!fir.array<42xi32>>) -> !fir.ref<!fir.array<42xi32>>
|
||||
%elt4 = fir.coordinate_of %ref4, %c0 : (!fir.ref<!fir.array<42xi32>>, index) -> !fir.ref<i32>
|
||||
fir.store %c0_i32_st to %elt4 : !fir.ref<i32>
|
||||
fir.freemem %0 : !fir.heap<!fir.array<42xi32>>
|
||||
%c0_i32 = arith.constant 0 : i32
|
||||
%false = arith.constant false
|
||||
fir.call @_FortranAStopStatement(%c0_i32, %false, %false) : (i32, i1, i1) -> ()
|
||||
fir.unreachable
|
||||
}
|
||||
// CHECK: func.func @stop_terminator() {
|
||||
// CHECK-NEXT: fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NEXT: %[[ZERO:.*]] = arith.constant 0 : i32
|
||||
// CHECK-NEXT: %[[FALSE:.*]] = arith.constant false
|
||||
// CHECK-NEXT: fir.call @_FortranAStopStatement(%[[ZERO]], %[[FALSE]], %[[FALSE]]) : (i32, i1, i1) -> ()
|
||||
// CHECK-NEXT: fir.unreachable
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-LABEL: func.func @stop_terminator()
|
||||
// CHECK: fir.alloca !fir.array<42xi32>
|
||||
// CHECK: fir.call @_FortranAStopStatement(
|
||||
// CHECK: fir.unreachable
|
||||
|
||||
|
||||
// check that stack allocations that use fir.declare which must be placed in loops
|
||||
@@ -387,7 +424,7 @@ func.func @placement_loop_declare() {
|
||||
}
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @placement_loop_declare() {
|
||||
// CHECK-LABEL: func.func @placement_loop_declare()
|
||||
// CHECK-NEXT: %[[C1:.*]] = arith.constant 1 : index
|
||||
// CHECK-NEXT: %[[C1_I32:.*]] = fir.convert %[[C1]] : (index) -> i32
|
||||
// CHECK-NEXT: %[[C2:.*]] = arith.constant 2 : index
|
||||
@@ -415,7 +452,7 @@ func.func @lookthrough() {
|
||||
fir.freemem %4 : !fir.heap<!fir.array<42xi32>>
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @lookthrough() {
|
||||
// CHECK-LABEL: func.func @lookthrough()
|
||||
// CHECK: fir.alloca !fir.array<42xi32>
|
||||
// CHECK-NOT: fir.freemem
|
||||
|
||||
@@ -457,6 +494,6 @@ func.func @finding_freemem_in_block() {
|
||||
^bb3: // pred: ^bb1
|
||||
return
|
||||
}
|
||||
// CHECK: func.func @finding_freemem_in_block() {
|
||||
// CHECK-LABEL: func.func @finding_freemem_in_block()
|
||||
// CHECK: fir.alloca !fir.array<?xi32>
|
||||
// CHECK-NOT: fir.freemem
|
||||
|
||||
Reference in New Issue
Block a user