Skip to content

[flang] Implement the lowering portion of the CSHIFT intrinsic #937

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 22, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions flang/include/flang/Lower/TransformationalRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class ExtendedValue;
namespace Fortran::lower {
class FirOpBuilder;

void genCshift(FirOpBuilder &builder, mlir::Location loc, mlir::Value resultBox,
mlir::Value arrayBox, mlir::Value shiftBox, mlir::Value dimBox);

void genCshiftVector(FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value arrayBox,
mlir::Value shiftBox);

void genReshape(FirOpBuilder &builder, mlir::Location loc,
mlir::Value resultBox, mlir::Value sourceBox,
mlir::Value shapeBox, mlir::Value padBox, mlir::Value orderBox);
Expand Down
45 changes: 45 additions & 0 deletions flang/lib/Lower/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ struct IntrinsicLibrary {
mlir::Value genConjg(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genCount(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
void genCpuTime(llvm::ArrayRef<fir::ExtendedValue>);
fir::ExtendedValue genCshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
void genDateAndTime(llvm::ArrayRef<fir::ExtendedValue>);
mlir::Value genDim(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genDprod(mlir::Type, llvm::ArrayRef<mlir::Value>);
Expand Down Expand Up @@ -629,6 +630,10 @@ static constexpr IntrinsicHandler handlers[]{
&I::genCpuTime,
{{{"time", asAddr}}},
/*isElemental=*/false},
{"cshift",
&I::genCshift,
{{{"array", asAddr}, {"shift", asAddr}, {"dim", asValue}}},
/*isElemental=*/false},
{"date_and_time",
&I::genDateAndTime,
{{{"date", asAddr},
Expand Down Expand Up @@ -1969,6 +1974,46 @@ void IntrinsicLibrary::genCpuTime(llvm::ArrayRef<fir::ExtendedValue> args) {
builder.create<fir::StoreOp>(loc, res2, *arg);
}

// CSHIFT
fir::ExtendedValue
IntrinsicLibrary::genCshift(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 3);

// Handle required ARRAY argument
fir::BoxValue arrayBox = builder.createBox(loc, args[0]);
auto array = fir::getBase(arrayBox);
auto arrayRank = arrayBox.rank();

// Create mutable fir.box to be passed to the runtime for the result.
auto resultArrayType = builder.getVarLenSeqTy(resultType, arrayRank);
auto resultMutableBox =
Fortran::lower::createTempMutableBox(builder, loc, resultArrayType);
auto resultIrBox =
Fortran::lower::getMutableIRBox(builder, loc, resultMutableBox);

if (arrayRank == 1) {
// Vector case
// Handle required SHIFT argument as a scalar
auto shift = fir::getBase(args[1]);

Fortran::lower::genCshiftVector(builder, loc, resultIrBox, array, shift);
} else {
// Non-vector case
// Handle required SHIFT argument as an array
auto shift = builder.createBox(loc, args[1]);

// Handle optional DIM argument
auto dim =
isAbsent(args[2])
? builder.createIntegerConstant(loc, builder.getIndexType(), 1)
: fir::getBase(args[2]);
Fortran::lower::genCshift(builder, loc, resultIrBox, array, shift, dim);
}
return readAndAddCleanUp(resultMutableBox, resultType,
"unexpected result for CSHIFT");
}

// DATE_AND_TIME
void IntrinsicLibrary::genDateAndTime(llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 4 && "date_and_time has 4 args");
Expand Down
34 changes: 34 additions & 0 deletions flang/lib/Lower/TransformationalRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,40 @@

using namespace Fortran::runtime;

/// Generate call to Cshift intrinsic
void Fortran::lower::genCshift(Fortran::lower::FirOpBuilder &builder,
mlir::Location loc, mlir::Value resultBox,
mlir::Value arrayBox, mlir::Value shiftBox,
mlir::Value dimBox) {
auto cshiftFunc =
Fortran::lower::getRuntimeFunc<mkRTKey(Cshift)>(loc, builder);
auto fTy = cshiftFunc.getType();
auto sourceFile = Fortran::lower::locationToFilename(builder, loc);
auto sourceLine =
Fortran::lower::locationToLineNo(builder, loc, fTy.getInput(5));
auto args =
Fortran::lower::createArguments(builder, loc, fTy, resultBox, arrayBox,
shiftBox, dimBox, sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, cshiftFunc, args);
}

/// Generate call to the vector version of the Cshift intrinsic
void Fortran::lower::genCshiftVector(Fortran::lower::FirOpBuilder &builder,
mlir::Location loc, mlir::Value resultBox,
mlir::Value arrayBox,
mlir::Value shiftBox) {
auto cshiftFunc =
Fortran::lower::getRuntimeFunc<mkRTKey(CshiftVector)>(loc, builder);
auto fTy = cshiftFunc.getType();

auto sourceFile = Fortran::lower::locationToFilename(builder, loc);
auto sourceLine =
Fortran::lower::locationToLineNo(builder, loc, fTy.getInput(4));
auto args = Fortran::lower::createArguments(
builder, loc, fTy, resultBox, arrayBox, shiftBox, sourceFile, sourceLine);
builder.create<fir::CallOp>(loc, cshiftFunc, args);
}

/// Generate call to Reshape intrinsic runtime routine.
void Fortran::lower::genReshape(Fortran::lower::FirOpBuilder &builder,
mlir::Location loc, mlir::Value resultBox,
Expand Down
52 changes: 52 additions & 0 deletions flang/test/Lower/transformational-intrinsics.f90
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,58 @@ subroutine in_elem_expr(x, y, z)
! CHECK: fir.freemem %[[res_addr]] : !fir.heap<!fir.array<?x!fir.logical<1>>>
end subroutine

! CSHIFT
subroutine cshift_test()
! CHECK-LABEL: cshift_test
integer, dimension (3, 3) :: array
integer, dimension(3) :: shift
integer, dimension(3, 3) :: result
integer, dimension(6) :: vectorResult
integer, dimension (6) :: vector
! CHECK-DAG: %[[cs0:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?xi32>>> {uniq_name = ""}
! CHECK-DAG: %[[cs1:.*]] = fir.alloca i32
! CHECK-DAG: %[[cs2:.*]] = fir.alloca !fir.box<!fir.heap<!fir.array<?x?xi32>>> {uniq_name = ""}
! CHECK-DAG: %[[cs3:.*]] = fir.alloca !fir.array<3x3xi32> {bindc_name = "array", uniq_name = "_QMtest2Fcshift_testEarray"}
! CHECK-DAG: %[[cs5:.*]] = fir.alloca !fir.array<3xi32> {bindc_name = "shift", uniq_name = "_QMtest2Fcshift_testEshift"}
! CHECK-DAG: %[[cs6:.*]] = fir.alloca !fir.array<6xi32> {bindc_name = "vector", uniq_name = "_QMtest2Fcshift_testEvector"}
! CHECK-DAG: %[[cs8:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
! CHECK-DAG: %[[cs10:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
! CHECK-DAG: %[[cs11:.*]] = fir.embox %[[cs3]](%[[cs10]]) : (!fir.ref<!fir.array<3x3xi32>>, !fir.shape<2>) -> !fir.box<!fir.array<3x3xi32>>
! CHECK-DAG: %[[cs12:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
! CHECK-DAG: %[[cs13:.*]] = fir.embox %[[cs5]](%[[cs12]]) : (!fir.ref<!fir.array<3xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<3xi32>>
! CHECK-DAG: %[[cs14:.*]] = fir.zero_bits !fir.heap<!fir.array<?x?xi32>>
! CHECK-DAG: %[[cs15:.*]] = fir.shape %{{.*}}, %{{.*}} : (index, index) -> !fir.shape<2>
! CHECK-DAG: %[[cs16:.*]] = fir.embox %[[cs14]](%[[cs15]]) : (!fir.heap<!fir.array<?x?xi32>>, !fir.shape<2>) -> !fir.box<!fir.heap<!fir.array<?x?xi32>>>
! CHECK-DAG: fir.store %[[cs16]] to %[[cs2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>
! CHECK-DAG: %[[cs17:.*]] = fir.address_of({{.*}})
! CHECK-DAG: %[[cs18:.*]] = fir.convert %[[cs2]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[cs19:.*]] = fir.convert %[[cs11]] : (!fir.box<!fir.array<3x3xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[cs20:.*]] = fir.convert %[[cs13]] : (!fir.box<!fir.array<3xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[cs21:.*]] = fir.convert %[[cs17]]
! CHECK: fir.call @_FortranACshift(%[[cs18]], %[[cs19]], %[[cs20]], %{{.*}}, %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, !fir.box<none>, i32, !fir.ref<i8>, i32) -> none
! CHECK-DAG: %[[cs23:.*]] = fir.load %[[cs2]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?x?xi32>>>>
! CHECK-DAG: %[[cs26:.*]] = fir.box_addr %{{.*}} : (!fir.box<!fir.heap<!fir.array<?x?xi32>>>) -> !fir.heap<!fir.array<?x?xi32>>
! CHECK: fir.freemem %[[cs26]] : !fir.heap<!fir.array<?x?xi32>>
result = cshift(array, shift, -2) ! non-vector case
vectorResult = cshift(vector, 3) ! vector case
! CHECK-DAG: %[[cs34:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
! CHECK-DAG: %[[cs36:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
! CHECK-DAG: %[[cs37:.*]] = fir.embox %[[cs6]](%[[cs36]]) : (!fir.ref<!fir.array<6xi32>>, !fir.shape<1>) -> !fir.box<!fir.array<6xi32>>
! CHECK-DAG: %[[cs38:.*]] = fir.zero_bits !fir.heap<!fir.array<?xi32>>
! CHECK-DAG: %[[cs39:.*]] = fir.shape %{{.*}} : (index) -> !fir.shape<1>
! CHECK-DAG: %[[cs40:.*]] = fir.embox %[[cs38]](%[[cs39]]) : (!fir.heap<!fir.array<?xi32>>, !fir.shape<1>) -> !fir.box<!fir.heap<!fir.array<?xi32>>>
! CHECK-DAG: fir.store %[[cs40]] to %[[cs0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[cs41:.*]] = fir.address_of({{.*}})
! CHECK-DAG: %[[cs42:.*]] = fir.convert %[[cs0]] : (!fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>) -> !fir.ref<!fir.box<none>>
! CHECK-DAG: %[[cs43:.*]] = fir.convert %[[cs37]] : (!fir.box<!fir.array<6xi32>>) -> !fir.box<none>
! CHECK-DAG: %[[cs44:.*]] = fir.convert %[[cs1]] : (!fir.ref<i32>) -> i64
! CHECK-DAG: %[[cs45:.*]] = fir.convert %[[cs41]]
! CHECK: fir.call @_FortranACshiftVector(%[[cs42]], %[[cs43]], %[[cs44]], %{{.*}}, %{{.*}}) : (!fir.ref<!fir.box<none>>, !fir.box<none>, i64, !fir.ref<i8>, i32) -> none
! CHECK-DAG: %[[cs47:.*]] = fir.load %[[cs0]] : !fir.ref<!fir.box<!fir.heap<!fir.array<?xi32>>>>
! CHECK-DAG: %[[cs49:.*]] = fir.box_addr %[[cs47]] : (!fir.box<!fir.heap<!fir.array<?xi32>>>) -> !fir.heap<!fir.array<?xi32>>
! CHECK: fir.freemem %[[cs49]] : !fir.heap<!fir.array<?xi32>>
end subroutine cshift_test

! UNPACK
! CHECK-LABEL: unpack_test
subroutine unpack_test()
Expand Down