diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index ecc04a6c9a2be..04389bdf44684 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -1122,6 +1122,16 @@ struct AllocMemOpConversion : public fir::FIROpConversion { for (mlir::Value opnd : adaptor.getOperands()) size = rewriter.create( loc, ity, size, integerCast(loc, rewriter, ity, opnd)); + + // As the return value of malloc(0) is implementation defined, allocate one + // byte to ensure the allocation status being true. This behavior aligns to + // what the runtime has. + mlir::Value zero = genConstantIndex(loc, ity, rewriter, 0); + mlir::Value one = genConstantIndex(loc, ity, rewriter, 1); + mlir::Value cmp = rewriter.create( + loc, mlir::LLVM::ICmpPredicate::sgt, size, zero); + size = rewriter.create(loc, cmp, size, one); + auto mallocTyWidth = lowerTy().getIndexTypeBitwidth(); auto mallocTy = mlir::IntegerType::get(rewriter.getContext(), mallocTyWidth); diff --git a/flang/test/Fir/alloc-32.fir b/flang/test/Fir/alloc-32.fir index 3eefc3225fac7..a3cbf200c24fc 100644 --- a/flang/test/Fir/alloc-32.fir +++ b/flang/test/Fir/alloc-32.fir @@ -20,7 +20,9 @@ func.func @allocmem_scalar_nonchar() -> !fir.heap { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]] -// CHECK: %[[trunc:.*]] = trunc i64 %[[mul2]] to i32 +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[sz:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: %[[trunc:.*]] = trunc i64 %[[sz]] to i32 // CHECK: call ptr @malloc(i32 %[[trunc]]) func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { %1 = fir.allocmem !fir.char<1,?>(%l : i32) diff --git a/flang/test/Fir/alloc.fir b/flang/test/Fir/alloc.fir index 5b4930bb9cb34..8da8b828c18b9 100644 --- a/flang/test/Fir/alloc.fir +++ b/flang/test/Fir/alloc.fir @@ -87,7 +87,9 @@ func.func @alloca_scalar_dynchar_kind(%l : i32) -> !fir.ref> { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 1, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { %1 = fir.allocmem !fir.char<1,?>(%l : i32) return %1 : !fir.heap> @@ -97,7 +99,9 @@ func.func @allocmem_scalar_dynchar(%l : i32) -> !fir.heap> { // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 2, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_scalar_dynchar_kind(%l : i32) -> !fir.heap>{ %1 = fir.allocmem !fir.char<2,?>(%l : i32) return %1 : !fir.heap> @@ -152,7 +156,9 @@ func.func @allocmem_array_of_char() -> !fir.heap> // CHECK-SAME: i32 %[[len:.*]]) // CHECK: %[[mul1:.*]] = sext i32 %[[len]] to i64 // CHECK: %[[mul2:.*]] = mul i64 9, %[[mul1]] -// CHECK: call ptr @malloc(i64 %[[mul2]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_of_dynchar(%l: i32) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x3x!fir.char<1,?>>(%l : i32) return %1 : !fir.heap>> @@ -180,7 +186,9 @@ func.func @alloca_dynarray_of_nonchar2(%e: index) -> !fir.ref !fir.heap> { %1 = fir.allocmem !fir.array<3x?xi32>, %e return %1 : !fir.heap> @@ -190,7 +198,9 @@ func.func @allocmem_dynarray_of_nonchar(%e: index) -> !fir.heap !fir.heap> { %1 = fir.allocmem !fir.array, %e, %e return %1 : !fir.heap> @@ -218,7 +228,9 @@ func.func @alloca_dynarray_of_char2(%e : index) -> !fir.ref !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x!fir.char<2,10>>, %e return %1 : !fir.heap>> @@ -228,7 +240,9 @@ func.func @allocmem_dynarray_of_char(%e : index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array>, %e, %e return %1 : !fir.heap>> @@ -261,7 +275,9 @@ func.func @alloca_dynarray_of_dynchar2(%l: i32, %e : index) -> !fir.ref !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x!fir.char<2,?>>(%l : i32), %e return %1 : !fir.heap>> @@ -273,7 +289,9 @@ func.func @allocmem_dynarray_of_dynchar(%l: i32, %e : index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array>(%l : i32), %e, %e return %1 : !fir.heap>> @@ -312,7 +330,9 @@ func.func @alloca_array_with_holes_dynchar(%arg0: index, %arg1: index) -> !fir.r // CHECK-SAME: i64 %[[e1:.*]], i64 %[[e2:.*]]) // CHECK: %[[a:.*]] = mul i64 240, %[[e1]] // CHECK: %[[b:.*]] = mul i64 %3, %[[e2]] -// CHECK: call ptr @malloc(i64 %[[b]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[b]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[b]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.heap> { %a = fir.allocmem !fir.array<4x?x3x?x5xi32>, %0, %1 return %a : !fir.heap> @@ -321,7 +341,9 @@ func.func @allocmem_array_with_holes_nonchar(%0 : index, %1 : index) -> !fir.hea // CHECK-LABEL: define ptr @allocmem_array_with_holes_char( // CHECK-SAME: i64 %[[e:.*]]) // CHECK: %[[mul:.*]] = mul i64 240, %[[e]] -// CHECK: call ptr @malloc(i64 %[[mul]]) +// CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul]], 0 +// CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul]], i64 1 +// CHECK: call ptr @malloc(i64 %[[size]]) func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,10>>, %e return %1 : !fir.heap>> @@ -331,7 +353,9 @@ func.func @allocmem_array_with_holes_char(%e: index) -> !fir.heap !fir.heap>> { %1 = fir.allocmem !fir.array<3x?x4x!fir.char<2,?>>(%arg0 : index), %arg1 return %1 : !fir.heap>> diff --git a/flang/test/Fir/arrexp.fir b/flang/test/Fir/arrexp.fir index 6c7f71f6f1f9c..e8ec8ac79e0c2 100644 --- a/flang/test/Fir/arrexp.fir +++ b/flang/test/Fir/arrexp.fir @@ -146,7 +146,9 @@ func.func @f6(%arg0: !fir.box>, %arg1: f32) { // CHECK: %[[EXT_GEP:.*]] = getelementptr {{.*}} %[[A]], i32 0, i32 7, i64 0, i32 1 // CHECK: %[[EXTENT:.*]] = load i64, ptr %[[EXT_GEP]] // CHECK: %[[SIZE:.*]] = mul i64 4, %[[EXTENT]] - // CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SIZE]]) + // CHECK: %[[CMP:.*]] = icmp sgt i64 %[[SIZE]], 0 + // CHECK: %[[SZ:.*]] = select i1 %[[CMP]], i64 %[[SIZE]], i64 1 + // CHECK: %[[MALLOC:.*]] = call ptr @malloc(i64 %[[SZ]]) %1 = fir.slice %c2, %c10, %c1 : (index, index, index) -> !fir.slice<1> %2 = fir.array_load %arg0 [%1] : (!fir.box>, !fir.slice<1>) -> !fir.array %3 = fir.slice %c1, %c9, %c1 : (index, index, index) -> !fir.slice<1> diff --git a/flang/test/Fir/convert-to-llvm.fir b/flang/test/Fir/convert-to-llvm.fir index 0e2bfe48a807d..50a98466f0d4b 100644 --- a/flang/test/Fir/convert-to-llvm.fir +++ b/flang/test/Fir/convert-to-llvm.fir @@ -216,10 +216,14 @@ func.func @test_alloc_and_freemem_one() { } // CHECK-LABEL: llvm.func @test_alloc_and_freemem_one() { -// CHECK: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64 -// CHECK-NEXT: llvm.call @malloc(%[[N]]) -// CHECK: llvm.call @free(%{{.*}}) -// CHECK-NEXT: llvm.return +// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(4 : i64) : i64 +// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64 +// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64 +// CHECK-NEXT: llvm.call @malloc(%[[SZ]]) +// CHECK: llvm.call @free(%{{.*}}) +// CHECK-NEXT: llvm.return // ----- // Verify that fir.allocmem is transformed to a call to malloc @@ -233,8 +237,12 @@ func.func @test_alloc_and_freemem_several() { } // CHECK-LABEL: llvm.func @test_alloc_and_freemem_several() { -// CHECK: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64 -// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[N]]) +// CHECK-DAG: %[[N:.*]] = llvm.mlir.constant(400 : i64) : i64 +// CHECK-DAG: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK-DAG: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK-NEXT: %[[CMP:.*]] = llvm.icmp "sgt" %[[N]], %[[ZERO]] : i64 +// CHECK-NEXT: %[[SZ:.*]] = llvm.select %[[CMP]], %[[N]], %[[ONE]] : i1, i64 +// CHECK: [[MALLOC:%.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free([[MALLOC]]) // CHECK: llvm.return @@ -250,7 +258,11 @@ func.func @test_with_shape(%ncols: index, %nrows: index) { // CHECK: %[[FOUR:.*]] = llvm.mlir.constant(4 : i64) : i64 // CHECK: %[[DIM1_SIZE:.*]] = llvm.mul %[[FOUR]], %[[NCOLS]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[DIM1_SIZE]], %[[NROWS]] : i64 -// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) +// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64 +// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONE]] : i1, i64 +// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> () // CHECK: llvm.return // CHECK: } @@ -266,7 +278,11 @@ func.func @test_string_with_shape(%len: index, %nelems: index) { // CHECK: %[[ONE:.*]] = llvm.mlir.constant(1 : i64) : i64 // CHECK: %[[LEN_SIZE:.*]] = llvm.mul %[[ONE]], %[[LEN]] : i64 // CHECK: %[[TOTAL_SIZE:.*]] = llvm.mul %[[LEN_SIZE]], %[[NELEMS]] : i64 -// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[TOTAL_SIZE]]) +// CHECK: %[[ZERO:.*]] = llvm.mlir.constant(0 : i64) : i64 +// CHECK: %[[ONEA:.*]] = llvm.mlir.constant(1 : i64) : i64 +// CHECK: %[[CMP:.*]] = llvm.icmp "sgt" %[[TOTAL_SIZE]], %[[ZERO]] : i64 +// CHECK: %[[SZ:.*]] = llvm.select %[[CMP]], %[[TOTAL_SIZE]], %[[ONEA]] : i1, i64 +// CHECK: %[[MEM:.*]] = llvm.call @malloc(%[[SZ]]) // CHECK: llvm.call @free(%[[MEM]]) : (!llvm.ptr) -> () // CHECK: llvm.return // CHECK: } diff --git a/flang/test/Lower/forall/character-1.f90 b/flang/test/Lower/forall/character-1.f90 index 1e4bb73350871..d1e12a8dbdfec 100644 --- a/flang/test/Lower/forall/character-1.f90 +++ b/flang/test/Lower/forall/character-1.f90 @@ -29,7 +29,9 @@ end program test ! CHECK: %[[esval:.*]] = load i64, ptr %[[elesize]] ! CHECK: %[[mul:.*]] = mul i64 1, %[[esval]] ! CHECK: %[[mul2:.*]] = mul i64 %[[mul]], %[[extval]] -! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[mul2]]) +! CHECK: %[[cmp:.*]] = icmp sgt i64 %[[mul2]], 0 +! CHECK: %[[size:.*]] = select i1 %[[cmp]], i64 %[[mul2]], i64 1 +! CHECK: %[[buff:.*]] = call ptr @malloc(i64 %[[size]]) ! CHECK: %[[to:.*]] = getelementptr i8, ptr %[[buff]], i64 % ! CHECK: call void @llvm.memmove.p0.p0.i64(ptr %[[to]], ptr %{{.*}}, i64 %{{.*}}, i1 false) ! CHECK: call void @free(ptr %[[buff]])