Skip to content

Commit df56b1a

Browse files
authored
[flang] handle allocation of zero-sized objects (#149165)
This PR handles the allocation of zero-sized objects for different implementations. One byte is allocated for the zero-sized objects.
1 parent 52a9c49 commit df56b1a

File tree

6 files changed

+79
-23
lines changed

6 files changed

+79
-23
lines changed

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,6 +1123,16 @@ struct AllocMemOpConversion : public fir::FIROpConversion<fir::AllocMemOp> {
11231123
for (mlir::Value opnd : adaptor.getOperands())
11241124
size = rewriter.create<mlir::LLVM::MulOp>(
11251125
loc, ity, size, integerCast(loc, rewriter, ity, opnd));
1126+
1127+
// As the return value of malloc(0) is implementation defined, allocate one
1128+
// byte to ensure the allocation status being true. This behavior aligns to
1129+
// what the runtime has.
1130+
mlir::Value zero = genConstantIndex(loc, ity, rewriter, 0);
1131+
mlir::Value one = genConstantIndex(loc, ity, rewriter, 1);
1132+
mlir::Value cmp = rewriter.create<mlir::LLVM::ICmpOp>(
1133+
loc, mlir::LLVM::ICmpPredicate::sgt, size, zero);
1134+
size = rewriter.create<mlir::LLVM::SelectOp>(loc, cmp, size, one);
1135+
11261136
auto mallocTyWidth = lowerTy().getIndexTypeBitwidth();
11271137
auto mallocTy =
11281138
mlir::IntegerType::get(rewriter.getContext(), mallocTyWidth);

flang/test/Fir/alloc-32.fir

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ func.func @allocmem_scalar_nonchar() -> !fir.heap<i32> {
2020
// CHECK-SAME: i32 %[[len:.*]])
2121
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
2222
// CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]]
23-
// CHECK: %[[trunc:.*]] = trunc i64 %[[mul2]] to i32
23+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
24+
// CHECK: %[[sz:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
25+
// CHECK: %[[trunc:.*]] = trunc i64 %[[sz]] to i32
2426
// CHECK: call ptr @malloc(i32 %[[trunc]])
2527
func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap<!fir.char<1,?>> {
2628
%1 = fir.allocmem !fir.char<1,?>(%l : i32)

flang/test/Fir/alloc.fir

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,9 @@ func.func @alloca_scalar_dynchar_kind(%l : i32) -> !fir.ref<!fir.char<2,?>> {
8787
// CHECK-SAME: i32 %[[len:.*]])
8888
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
8989
// CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]]
90-
// CHECK: call ptr @malloc(i64 %[[mul2]])
90+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
91+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
92+
// CHECK: call ptr @malloc(i64 %[[size]])
9193
func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap<!fir.char<1,?>> {
9294
%1 = fir.allocmem !fir.char<1,?>(%l : i32)
9395
return %1 : !fir.heap<!fir.char<1,?>>
@@ -97,7 +99,9 @@ func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap<!fir.char<1,?>> {
9799
// CHECK-SAME: i32 %[[len:.*]])
98100
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
99101
// CHECK: %[[mul2:.*]] = mul i64 2, %[[mul1]]
100-
// CHECK: call ptr @malloc(i64 %[[mul2]])
102+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
103+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
104+
// CHECK: call ptr @malloc(i64 %[[size]])
101105
func.func @allocmem_scalar_dynchar_kind(%l : i32) -> !fir.heap<!fir.char<2,?>>{
102106
%1 = fir.allocmem !fir.char<2,?>(%l : i32)
103107
return %1 : !fir.heap<!fir.char<2,?>>
@@ -152,7 +156,9 @@ func.func @allocmem_array_of_char() -> !fir.heap<!fir.array<3x3x!fir.char<1,10>>
152156
// CHECK-SAME: i32 %[[len:.*]])
153157
// CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64
154158
// CHECK: %[[mul2:.*]] = mul i64 9, %[[mul1]]
155-
// CHECK: call ptr @malloc(i64 %[[mul2]])
159+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
160+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
161+
// CHECK: call ptr @malloc(i64 %[[size]])
156162
func.func @allocmem_array_of_dynchar(%l: i32) -> !fir.heap<!fir.array<3x3x!fir.char<1,?>>> {
157163
%1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%l : i32)
158164
return %1 : !fir.heap<!fir.array<3x3x!fir.char<1,?>>>
@@ -180,7 +186,9 @@ func.func @alloca_dynarray_of_nonchar2(%e: index) -> !fir.ref<!fir.array<?x?xi32
180186
// CHECK-LABEL: define ptr @allocmem_dynarray_of_nonchar(
181187
// CHECK-SAME: i64 %[[extent:.*]])
182188
// CHECK: %[[prod1:.*]] = mul i64 12, %[[extent]]
183-
// CHECK: call ptr @malloc(i64 %[[prod1]])
189+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod1]], 0
190+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[prod1]], i64 1
191+
// CHECK: call ptr @malloc(i64 %[[size]])
184192
func.func @allocmem_dynarray_of_nonchar(%e: index) -> !fir.heap<!fir.array<3x?xi32>> {
185193
%1 = fir.allocmem !fir.array<3x?xi32>, %e
186194
return %1 : !fir.heap<!fir.array<3x?xi32>>
@@ -190,7 +198,9 @@ func.func @allocmem_dynarray_of_nonchar(%e: index) -> !fir.heap<!fir.array<3x?xi
190198
// CHECK-SAME: i64 %[[extent:.*]])
191199
// CHECK: %[[prod1:.*]] = mul i64 4, %[[extent]]
192200
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
193-
// CHECK: call ptr @malloc(i64 %[[prod2]])
201+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod2]], 0
202+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[prod2]], i64 1
203+
// CHECK: call ptr @malloc(i64 %[[size]])
194204
func.func @allocmem_dynarray_of_nonchar2(%e: index) -> !fir.heap<!fir.array<?x?xi32>> {
195205
%1 = fir.allocmem !fir.array<?x?xi32>, %e, %e
196206
return %1 : !fir.heap<!fir.array<?x?xi32>>
@@ -218,7 +228,9 @@ func.func @alloca_dynarray_of_char2(%e : index) -> !fir.ref<!fir.array<?x?x!fir.
218228
// CHECK-LABEL: define ptr @allocmem_dynarray_of_char(
219229
// CHECK-SAME: i64 %[[extent:.*]])
220230
// CHECK: %[[prod1:.*]] = mul i64 60, %[[extent]]
221-
// CHECK: call ptr @malloc(i64 %[[prod1]])
231+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod1]], 0
232+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[prod1]], i64 1
233+
// CHECK: call ptr @malloc(i64 %[[size]])
222234
func.func @allocmem_dynarray_of_char(%e : index) -> !fir.heap<!fir.array<3x?x!fir.char<2,10>>> {
223235
%1 = fir.allocmem !fir.array<3x?x!fir.char<2,10>>, %e
224236
return %1 : !fir.heap<!fir.array<3x?x!fir.char<2,10>>>
@@ -228,7 +240,9 @@ func.func @allocmem_dynarray_of_char(%e : index) -> !fir.heap<!fir.array<3x?x!fi
228240
// CHECK-SAME: i64 %[[extent:.*]])
229241
// CHECK: %[[prod1:.*]] = mul i64 20, %[[extent]]
230242
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
231-
// CHECK: call ptr @malloc(i64 %[[prod2]])
243+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod2]], 0
244+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
245+
// CHECK: call ptr @malloc(i64 %[[size]])
232246
func.func @allocmem_dynarray_of_char2(%e : index) -> !fir.heap<!fir.array<?x?x!fir.char<2,10>>> {
233247
%1 = fir.allocmem !fir.array<?x?x!fir.char<2,10>>, %e, %e
234248
return %1 : !fir.heap<!fir.array<?x?x!fir.char<2,10>>>
@@ -261,7 +275,9 @@ func.func @alloca_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.ref<!fir.arr
261275
// CHECK: %[[prod1:.*]] = sext i32 %[[len]] to i64
262276
// CHECK: %[[prod2:.*]] = mul i64 6, %[[prod1]]
263277
// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
264-
// CHECK: call ptr @malloc(i64 %[[prod3]])
278+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod3]], 0
279+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[prod3]], i64 1
280+
// CHECK: call ptr @malloc(i64 %[[size]])
265281
func.func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap<!fir.array<3x?x!fir.char<2,?>>> {
266282
%1 = fir.allocmem !fir.array<3x?x!fir.char<2,?>>(%l : i32), %e
267283
return %1 : !fir.heap<!fir.array<3x?x!fir.char<2,?>>>
@@ -273,7 +289,9 @@ func.func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap<!fir.a
273289
// CHECK: %[[prod1:.*]] = mul i64 2, %[[a]]
274290
// CHECK: %[[prod2:.*]] = mul i64 %[[prod1]], %[[extent]]
275291
// CHECK: %[[prod3:.*]] = mul i64 %[[prod2]], %[[extent]]
276-
// CHECK: call ptr @malloc(i64 %[[prod3]])
292+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[prod3]], 0
293+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[prod3]], i64 1
294+
// CHECK: call ptr @malloc(i64 %[[size]])
277295
func.func @allocmem_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.heap<!fir.array<?x?x!fir.char<2,?>>> {
278296
%1 = fir.allocmem !fir.array<?x?x!fir.char<2,?>>(%l : i32), %e, %e
279297
return %1 : !fir.heap<!fir.array<?x?x!fir.char<2,?>>>
@@ -312,7 +330,9 @@ func.func @alloca_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.r
312330
// CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]])
313331
// CHECK: %[[a:.*]] = mul i64 240, %[[e1]]
314332
// CHECK: %[[b:.*]] = mul i64 %3, %[[e2]]
315-
// CHECK: call ptr @malloc(i64 %[[b]])
333+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[b]], 0
334+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[b]], i64 1
335+
// CHECK: call ptr @malloc(i64 %[[size]])
316336
func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.heap<!fir.array<4x?x3x?x5xi32>> {
317337
%a = fir.allocmem !fir.array<4x?x3x?x5xi32>, %0, %1
318338
return %a : !fir.heap<!fir.array<4x?x3x?x5xi32>>
@@ -321,7 +341,9 @@ func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.hea
321341
// CHECK-LABEL: define ptr @allocmem_array_with_holes_char(
322342
// CHECK-SAME: i64 %[[e:.*]])
323343
// CHECK: %[[mul:.*]] = mul i64 240, %[[e]]
324-
// CHECK: call ptr @malloc(i64 %[[mul]])
344+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul]], 0
345+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul]], i64 1
346+
// CHECK: call ptr @malloc(i64 %[[size]])
325347
func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap<!fir.array<3x?x4x!fir.char<2,10>>> {
326348
%1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,10>>, %e
327349
return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,10>>>
@@ -331,7 +353,9 @@ func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap<!fir.array<3x?
331353
// CHECK-SAME: i64 %[[len:.*]], i64 %[[extent:.*]])
332354
// CHECK: %[[a:.*]] = mul i64 24, %[[len]]
333355
// CHECK: %[[b:.*]] = mul i64 %[[a]], %[[extent]]
334-
// CHECK: call ptr @malloc(i64 %[[b]])
356+
// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[b]], 0
357+
// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[b]], i64 1
358+
// CHECK: call ptr @malloc(i64 %[[size]])
335359
func.func @allocmem_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>> {
336360
%1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1
337361
return %1 : !fir.heap<!fir.array<3x?x4x!fir.char<2,?>>>

flang/test/Fir/arrexp.fir

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ func.func @f6(%arg0: !fir.box<!fir.array<?xf32>>, %arg1: f32) {
146146
// CHECK: %[[EXT_GEP:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 7, i64 0, i32 1
147147
// CHECK: %[[EXTENT:.*]] = load i64, ptr %[[EXT_GEP]]
148148
// CHECK: %[[SIZE:.*]] = mul i64 4, %[[EXTENT]]
149-
// CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SIZE]])
149+
// CHECK: %[[CMP:.*]] = icmp sgt i64 %[[SIZE]], 0
150+
// CHECK: %[[SZ:.*]] = select i1 %[[CMP]], i64 %[[SIZE]], i64 1
151+
// CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SZ]])
150152
%1 = fir.slice %c2, %c10, %c1 : (index, index, index) -> !fir.slice<1>
151153
%2 = fir.array_load %arg0 [%1] : (!fir.box<!fir.array<?xf32>>, !fir.slice<1>) -> !fir.array<?xf32>
152154
%3 = fir.slice %c1, %c9, %c1 : (index, index, index) -> !fir.slice<1>

flang/test/Fir/convert-to-llvm.fir

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,10 +216,14 @@ func.func @test_alloc_and_freemem_one() {
216216
}
217217

218218
// CHECK-LABEL: llvm.func @test_alloc_and_freemem_one() {
219-
// CHECK: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64
220-
// CHECK-NEXT: llvm.call @malloc(%[[N]])
221-
// CHECK: llvm.call @free(%{{.*}})
222-
// CHECK-NEXT: llvm.return
219+
// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64
220+
// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
221+
// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
222+
// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64
223+
// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64
224+
// CHECK-NEXT: llvm.call @malloc(%[[SZ]])
225+
// CHECK: llvm.call @free(%{{.*}})
226+
// CHECK-NEXT: llvm.return
223227

224228
// -----
225229
// Verify that fir.allocmem is transformed to a call to malloc
@@ -233,8 +237,12 @@ func.func @test_alloc_and_freemem_several() {
233237
}
234238

235239
// CHECK-LABEL: llvm.func @test_alloc_and_freemem_several() {
236-
// CHECK: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64
237-
// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[N]])
240+
// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64
241+
// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
242+
// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
243+
// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64
244+
// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64
245+
// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[SZ]])
238246
// CHECK: llvm.call @free([[MALLOC]])
239247
// CHECK: llvm.return
240248

@@ -250,7 +258,11 @@ func.func @test_with_shape(%ncols: index, %nrows: index) {
250258
// CHECK: %[[FOUR:.*]] = llvm.mlir.constant(4 : i64) : i64
251259
// CHECK: %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]] : i64
252260
// CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]] : i64
253-
// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
261+
// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
262+
// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
263+
// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64
264+
// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONE]] : i1, i64
265+
// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]])
254266
// CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> ()
255267
// CHECK: llvm.return
256268
// CHECK: }
@@ -266,7 +278,11 @@ func.func @test_string_with_shape(%len: index, %nelems: index) {
266278
// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64
267279
// CHECK: %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]] : i64
268280
// CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]] : i64
269-
// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]])
281+
// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64
282+
// CHECK: %[[ONEA:.*]] = llvm.mlir.constant(1 : i64) : i64
283+
// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64
284+
// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONEA]] : i1, i64
285+
// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]])
270286
// CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> ()
271287
// CHECK: llvm.return
272288
// CHECK: }

flang/test/Lower/forall/character-1.f90

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,9 @@ end program test
2929
! CHECK: %[[esval:.*]] = load i64, ptr %[[elesize]]
3030
! CHECK: %[[mul:.*]] = mul i64 1, %[[esval]]
3131
! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]]
32-
! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[mul2]])
32+
! CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0
33+
! CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1
34+
! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[size]])
3335
! CHECK: %[[to:.*]] = getelementptr i8, ptr %[[buff]], i64 %
3436
! CHECK: call void @llvm.memmove.p0.p0.i64(ptr %[[to]], ptr %{{.*}}, i64 %{{.*}}, i1 false)
3537
! CHECK: call void @free(ptr %[[buff]])

0 commit comments

Comments
 (0)