Skip to content

Commit

Permalink
[flang] Lower REAL(16) MODULO to Float128Math library call. (#85322)
Browse files Browse the repository at this point in the history
I did not test it through in #85005, and my assumption was wrong:
arith::RemFOp might be lowered to an fmodf128() call that does not
exist everywhere.
  • Loading branch information
vzakhari committed Mar 15, 2024
1 parent ec2b752 commit 86293a7
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 12 deletions.
4 changes: 4 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Numeric.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ mlir::Value genFraction(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value genMod(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value a, mlir::Value p);

/// Generate call to Modulo intrinsic runtime routine.
mlir::Value genModulo(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value a, mlir::Value p);

/// Generate call to Nearest intrinsic runtime routine.
mlir::Value genNearest(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value x, mlir::Value s);
Expand Down
7 changes: 7 additions & 0 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5259,6 +5259,13 @@ mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType,
remainder);
}

// F128 arith::RemFOp may be lowered to a runtime call that may be unsupported
// on the target, so generate a call to Fortran Runtime's ModuloReal16.
if (resultType == mlir::FloatType::getF128(builder.getContext()))
return builder.createConvert(
loc, resultType,
fir::runtime::genModulo(builder, loc, args[0], args[1]));

auto remainder = builder.create<mlir::arith::RemFOp>(loc, args[0], args[1]);
mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType());
auto remainderIsNotZero = builder.create<mlir::arith::CmpFOp>(
Expand Down
41 changes: 41 additions & 0 deletions flang/lib/Optimizer/Builder/Runtime/Numeric.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,20 @@ struct ForcedMod16 {
}
};

/// Placeholder for real*16 version of Modulo Intrinsic
struct ForcedModulo16 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(ModuloReal16));
static constexpr fir::runtime::FuncTypeBuilderFunc getTypeModel() {
return [](mlir::MLIRContext *ctx) {
auto fltTy = mlir::FloatType::getF128(ctx);
auto strTy = fir::ReferenceType::get(mlir::IntegerType::get(ctx, 8));
auto intTy = mlir::IntegerType::get(ctx, 8 * sizeof(int));
return mlir::FunctionType::get(ctx, {fltTy, fltTy, strTy, intTy},
{fltTy});
};
}
};

/// Placeholder for real*10 version of Nearest Intrinsic
struct ForcedNearest10 {
static constexpr const char *name = ExpandAndQuoteKey(RTNAME(Nearest10));
Expand Down Expand Up @@ -323,6 +337,33 @@ mlir::Value fir::runtime::genMod(fir::FirOpBuilder &builder, mlir::Location loc,
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}

/// Generate call to Modulo intrinsic runtime routine.
mlir::Value fir::runtime::genModulo(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value a,
mlir::Value p) {
mlir::func::FuncOp func;
mlir::Type fltTy = a.getType();

if (fltTy != p.getType())
fir::emitFatalError(loc, "arguments type mismatch in MOD");

// MODULO is lowered into math operations in intrinsics lowering,
// so genModulo() should only be used for F128 data type now.
if (fltTy.isF128())
func = fir::runtime::getRuntimeFunc<ForcedModulo16>(loc, builder);
else
fir::intrinsicTypeTODO(builder, fltTy, loc, "MODULO");

auto funcTy = func.getFunctionType();
auto sourceFile = fir::factory::locationToFilename(builder, loc);
auto sourceLine =
fir::factory::locationToLineNo(builder, loc, funcTy.getInput(3));
auto args = fir::runtime::createArguments(builder, loc, funcTy, a, p,
sourceFile, sourceLine);

return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}

/// Generate call to Nearest intrinsic runtime routine.
mlir::Value fir::runtime::genNearest(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value x,
Expand Down
13 changes: 1 addition & 12 deletions flang/test/Lower/Intrinsics/modulo.f90
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,6 @@ subroutine modulo_testi(r, a, p)
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f128>{{.*}}, %[[arg1:.*]]: !fir.ref<f128>{{.*}}, %[[arg2:.*]]: !fir.ref<f128>{{.*}}) {
subroutine modulo_testr16(r, a, p)
real(16) :: r, a, p
! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f128>
! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f128>
! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] {{.*}}: f128
! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f128
! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] {{.*}} : f128
! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] {{.*}} : f128
! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] {{.*}} : f128
! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1
! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1
! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] {{.*}}: f128
! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f128
! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<f128>
! CHECK: fir.call @_FortranAModuloReal16({{.*}}){{.*}}: (f128, f128, !fir.ref<i8>, i32) -> f128
r = modulo(a, p)
end subroutine

0 comments on commit 86293a7

Please sign in to comment.