Skip to content

Commit 4ed30c8

Browse files
committed
[flang] Avoid copyin/copyout if the actual argument is contiguous at runtime
This patch adds contiguity check with the runtime to avoid copyin/copyout in case the actual argument is actually contiguous. Reviewed By: jeanPerier Differential Revision: https://reviews.llvm.org/D133097
1 parent c453e5b commit 4ed30c8

File tree

5 files changed

+222
-47
lines changed

5 files changed

+222
-47
lines changed

flang/lib/Lower/ConvertExpr.cpp

Lines changed: 95 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "flang/Optimizer/Dialect/FIRDialect.h"
4242
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
4343
#include "flang/Optimizer/Support/FatalError.h"
44+
#include "flang/Runtime/support.h"
4445
#include "flang/Semantics/expression.h"
4546
#include "flang/Semantics/symbol.h"
4647
#include "flang/Semantics/tools.h"
@@ -55,6 +56,8 @@
5556

5657
#define DEBUG_TYPE "flang-lower-expr"
5758

59+
using namespace Fortran::runtime;
60+
5861
//===----------------------------------------------------------------------===//
5962
// The composition and structure of Fortran::evaluate::Expr is defined in
6063
// the various header files in include/flang/Evaluate. You are referred
@@ -2836,35 +2839,114 @@ class ScalarExprLowering {
28362839
bool byValue) {
28372840
const bool doCopyOut = !byValue && arg.mayBeModifiedByCall();
28382841
llvm::StringRef tempName = byValue ? ".copy" : ".copyinout";
2839-
if (!restrictCopyAtRuntime) {
2842+
mlir::Location loc = getLoc();
2843+
bool isActualArgBox = fir::isa_box_type(fir::getBase(actualArg).getType());
2844+
mlir::Value isContiguousResult;
2845+
mlir::Type addrType = fir::HeapType::get(
2846+
fir::unwrapPassByRefType(fir::getBase(actualArg).getType()));
2847+
2848+
if (isActualArgBox) {
2849+
// Check at runtime if the argument is contiguous so no copy is needed.
2850+
mlir::func::FuncOp isContiguousFct =
2851+
fir::runtime::getRuntimeFunc<mkRTKey(IsContiguous)>(loc, builder);
2852+
fir::CallOp isContiguous = builder.create<fir::CallOp>(
2853+
loc, isContiguousFct,
2854+
mlir::ValueRange{builder.createConvert(
2855+
loc, isContiguousFct.getFunctionType().getInput(0),
2856+
fir::getBase(actualArg))});
2857+
isContiguousResult = isContiguous.getResult(0);
2858+
}
2859+
2860+
auto doCopyIn = [&]() -> ExtValue {
28402861
ExtValue temp = genArrayTempFromMold(actualArg, tempName);
28412862
if (arg.mayBeReadByCall())
28422863
genArrayCopy(temp, actualArg);
2843-
copyOutPairs.emplace_back(
2844-
CopyOutPair{actualArg, temp, doCopyOut, restrictCopyAtRuntime});
2864+
return temp;
2865+
};
2866+
2867+
auto noCopy = [&]() {
2868+
mlir::Value box = fir::getBase(actualArg);
2869+
mlir::Value boxAddr = builder.create<fir::BoxAddrOp>(loc, addrType, box);
2870+
builder.create<fir::ResultOp>(loc, boxAddr);
2871+
};
2872+
2873+
auto combinedCondition = [&]() {
2874+
if (isActualArgBox) {
2875+
mlir::Value zero =
2876+
builder.createIntegerConstant(loc, builder.getI1Type(), 0);
2877+
mlir::Value notContiguous = builder.create<mlir::arith::CmpIOp>(
2878+
loc, mlir::arith::CmpIPredicate::eq, isContiguousResult, zero);
2879+
if (!restrictCopyAtRuntime) {
2880+
restrictCopyAtRuntime = notContiguous;
2881+
} else {
2882+
mlir::Value cond = builder.create<mlir::arith::AndIOp>(
2883+
loc, *restrictCopyAtRuntime, notContiguous);
2884+
restrictCopyAtRuntime = cond;
2885+
}
2886+
}
2887+
};
2888+
2889+
if (!restrictCopyAtRuntime) {
2890+
if (isActualArgBox) {
2891+
// isContiguousResult = genIsContiguousCall();
2892+
mlir::Value addr =
2893+
builder
2894+
.genIfOp(loc, {addrType}, isContiguousResult,
2895+
/*withElseRegion=*/true)
2896+
.genThen([&]() { noCopy(); })
2897+
.genElse([&] {
2898+
ExtValue temp = doCopyIn();
2899+
builder.create<fir::ResultOp>(loc, fir::getBase(temp));
2900+
})
2901+
.getResults()[0];
2902+
fir::ExtendedValue temp =
2903+
fir::substBase(readIfBoxValue(actualArg), addr);
2904+
combinedCondition();
2905+
copyOutPairs.emplace_back(
2906+
CopyOutPair{actualArg, temp, doCopyOut, restrictCopyAtRuntime});
2907+
return temp;
2908+
}
2909+
2910+
ExtValue temp = doCopyIn();
2911+
copyOutPairs.emplace_back(CopyOutPair{actualArg, temp, doCopyOut, {}});
28452912
return temp;
28462913
}
2914+
28472915
// Otherwise, need to be careful to only copy-in if allowed at runtime.
2848-
mlir::Location loc = getLoc();
2849-
auto addrType = fir::HeapType::get(
2850-
fir::unwrapPassByRefType(fir::getBase(actualArg).getType()));
28512916
mlir::Value addr =
28522917
builder
28532918
.genIfOp(loc, {addrType}, *restrictCopyAtRuntime,
28542919
/*withElseRegion=*/true)
28552920
.genThen([&]() {
2856-
auto temp = genArrayTempFromMold(actualArg, tempName);
2857-
if (arg.mayBeReadByCall())
2858-
genArrayCopy(temp, actualArg);
2859-
builder.create<fir::ResultOp>(loc, fir::getBase(temp));
2921+
if (isActualArgBox) {
2922+
// isContiguousResult = genIsContiguousCall();
2923+
// Avoid copyin if the argument is contiguous at runtime.
2924+
mlir::Value addr1 =
2925+
builder
2926+
.genIfOp(loc, {addrType}, isContiguousResult,
2927+
/*withElseRegion=*/true)
2928+
.genThen([&]() { noCopy(); })
2929+
.genElse([&]() {
2930+
ExtValue temp = doCopyIn();
2931+
builder.create<fir::ResultOp>(loc,
2932+
fir::getBase(temp));
2933+
})
2934+
.getResults()[0];
2935+
builder.create<fir::ResultOp>(loc, addr1);
2936+
} else {
2937+
ExtValue temp = doCopyIn();
2938+
builder.create<fir::ResultOp>(loc, fir::getBase(temp));
2939+
}
28602940
})
28612941
.genElse([&]() {
2862-
auto nullPtr = builder.createNullConstant(loc, addrType);
2942+
mlir::Value nullPtr = builder.createNullConstant(loc, addrType);
28632943
builder.create<fir::ResultOp>(loc, nullPtr);
28642944
})
28652945
.getResults()[0];
2866-
// Associate the temp address with actualArg lengths and extents.
2946+
// Associate the temp address with actualArg lengths and extents if a
2947+
// temporary is generated. Otherwise the same address is associated.
28672948
fir::ExtendedValue temp = fir::substBase(readIfBoxValue(actualArg), addr);
2949+
combinedCondition();
28682950
copyOutPairs.emplace_back(
28692951
CopyOutPair{actualArg, temp, doCopyOut, restrictCopyAtRuntime});
28702952
return temp;
@@ -2880,6 +2962,7 @@ class ScalarExprLowering {
28802962
builder.create<fir::FreeMemOp>(loc, fir::getBase(copyOutPair.temp));
28812963
return;
28822964
}
2965+
28832966
builder.genIfThen(loc, *copyOutPair.restrictCopyAndFreeAtRuntime)
28842967
.genThen([&]() {
28852968
if (copyOutPair.argMayBeModifiedByCall)

flang/test/Lower/call-by-value-attr.f90

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ end subroutine subra
6767
!CHECK: %[[SHAPE_7:.*]] = fir.shape %[[CONST_15_1]] : (index) -> !fir.shape<1>
6868
!CHECK: %[[SLICE:.*]] = fir.slice %[[CONV_5]], %[[CONV_15]], %[[CONV_1]] : (index, index, index) -> !fir.slice<1>
6969
!CHECK: %[[BOX:.*]] = fir.embox %[[ARRAY_B]](%[[SHAPE_7]]) [%[[SLICE]]] : (!fir.ref<!fir.array<15xi32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<11xi32>>
70+
!CHECK: %[[BOX_NONE:.*]] = fir.convert %[[BOX]] : (!fir.box<!fir.array<11xi32>>) -> !fir.box<none>
71+
!CHECK: %[[IS_CONTIGUOUS:.*]] = fir.call @_FortranAIsContiguous(%[[BOX_NONE]]) : (!fir.box<none>) -> i1
72+
!CHECK: %[[ADDR:.*]] = fir.if %[[IS_CONTIGUOUS]] -> (!fir.heap<!fir.array<11xi32>>) {
73+
!CHECK: %[[BOX_ADDR:.*]] = fir.box_addr %[[BOX]] : (!fir.box<!fir.array<11xi32>>) -> !fir.heap<!fir.array<11xi32>>
74+
!CHECKL fir.result %[[BOXADDR]] : !fir.heap<!fir.array<11xi32>>
7075
!CHECK: %[[CONST_0:.*]] = arith.constant 0 : index
7176
!CHECK: %[[DIMS:.*]]:3 = fir.box_dims %[[BOX]], %[[CONST_0]] : (!fir.box<!fir.array<11xi32>>, index) -> (index, index, index)
7277
!CHECK: %[[ARRAY_COPY_2:.*]] = fir.allocmem !fir.array<11xi32>, %[[DIMS]]#1 {uniq_name = ".copy"}
@@ -75,8 +80,9 @@ end subroutine subra
7580
!CHECK: %[[ARRAY_LOAD_8:.*]] = fir.array_load %[[BOX]] : (!fir.box<!fir.array<11xi32>>) -> !fir.array<11xi32>
7681
!CHECK: %[[DO_4:.*]] = fir.do_loop {{.*}} {
7782
!CHECK: }
78-
!CHECK fir.array_merge_store %[[ARRAY_LOAD_7]], %[[DO_4]] to %[[ARRAY_COPY_2]] : !fir.array<11xi32>, !fir.array<11xi32>, !fir.heap<!fir.array<11xi32>>
79-
!CHECK: %[[CONVERT_B:.*]] = fir.convert %[[ARRAY_COPY_2]] : (!fir.heap<!fir.array<11xi32>>) -> !fir.ref<!fir.array<10xi32>>
83+
!CHECK: fir.array_merge_store %[[ARRAY_LOAD_7]], %[[DO_4]] to %[[ARRAY_COPY_2]] : !fir.array<11xi32>, !fir.array<11xi32>, !fir.heap<!fir.array<11xi32>>
84+
!CHECK: fir.result %[[ARRAY_COPY_2]] : !fir.heap<!fir.array<11xi32>>
85+
!CHECK: %[[CONVERT_B:.*]] = fir.convert %[[ADDR]] : (!fir.heap<!fir.array<11xi32>>) -> !fir.ref<!fir.array<10xi32>>
8086
!CHECK: fir.call @_QPsubra(%[[CONVERT_B]])
8187
call subra(b(5:15))
8288
end program call_by_value_attr

flang/test/Lower/call-copy-in-out.f90

Lines changed: 57 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66
! CHECK-SAME: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
77
subroutine test_assumed_shape_to_array(x)
88
real :: x(:)
9+
10+
! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
11+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
12+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
13+
! CHECK: %[[box_addr:.*]] = fir.box_addr %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.heap<!fir.array<?xf32>>
14+
! CHECK: fir.result %[[box_addr]] : !fir.heap<!fir.array<?xf32>>
15+
! CHECK: } else {
916
! Creating temp
1017
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x:.*]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
1118
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1 {uniq_name = ".copyinout"}
@@ -20,23 +27,26 @@ subroutine test_assumed_shape_to_array(x)
2027
! CHECK: fir.result %[[update]] : !fir.array<?xf32>
2128
! CHECK: }
2229
! CHECK: fir.array_merge_store %[[temp_load]], %[[copyin:.*]] to %[[temp]] : !fir.array<?xf32>, !fir.array<?xf32>, !fir.heap<!fir.array<?xf32>>
30+
! CHECK: fir.result %[[temp]] : !fir.heap<!fir.array<?xf32>>
2331

24-
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
32+
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
33+
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
2534
! CHECK: fir.call @_QPbar(%[[cast]]) : (!fir.ref<!fir.array<?xf32>>) -> ()
2635

2736
! Copy-out
28-
2937
! CHECK-DAG: %[[x_load:.*]] = fir.array_load %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.array<?xf32>
38+
! CHECK-DAG: %[[c0:.*]] = arith.constant 0 : index
39+
3040
! CHECK-DAG: %[[shape:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
31-
! CHECK-DAG: %[[temp_load:.*]] = fir.array_load %[[temp]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.array<?xf32>
41+
! CHECK-DAG: %[[temp_load:.*]] = fir.array_load %[[addr]](%[[shape]]) : (!fir.heap<!fir.array<?xf32>>, !fir.shape<1>) -> !fir.array<?xf32>
3242
! CHECK: %[[copyout:.*]] = fir.do_loop %[[i:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[res:.*]] = %[[x_load]]) -> (!fir.array<?xf32>) {
3343
! CHECK: %[[fetch:.*]] = fir.array_fetch %[[temp_load]], %[[i]] : (!fir.array<?xf32>, index) -> f32
3444
! CHECK: %[[update:.*]] = fir.array_update %[[res]], %[[fetch]], %[[i]] : (!fir.array<?xf32>, f32, index) -> !fir.array<?xf32>
3545
! CHECK: fir.result %[[update]] : !fir.array<?xf32>
3646
! CHECK: }
3747
! CHECK: fir.array_merge_store %[[x_load]], %[[copyout:.*]] to %[[x]] : !fir.array<?xf32>, !fir.array<?xf32>, !fir.box<!fir.array<?xf32>>
3848

39-
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
49+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
4050

4151
call bar(x)
4252
end subroutine
@@ -50,19 +60,24 @@ subroutine eval_expr_only_once(x)
5060
real :: x(200)
5161
! CHECK: fir.call @_QPonly_once()
5262
! CHECK: %[[x_section:.*]] = fir.embox %[[x]](%{{.*}}) [%{{.*}}] : (!fir.ref<!fir.array<200xf32>>, !fir.shape<1>, !fir.slice<1>) -> !fir.box<!fir.array<?xf32>>
63+
! CHECK: %[[box_none:.*]] = fir.convert %[[x_section]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
64+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
65+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]] -> (!fir.heap<!fir.array<?xf32>>) {
66+
5367
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>
5468
! CHECK-NOT: fir.call @_QPonly_once()
5569
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[temp]]
5670
! CHECK-NOT: fir.call @_QPonly_once()
5771

58-
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
72+
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<?xf32>>
5973
! CHECK: fir.call @_QPbar(%[[cast]]) : (!fir.ref<!fir.array<?xf32>>) -> ()
6074
call bar(x(1:200:only_once()))
6175

6276
! CHECK-NOT: fir.call @_QPonly_once()
6377
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[x_section]]
6478
! CHECK-NOT: fir.call @_QPonly_once()
65-
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
79+
80+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
6681
end subroutine
6782

6883
! Test no copy-in/copy-out is generated for contiguous assumed shapes.
@@ -104,19 +119,26 @@ subroutine bar_intent_out(x)
104119
real, intent(out) :: x(100)
105120
end subroutine
106121
end interface
122+
! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
123+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
124+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
125+
! CHECK: } else {
107126
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
108127
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
109128
! CHECK-NOT: fir.array_merge_store
110-
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
129+
! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
130+
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
111131
! CHECK: fir.call @_QPbar_intent_out(%[[cast]]) : (!fir.ref<!fir.array<100xf32>>) -> ()
112132
call bar_intent_out(x)
113-
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[x]]
114-
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
133+
134+
! CHECK: fir.if %[[not_contiguous]]
135+
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[x]]
136+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
115137
! CHECK: return
116138
end subroutine
117139

118140
! Test copy-out is skipped for intent(out) arguments.
119-
! CHECK: func @_QPtest_intent_in(
141+
! CHECK-LABEL: func.func @_QPtest_intent_in(
120142
! CHECK: %[[x:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}) {
121143
subroutine test_intent_in(x)
122144
real :: x(:)
@@ -125,14 +147,20 @@ subroutine bar_intent_in(x)
125147
real, intent(in) :: x(100)
126148
end subroutine
127149
end interface
150+
! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
151+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
152+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
153+
! CHECK: } else {
128154
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
129155
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
130156
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[temp]]
131-
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
157+
! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
158+
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
132159
! CHECK: fir.call @_QPbar_intent_in(%[[cast]]) : (!fir.ref<!fir.array<100xf32>>) -> ()
133160
call bar_intent_in(x)
161+
! CHECK: fir.if %[[not_contiguous]]
134162
! CHECK-NOT: fir.array_merge_store
135-
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
163+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
136164
! CHECK: return
137165
end subroutine
138166

@@ -146,14 +174,20 @@ subroutine bar_intent_inout(x)
146174
real, intent(inout) :: x(100)
147175
end subroutine
148176
end interface
177+
! CHECK: %[[box_none:.*]] = fir.convert %[[x]] : (!fir.box<!fir.array<?xf32>>) -> !fir.box<none>
178+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
179+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
180+
! CHECK: } else {
149181
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[x]], %c0{{.*}} : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
150182
! CHECK: %[[temp:.*]] = fir.allocmem !fir.array<?xf32>, %[[dim]]#1
151183
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[temp]]
152-
! CHECK: %[[cast:.*]] = fir.convert %[[temp]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
184+
! CHECK: %[[not_contiguous:.*]] = arith.cmpi eq, %[[is_contiguous]], %false{{.*}} : i1
185+
! CHECK: %[[cast:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?xf32>>) -> !fir.ref<!fir.array<100xf32>>
153186
! CHECK: fir.call @_QPbar_intent_inout(%[[cast]]) : (!fir.ref<!fir.array<100xf32>>) -> ()
154187
call bar_intent_inout(x)
188+
! CHECK: fir.if %[[not_contiguous]]
155189
! CHECK: fir.array_merge_store %{{.*}}, %{{.*}} to %[[x]]
156-
! CHECK: fir.freemem %[[temp]] : !fir.heap<!fir.array<?xf32>>
190+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?xf32>>
157191
! CHECK: return
158192
end subroutine
159193

@@ -162,6 +196,10 @@ subroutine bar_intent_inout(x)
162196
! CHECK-SAME: %[[VAL_0:.*]]: !fir.box<!fir.array<?x!fir.char<1,10>>>{{.*}}) {
163197
subroutine test_char(x)
164198
! CHECK: %[[VAL_1:.*]] = arith.constant 10 : index
199+
! CHECK: %[[box_none:.*]] = fir.convert %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.box<none>
200+
! CHECK: %[[is_contiguous:.*]] = fir.call @_FortranAIsContiguous(%[[box_none]]) : (!fir.box<none>) -> i1
201+
! CHECK: %[[addr:.*]] = fir.if %[[is_contiguous]]
202+
! CHECK: } else {
165203
! CHECK: %[[VAL_2:.*]] = arith.constant 0 : index
166204
! CHECK: %[[VAL_3:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_2]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
167205
! CHECK: %[[VAL_4:.*]] = fir.allocmem !fir.array<?x!fir.char<1,10>>, %[[VAL_3]]#1 {uniq_name = ".copyinout"}
@@ -186,14 +224,15 @@ subroutine test_char(x)
186224
! CHECK: fir.result %[[VAL_23]] : !fir.array<?x!fir.char<1,10>>
187225
! CHECK: }
188226
! CHECK: fir.array_merge_store %[[VAL_6]], %[[VAL_24:.*]] to %[[VAL_4]] : !fir.array<?x!fir.char<1,10>>, !fir.array<?x!fir.char<1,10>>, !fir.heap<!fir.array<?x!fir.char<1,10>>>
189-
! CHECK: %[[VAL_25:.*]] = fir.convert %[[VAL_4]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
227+
! CHECK: %[[dim:.*]]:3 = fir.box_dims %[[VAL_0]], %c0{{.*}} : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
228+
! CHECK: %[[VAL_25:.*]] = fir.convert %[[addr]] : (!fir.heap<!fir.array<?x!fir.char<1,10>>>) -> !fir.ref<!fir.char<1,?>>
190229
! CHECK: %[[VAL_26:.*]] = fir.emboxchar %[[VAL_25]], %[[VAL_1]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
191230
! CHECK: fir.call @_QPbar_char(%[[VAL_26]]) : (!fir.boxchar<1>) -> ()
192231
! CHECK: %[[VAL_27:.*]] = fir.array_load %[[VAL_0]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>) -> !fir.array<?x!fir.char<1,10>>
193232
! CHECK: %[[VAL_28:.*]] = arith.constant 0 : index
194233
! CHECK: %[[VAL_29:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_28]] : (!fir.box<!fir.array<?x!fir.char<1,10>>>, index) -> (index, index, index)
195-
! CHECK: %[[VAL_30:.*]] = fir.shape %[[VAL_3]]#1 : (index) -> !fir.shape<1>
196-
! CHECK: %[[VAL_31:.*]] = fir.array_load %[[VAL_4]](%[[VAL_30]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.array<?x!fir.char<1,10>>
234+
! CHECK: %[[VAL_30:.*]] = fir.shape %[[dim]]#1 : (index) -> !fir.shape<1>
235+
! CHECK: %[[VAL_31:.*]] = fir.array_load %[[addr]](%[[VAL_30]]) : (!fir.heap<!fir.array<?x!fir.char<1,10>>>, !fir.shape<1>) -> !fir.array<?x!fir.char<1,10>>
197236
! CHECK: %[[VAL_32:.*]] = arith.constant 1 : index
198237
! CHECK: %[[VAL_33:.*]] = arith.constant 0 : index
199238
! CHECK: %[[VAL_34:.*]] = arith.subi %[[VAL_29]]#1, %[[VAL_32]] : index
@@ -212,7 +251,7 @@ subroutine test_char(x)
212251
! CHECK: fir.result %[[VAL_47]] : !fir.array<?x!fir.char<1,10>>
213252
! CHECK: }
214253
! CHECK: fir.array_merge_store %[[VAL_27]], %[[VAL_48:.*]] to %[[VAL_0]] : !fir.array<?x!fir.char<1,10>>, !fir.array<?x!fir.char<1,10>>, !fir.box<!fir.array<?x!fir.char<1,10>>>
215-
! CHECK: fir.freemem %[[VAL_4]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
254+
! CHECK: fir.freemem %[[addr]] : !fir.heap<!fir.array<?x!fir.char<1,10>>>
216255

217256
character(10) :: x(:)
218257
call bar_char(x)

0 commit comments

Comments
 (0)