Skip to content

Commit 2ab1c6d

Browse files
committed
[flang] Add lowering of move_alloc to IntrinsicCall
This patch relies on D141286 for the runtime implementation of move_alloc. Reviewed By: jeanPerier Differential Revision: https://reviews.llvm.org/D141616
1 parent d47a0ac commit 2ab1c6d

File tree

8 files changed

+210
-1
lines changed

8 files changed

+210
-1
lines changed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===-- Allocatable.h - generate Allocatable runtime API calls---*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#ifndef FORTRAN_OPTIMIZER_BUILDER_RUNTIME_ALLOCATABLE_H
10+
#define FORTRAN_OPTIMIZER_BUILDER_RUNTIME_ALLOCATABLE_H
11+
12+
namespace mlir {
13+
class Value;
14+
class Location;
15+
} // namespace mlir
16+
17+
namespace fir {
18+
class FirOpBuilder;
19+
}
20+
21+
namespace fir::runtime {
22+
23+
/// Generate runtime call to assign \p sourceBox to \p destBox.
24+
/// \p destBox must be a fir.ref<fir.box<T>> and \p sourceBox a fir.box<T>.
25+
/// \p destBox Fortran descriptor may be modified if destBox is an allocatable
26+
/// according to Fortran allocatable assignment rules, otherwise it is not
27+
/// modified.
28+
mlir::Value genMoveAlloc(fir::FirOpBuilder &builder, mlir::Location loc,
29+
mlir::Value to, mlir::Value from, mlir::Value hasStat,
30+
mlir::Value errMsg);
31+
32+
} // namespace fir::runtime
33+
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_ALLOCATABLE_H

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
#include "flang/Lower/Runtime.h"
2020
#include "flang/Lower/StatementContext.h"
2121
#include "flang/Lower/SymbolMap.h"
22+
#include "flang/Optimizer/Builder/BoxValue.h"
2223
#include "flang/Optimizer/Builder/Character.h"
2324
#include "flang/Optimizer/Builder/Complex.h"
2425
#include "flang/Optimizer/Builder/FIRBuilder.h"
2526
#include "flang/Optimizer/Builder/MutableBox.h"
27+
#include "flang/Optimizer/Builder/Runtime/Allocatable.h"
2628
#include "flang/Optimizer/Builder/Runtime/Character.h"
2729
#include "flang/Optimizer/Builder/Runtime/Command.h"
2830
#include "flang/Optimizer/Builder/Runtime/Derived.h"
@@ -267,6 +269,7 @@ struct IntrinsicLibrary {
267269
fir::ExtendedValue genMinval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
268270
mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
269271
mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
272+
void genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue>);
270273
void genMvbits(llvm::ArrayRef<fir::ExtendedValue>);
271274
mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
272275
mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -695,6 +698,13 @@ static constexpr IntrinsicHandler handlers[]{
695698
/*isElemental=*/false},
696699
{"mod", &I::genMod},
697700
{"modulo", &I::genModulo},
701+
{"move_alloc",
702+
&I::genMoveAlloc,
703+
{{{"from", asInquired},
704+
{"to", asInquired},
705+
{"status", asAddr, handleDynamicOptional},
706+
{"errMsg", asBox, handleDynamicOptional}}},
707+
/*isElemental=*/false},
698708
{"mvbits",
699709
&I::genMvbits,
700710
{{{"from", asValue},
@@ -3900,6 +3910,46 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType,
39003910
remainder);
39013911
}
39023912

3913+
void IntrinsicLibrary::genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue> args) {
3914+
assert(args.size() == 4);
3915+
3916+
const fir::ExtendedValue &from = args[0];
3917+
const fir::ExtendedValue &to = args[1];
3918+
const fir::ExtendedValue &status = args[2];
3919+
const fir::ExtendedValue &errMsg = args[3];
3920+
3921+
mlir::Type boxNoneTy = fir::BoxType::get(builder.getNoneType());
3922+
mlir::Value errBox =
3923+
isStaticallyPresent(errMsg)
3924+
? fir::getBase(errMsg)
3925+
: builder.create<fir::AbsentOp>(loc, boxNoneTy).getResult();
3926+
3927+
const fir::MutableBoxValue *fromBox = from.getBoxOf<fir::MutableBoxValue>();
3928+
const fir::MutableBoxValue *toBox = to.getBoxOf<fir::MutableBoxValue>();
3929+
3930+
assert(fromBox && toBox && "move_alloc parameters must be mutable arrays");
3931+
3932+
mlir::Value fromAddr = fir::factory::getMutableIRBox(builder, loc, *fromBox);
3933+
mlir::Value toAddr = fir::factory::getMutableIRBox(builder, loc, *toBox);
3934+
3935+
mlir::Value hasStat = builder.createBool(loc, isStaticallyPresent(status));
3936+
3937+
mlir::Value stat = fir::runtime::genMoveAlloc(builder, loc, toAddr, fromAddr,
3938+
hasStat, errBox);
3939+
3940+
fir::factory::syncMutableBoxFromIRBox(builder, loc, *fromBox);
3941+
fir::factory::syncMutableBoxFromIRBox(builder, loc, *toBox);
3942+
3943+
if (isStaticallyPresent(status)) {
3944+
mlir::Value statAddr = fir::getBase(status);
3945+
mlir::Value statIsPresentAtRuntime =
3946+
builder.genIsNotNullAddr(loc, statAddr);
3947+
builder.genIfThen(loc, statIsPresentAtRuntime)
3948+
.genThen([&]() { builder.createStoreWithConvert(loc, stat, statAddr); })
3949+
.end();
3950+
}
3951+
}
3952+
39033953
// MVBITS
39043954
void IntrinsicLibrary::genMvbits(llvm::ArrayRef<fir::ExtendedValue> args) {
39053955
// A conformant MVBITS(FROM,FROMPOS,LEN,TO,TOPOS) call satisfies:

flang/lib/Optimizer/Builder/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_flang_library(FIRBuilder
99
HLFIRTools.cpp
1010
LowLevelIntrinsics.cpp
1111
MutableBox.cpp
12+
Runtime/Allocatable.cpp
1213
Runtime/Assign.cpp
1314
Runtime/Character.cpp
1415
Runtime/Command.cpp
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//===-- Allocatable.cpp -- generate allocatable runtime API calls----------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "flang/Optimizer/Builder/Runtime/Allocatable.h"
10+
#include "flang/Optimizer/Builder/FIRBuilder.h"
11+
#include "flang/Optimizer/Builder/Runtime/RTBuilder.h"
12+
#include "flang/Runtime/allocatable.h"
13+
14+
using namespace Fortran::runtime;
15+
16+
mlir::Value fir::runtime::genMoveAlloc(fir::FirOpBuilder &builder,
17+
mlir::Location loc, mlir::Value to,
18+
mlir::Value from, mlir::Value hasStat,
19+
mlir::Value errMsg) {
20+
mlir::func::FuncOp func{
21+
fir::runtime::getRuntimeFunc<mkRTKey(MoveAlloc)>(loc, builder)};
22+
mlir::FunctionType fTy{func.getFunctionType()};
23+
mlir::Value sourceFile{fir::factory::locationToFilename(builder, loc)};
24+
mlir::Value sourceLine{
25+
fir::factory::locationToLineNo(builder, loc, fTy.getInput(5))};
26+
llvm::SmallVector<mlir::Value> args{fir::runtime::createArguments(
27+
builder, loc, fTy, to, from, hasStat, errMsg, sourceFile, sourceLine)};
28+
29+
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
30+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
! RUN: flang-new -fc1 -emit-fir %s -o - | FileCheck %s
3+
4+
! CHECK-LABEL: to_from_only
5+
subroutine to_from_only
6+
! CHECK: %[[a1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
7+
! CHECK: %[[b1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
8+
integer, allocatable :: from(:), to(:)
9+
allocate(from(20))
10+
! CHECK: %[[errMsg:.*]] = fir.absent !fir.box<none>
11+
! CHECK: %[[false:.*]] = arith.constant false
12+
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
13+
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
14+
call move_alloc(from, to)
15+
! CHECK: fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[false]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
16+
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
17+
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
18+
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
19+
! CHECK-DAG: %[[b4:.*]] = fir.box_addr %[[b3:.*]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
20+
end subroutine to_from_only
21+
22+
! CHECK-LABEL: to_from_stat
23+
subroutine to_from_stat
24+
! CHECK-DAG: %[[a1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
25+
! CHECK-DAG: %[[b1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
26+
integer, allocatable :: from(:), to(:)
27+
! CHECK-DAG: %[[stat1:.*]] = fir.alloca i32
28+
integer :: stat
29+
allocate(from(20))
30+
! CHECK: %[[errMsg:.*]] = fir.absent !fir.box<none>
31+
! CHECK: %[[true:.*]] = arith.constant true
32+
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
33+
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
34+
call move_alloc(from, to, stat)
35+
! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[true]], %[[errMsg]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
36+
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
37+
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
38+
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
39+
! CHECK-DAG: %[[b4:.*]] = fir.box_addr %[[b3:.*]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
40+
end subroutine to_from_stat
41+
42+
! CHECK-LABEL: to_from_stat_errmsg
43+
subroutine to_from_stat_errmsg
44+
! CHECK-DAG: %[[errMsg1:.*]] = fir.alloca !fir.char<1,64>
45+
! CHECK-DAG: %[[a1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
46+
! CHECK-DAG: %[[b1:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>>
47+
integer, allocatable :: from(:), to(:)
48+
! CHECK-DAG: %[[stat1:.*]] = fir.alloca i32
49+
integer :: stat
50+
character :: errMsg*64
51+
allocate(from(20))
52+
! CHECK: %[[errMsg2:.*]] = fir.embox %[[errMsg1]] : (!fir.ref<!fir.char<1,64>>) -> !fir.box<!fir.char<1,64>>
53+
! CHECK: %[[true:.*]] = arith.constant true
54+
! CHECK-DAG: %[[errMsg3:.*]] = fir.convert %[[errMsg2]] : (!fir.box<!fir.char<1,64>>) -> !fir.box<none>
55+
! CHECK-DAG: %[[a2:.*]] = fir.convert %[[a1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
56+
! CHECK-DAG: %[[b2:.*]] = fir.convert %[[b1]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
57+
call move_alloc(from, to, stat, errMsg)
58+
! CHECK: %[[stat:.*]] = fir.call @_FortranAMoveAlloc(%[[b2]], %[[a2]], %[[true]], %[[errMsg3]], %{{.*}}, %{{.*}}) fastmath<contract> : (!fir.ref<!fir.box<none>>, !fir.ref<!fir.box<none>>, i1, !fir.box<none>, !fir.ref<i8>, i32) -> i32
59+
! CHECK-DAG: %[[a3:.*]] = fir.load %[[a1:.*]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
60+
! CHECK-DAG: %[[a4:.*]] = fir.box_addr %[[a3]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
61+
! CHECK-DAG: %[[b3:.*]] = fir.load %[[b1]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
62+
! CHECK-DAG: %[[b4:.*]] = fir.box_addr %[[b3:.*]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
63+
end subroutine to_from_stat_errmsg

flang/unittests/Optimizer/Builder/Runtime/Allocatable.cpp

Whitespace-only changes.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===- AllocatableTest.cpp -- allocatable runtime builder unit tests ------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
#include "flang/Optimizer/Builder/Runtime/Allocatable.h"
10+
#include "RuntimeCallTestBase.h"
11+
#include "gtest/gtest.h"
12+
#include "flang/Runtime/descriptor.h"
13+
14+
using namespace Fortran::runtime;
15+
16+
TEST_F(RuntimeCallTest, genMoveAlloc) {
17+
mlir::Location loc = firBuilder->getUnknownLoc();
18+
mlir::Type seqTy =
19+
fir::SequenceType::get(fir::SequenceType::Shape(1, 10), i32Ty);
20+
mlir::Value from = firBuilder->create<fir::UndefOp>(loc, seqTy);
21+
mlir::Value to = firBuilder->create<fir::UndefOp>(loc, seqTy);
22+
mlir::Value errMsg = firBuilder->create<fir::UndefOp>(loc, seqTy);
23+
mlir::Value hasStat = firBuilder->createBool(loc, false);
24+
fir::runtime::genMoveAlloc(*firBuilder, loc, to, from, hasStat, errMsg);
25+
checkCallOpFromResultBox(to, "_FortranAMoveAlloc", 4);
26+
}

flang/unittests/Optimizer/CMakeLists.txt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ add_flang_unittest(FlangOptimizerTests
1616
Builder/DoLoopHelperTest.cpp
1717
Builder/FIRBuilderTest.cpp
1818
Builder/HLFIRToolsTest.cpp
19+
Builder/Runtime/AllocatableTest.cpp
1920
Builder/Runtime/AssignTest.cpp
2021
Builder/Runtime/CommandTest.cpp
2122
Builder/Runtime/CharacterTest.cpp
@@ -31,7 +32,12 @@ add_flang_unittest(FlangOptimizerTests
3132
InternalNamesTest.cpp
3233
KindMappingTest.cpp
3334
RTBuilder.cpp
34-
)
35+
DEPENDS
36+
FIRDialect
37+
FIRSupport
38+
HLFIRDialect
39+
${dialect_libs})
40+
3541
target_link_libraries(FlangOptimizerTests
3642
PRIVATE
3743
${LIBS})

0 commit comments

Comments
 (0)