Skip to content

Commit 69b3303

Browse files
clementvalpsteinfeldjeanPeriermleairschweitzpgi
committed
[flang] Lower numeric related instrinsics
This patch adds lowering for some numeric related intrinsics: - `exponent` - `floor` - `fraction` - `mod` - `modulo` - `nint` - `not` - `product` This patch is part of the upstreaming effort from fir-dev branch. Reviewed By: PeteSteinfeld, schweitz Differential Revision: https://reviews.llvm.org/D121828 Co-authored-by: Peter Steinfeld <[email protected]> Co-authored-by: Jean Perier <[email protected]> Co-authored-by: mleair <[email protected]> Co-authored-by: Eric Schweitz <[email protected]>
1 parent 2e7cb8c commit 69b3303

File tree

8 files changed

+463
-1
lines changed

8 files changed

+463
-1
lines changed

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 162 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -453,8 +453,12 @@ struct IntrinsicLibrary {
453453
fir::ExtendedValue genDotProduct(mlir::Type,
454454
llvm::ArrayRef<fir::ExtendedValue>);
455455
fir::ExtendedValue genEoshift(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
456+
mlir::Value genExponent(mlir::Type, llvm::ArrayRef<mlir::Value>);
456457
template <Extremum, ExtremumBehavior>
457458
mlir::Value genExtremum(mlir::Type, llvm::ArrayRef<mlir::Value>);
459+
mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
460+
mlir::Value genFraction(mlir::Type resultType,
461+
mlir::ArrayRef<mlir::Value> args);
458462
/// Lowering for the IAND intrinsic. The IAND intrinsic expects two arguments
459463
/// in the llvm::ArrayRef.
460464
mlir::Value genIand(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -466,13 +470,18 @@ struct IntrinsicLibrary {
466470
mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
467471
mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
468472
fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
469-
fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
470473
fir::ExtendedValue genLen(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
471474
fir::ExtendedValue genLenTrim(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
472475
fir::ExtendedValue genMaxloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
473476
fir::ExtendedValue genMaxval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
474477
fir::ExtendedValue genMinloc(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
475478
fir::ExtendedValue genMinval(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
479+
mlir::Value genMod(mlir::Type, llvm::ArrayRef<mlir::Value>);
480+
mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
481+
mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
482+
mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
483+
fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
484+
fir::ExtendedValue genProduct(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
476485
void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
477486
void genRandomNumber(llvm::ArrayRef<fir::ExtendedValue>);
478487
void genRandomSeed(llvm::ArrayRef<fir::ExtendedValue>);
@@ -636,6 +645,9 @@ static constexpr IntrinsicHandler handlers[]{
636645
{"boundary", asBox, handleDynamicOptional},
637646
{"dim", asValue}}},
638647
/*isElemental=*/false},
648+
{"exponent", &I::genExponent},
649+
{"floor", &I::genFloor},
650+
{"fraction", &I::genFraction},
639651
{"iachar", &I::genIchar},
640652
{"iand", &I::genIand},
641653
{"ibclr", &I::genIbclr},
@@ -684,7 +696,17 @@ static constexpr IntrinsicHandler handlers[]{
684696
{"dim", asValue},
685697
{"mask", asBox, handleDynamicOptional}}},
686698
/*isElemental=*/false},
699+
{"mod", &I::genMod},
700+
{"modulo", &I::genModulo},
701+
{"nint", &I::genNint},
702+
{"not", &I::genNot},
687703
{"null", &I::genNull, {{{"mold", asInquired}}}, /*isElemental=*/false},
704+
{"product",
705+
&I::genProduct,
706+
{{{"array", asBox},
707+
{"dim", asValue},
708+
{"mask", asBox, handleDynamicOptional}}},
709+
/*isElemental=*/false},
688710
{"random_init",
689711
&I::genRandomInit,
690712
{{{"repeatable", asValue}, {"image_distinct", asValue}}},
@@ -795,12 +817,33 @@ static mlir::FunctionType genF64F64F64FuncType(mlir::MLIRContext *context) {
795817
return mlir::FunctionType::get(context, {t, t}, {t});
796818
}
797819

820+
template <int Bits>
821+
static mlir::FunctionType genIntF64FuncType(mlir::MLIRContext *context) {
822+
auto t = mlir::FloatType::getF64(context);
823+
auto r = mlir::IntegerType::get(context, Bits);
824+
return mlir::FunctionType::get(context, {t}, {r});
825+
}
826+
827+
template <int Bits>
828+
static mlir::FunctionType genIntF32FuncType(mlir::MLIRContext *context) {
829+
auto t = mlir::FloatType::getF32(context);
830+
auto r = mlir::IntegerType::get(context, Bits);
831+
return mlir::FunctionType::get(context, {t}, {r});
832+
}
833+
798834
// TODO : Fill-up this table with more intrinsic.
799835
// Note: These are also defined as operations in LLVM dialect. See if this
800836
// can be use and has advantages.
801837
static constexpr RuntimeFunction llvmIntrinsics[] = {
802838
{"abs", "llvm.fabs.f32", genF32F32FuncType},
803839
{"abs", "llvm.fabs.f64", genF64F64FuncType},
840+
// llvm.floor is used for FLOOR, but returns real.
841+
{"floor", "llvm.floor.f32", genF32F32FuncType},
842+
{"floor", "llvm.floor.f64", genF64F64FuncType},
843+
{"nint", "llvm.lround.i64.f64", genIntF64FuncType<64>},
844+
{"nint", "llvm.lround.i64.f32", genIntF32FuncType<64>},
845+
{"nint", "llvm.lround.i32.f64", genIntF64FuncType<32>},
846+
{"nint", "llvm.lround.i32.f32", genIntF32FuncType<32>},
804847
{"pow", "llvm.pow.f32", genF32F32F32FuncType},
805848
{"pow", "llvm.pow.f64", genF64F64F64FuncType},
806849
};
@@ -1890,6 +1933,38 @@ IntrinsicLibrary::genEoshift(mlir::Type resultType,
18901933
"unexpected result for EOSHIFT");
18911934
}
18921935

1936+
// EXPONENT
1937+
mlir::Value IntrinsicLibrary::genExponent(mlir::Type resultType,
1938+
llvm::ArrayRef<mlir::Value> args) {
1939+
assert(args.size() == 1);
1940+
1941+
return builder.createConvert(
1942+
loc, resultType,
1943+
fir::runtime::genExponent(builder, loc, resultType,
1944+
fir::getBase(args[0])));
1945+
}
1946+
1947+
// FLOOR
1948+
mlir::Value IntrinsicLibrary::genFloor(mlir::Type resultType,
1949+
llvm::ArrayRef<mlir::Value> args) {
1950+
// Optional KIND argument.
1951+
assert(args.size() >= 1);
1952+
mlir::Value arg = args[0];
1953+
// Use LLVM floor that returns real.
1954+
mlir::Value floor = genRuntimeCall("floor", arg.getType(), {arg});
1955+
return builder.createConvert(loc, resultType, floor);
1956+
}
1957+
1958+
// FRACTION
1959+
mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType,
1960+
llvm::ArrayRef<mlir::Value> args) {
1961+
assert(args.size() == 1);
1962+
1963+
return builder.createConvert(
1964+
loc, resultType,
1965+
fir::runtime::genFraction(builder, loc, fir::getBase(args[0])));
1966+
}
1967+
18931968
// IAND
18941969
mlir::Value IntrinsicLibrary::genIand(mlir::Type resultType,
18951970
llvm::ArrayRef<mlir::Value> args) {
@@ -2238,6 +2313,83 @@ mlir::Value IntrinsicLibrary::genExtremum(mlir::Type,
22382313
return result;
22392314
}
22402315

2316+
// MOD
2317+
mlir::Value IntrinsicLibrary::genMod(mlir::Type resultType,
2318+
llvm::ArrayRef<mlir::Value> args) {
2319+
assert(args.size() == 2);
2320+
if (resultType.isa<mlir::IntegerType>())
2321+
return builder.create<mlir::arith::RemSIOp>(loc, args[0], args[1]);
2322+
2323+
// Use runtime. Note that mlir::arith::RemFOp implements floating point
2324+
// remainder, but it does not work with fir::Real type.
2325+
// TODO: consider using mlir::arith::RemFOp when possible, that may help
2326+
// folding and optimizations.
2327+
return genRuntimeCall("mod", resultType, args);
2328+
}
2329+
2330+
// MODULO
2331+
mlir::Value IntrinsicLibrary::genModulo(mlir::Type resultType,
2332+
llvm::ArrayRef<mlir::Value> args) {
2333+
assert(args.size() == 2);
2334+
// No floored modulo op in LLVM/MLIR yet. TODO: add one to MLIR.
2335+
// In the meantime, use a simple inlined implementation based on truncated
2336+
// modulo (MOD(A, P) implemented by RemIOp, RemFOp). This avoids making manual
2337+
// division and multiplication from MODULO formula.
2338+
// - If A/P > 0 or MOD(A,P)=0, then INT(A/P) = FLOOR(A/P), and MODULO = MOD.
2339+
// - Otherwise, when A/P < 0 and MOD(A,P) !=0, then MODULO(A, P) =
2340+
// A-FLOOR(A/P)*P = A-(INT(A/P)-1)*P = A-INT(A/P)*P+P = MOD(A,P)+P
2341+
// Note that A/P < 0 if and only if A and P signs are different.
2342+
if (resultType.isa<mlir::IntegerType>()) {
2343+
auto remainder =
2344+
builder.create<mlir::arith::RemSIOp>(loc, args[0], args[1]);
2345+
auto argXor = builder.create<mlir::arith::XOrIOp>(loc, args[0], args[1]);
2346+
mlir::Value zero = builder.createIntegerConstant(loc, argXor.getType(), 0);
2347+
auto argSignDifferent = builder.create<mlir::arith::CmpIOp>(
2348+
loc, mlir::arith::CmpIPredicate::slt, argXor, zero);
2349+
auto remainderIsNotZero = builder.create<mlir::arith::CmpIOp>(
2350+
loc, mlir::arith::CmpIPredicate::ne, remainder, zero);
2351+
auto mustAddP = builder.create<mlir::arith::AndIOp>(loc, remainderIsNotZero,
2352+
argSignDifferent);
2353+
auto remPlusP =
2354+
builder.create<mlir::arith::AddIOp>(loc, remainder, args[1]);
2355+
return builder.create<mlir::arith::SelectOp>(loc, mustAddP, remPlusP,
2356+
remainder);
2357+
}
2358+
// Real case
2359+
auto remainder = builder.create<mlir::arith::RemFOp>(loc, args[0], args[1]);
2360+
mlir::Value zero = builder.createRealZeroConstant(loc, remainder.getType());
2361+
auto remainderIsNotZero = builder.create<mlir::arith::CmpFOp>(
2362+
loc, mlir::arith::CmpFPredicate::UNE, remainder, zero);
2363+
auto aLessThanZero = builder.create<mlir::arith::CmpFOp>(
2364+
loc, mlir::arith::CmpFPredicate::OLT, args[0], zero);
2365+
auto pLessThanZero = builder.create<mlir::arith::CmpFOp>(
2366+
loc, mlir::arith::CmpFPredicate::OLT, args[1], zero);
2367+
auto argSignDifferent =
2368+
builder.create<mlir::arith::XOrIOp>(loc, aLessThanZero, pLessThanZero);
2369+
auto mustAddP = builder.create<mlir::arith::AndIOp>(loc, remainderIsNotZero,
2370+
argSignDifferent);
2371+
auto remPlusP = builder.create<mlir::arith::AddFOp>(loc, remainder, args[1]);
2372+
return builder.create<mlir::arith::SelectOp>(loc, mustAddP, remPlusP,
2373+
remainder);
2374+
}
2375+
2376+
// NINT
2377+
mlir::Value IntrinsicLibrary::genNint(mlir::Type resultType,
2378+
llvm::ArrayRef<mlir::Value> args) {
2379+
assert(args.size() >= 1);
2380+
// Skip optional kind argument to search the runtime; it is already reflected
2381+
// in result type.
2382+
return genRuntimeCall("nint", resultType, {args[0]});
2383+
}
2384+
2385+
// NOT
2386+
mlir::Value IntrinsicLibrary::genNot(mlir::Type resultType,
2387+
llvm::ArrayRef<mlir::Value> args) {
2388+
assert(args.size() == 1);
2389+
mlir::Value allOnes = builder.createIntegerConstant(loc, resultType, -1);
2390+
return builder.create<mlir::arith::XOrIOp>(loc, args[0], allOnes);
2391+
}
2392+
22412393
// NULL
22422394
fir::ExtendedValue
22432395
IntrinsicLibrary::genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) {
@@ -2255,6 +2407,15 @@ IntrinsicLibrary::genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue> args) {
22552407
return fir::MutableBoxValue(boxStorage, mold->nonDeferredLenParams(), {});
22562408
}
22572409

2410+
// PRODUCT
2411+
fir::ExtendedValue
2412+
IntrinsicLibrary::genProduct(mlir::Type resultType,
2413+
llvm::ArrayRef<fir::ExtendedValue> args) {
2414+
return genProdOrSum(fir::runtime::genProduct, fir::runtime::genProductDim,
2415+
resultType, builder, loc, stmtCtx,
2416+
"unexpected result for Product", args);
2417+
}
2418+
22582419
// RANDOM_INIT
22592420
void IntrinsicLibrary::genRandomInit(llvm::ArrayRef<fir::ExtendedValue> args) {
22602421
assert(args.size() == 2);
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! EXPONENT
4+
! CHECK-LABEL: exponent_test
5+
subroutine exponent_test
6+
7+
integer :: i1, i2, i3, i4
8+
! CHECK: %[[i0:.*]] = fir.alloca i32 {bindc_name = "i1", uniq_name = "_QFexponent_testEi1"}
9+
! CHECK: %[[i1:.*]] = fir.alloca i32 {bindc_name = "i2", uniq_name = "_QFexponent_testEi2"}
10+
! CHECK: %[[i2:.*]] = fir.alloca i32 {bindc_name = "i3", uniq_name = "_QFexponent_testEi3"}
11+
! CHECK: %[[i3:.*]] = fir.alloca i32 {bindc_name = "i4", uniq_name = "_QFexponent_testEi4"}
12+
13+
real(kind = 4) :: x1
14+
real(kind = 8) :: x2
15+
real(kind = 10) :: x3
16+
real(kind = 16) :: x4
17+
! CHECK: %[[x0:.*]] = fir.alloca f32 {bindc_name = "x1", uniq_name = "_QFexponent_testEx1"}
18+
! CHECK: %[[x1:.*]] = fir.alloca f64 {bindc_name = "x2", uniq_name = "_QFexponent_testEx2"}
19+
! CHECK: %[[x2:.*]] = fir.alloca f80 {bindc_name = "x3", uniq_name = "_QFexponent_testEx3"}
20+
! CHECK: %[[x3:.*]] = fir.alloca f128 {bindc_name = "x4", uniq_name = "_QFexponent_testEx4"}
21+
22+
i1 = exponent(x1)
23+
! CHECK: %[[temp0:.*]] = fir.load %[[x0:.*]] : !fir.ref<f32>
24+
! CHECK: %[[result0:.*]] = fir.call @_FortranAExponent4_4(%[[temp0:.*]]) : (f32) -> i32
25+
! CHECK: fir.store %[[result0:.*]] to %[[i0:.*]] : !fir.ref<i32>
26+
27+
i2 = exponent(x2)
28+
! CHECK: %[[temp1:.*]] = fir.load %[[x1:.*]] : !fir.ref<f64>
29+
! CHECK: %[[result1:.*]] = fir.call @_FortranAExponent8_4(%[[temp1:.*]]) : (f64) -> i32
30+
! CHECK: fir.store %[[result1:.*]] to %[[i1:.*]] : !fir.ref<i32>
31+
32+
i3 = exponent(x3)
33+
! CHECK: %[[temp2:.*]] = fir.load %[[x2:.*]] : !fir.ref<f80>
34+
! CHECK: %[[result2:.*]] = fir.call @_FortranAExponent10_4(%[[temp2:.*]]) : (f80) -> i32
35+
! CHECK: fir.store %[[result2:.*]] to %[[i2:.*]] : !fir.ref<i32>
36+
37+
i4 = exponent(x4)
38+
! CHECK: %[[temp3:.*]] = fir.load %[[x3:.*]] : !fir.ref<f128>
39+
! CHECK: %[[result3:.*]] = fir.call @_FortranAExponent16_4(%[[temp3:.*]]) : (f128) -> i32
40+
! CHECK: fir.store %[[result3:.*]] to %[[i3:.*]] : !fir.ref<i32>
41+
end subroutine exponent_test

flang/test/Lower/Intrinsics/floor.f90

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! CHECK-LABEL: floor_test1
4+
subroutine floor_test1(i, a)
5+
integer :: i
6+
real :: a
7+
i = floor(a)
8+
! CHECK: %[[f:.*]] = fir.call @llvm.floor.f32
9+
! CHECK: fir.convert %[[f]] : (f32) -> i32
10+
end subroutine
11+
! CHECK-LABEL: floor_test2
12+
subroutine floor_test2(i, a)
13+
integer(8) :: i
14+
real :: a
15+
i = floor(a, 8)
16+
! CHECK: %[[f:.*]] = fir.call @llvm.floor.f32
17+
! CHECK: fir.convert %[[f]] : (f32) -> i64
18+
end subroutine
19+
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! FRACTION
4+
! CHECK-LABE: fraction_test
5+
subroutine fraction_test
6+
7+
real(kind=4) :: x1 = 178.1387e-4
8+
real(kind=8) :: x2 = 178.1387e-4
9+
real(kind=10) :: x3 = 178.1387e-4
10+
real(kind=16) :: x4 = 178.1387e-4
11+
! CHECK: %[[r0:.*]] = fir.address_of(@_QFfraction_testEx1) : !fir.ref<f32>
12+
! CHECK: %[[r1:.*]] = fir.address_of(@_QFfraction_testEx2) : !fir.ref<f64>
13+
! CHECK: %[[r2:.*]] = fir.address_of(@_QFfraction_testEx3) : !fir.ref<f80>
14+
! CHECK: %[[r3:.*]] = fir.address_of(@_QFfraction_testEx4) : !fir.ref<f128>
15+
16+
x1 = fraction(x1)
17+
! CHECK: %[[temp0:.*]] = fir.load %[[r0:.*]] : !fir.ref<f32>
18+
! CHECK: %[[result0:.*]] = fir.call @_FortranAFraction4(%[[temp0:.*]]) : (f32) -> f32
19+
! CHECK: fir.store %[[result0:.*]] to %[[r0:.*]] : !fir.ref<f32>
20+
21+
x2 = fraction(x2)
22+
! CHECK: %[[temp1:.*]] = fir.load %[[r1:.*]] : !fir.ref<f64>
23+
! CHECK: %[[result1:.*]] = fir.call @_FortranAFraction8(%[[temp1:.*]]) : (f64) -> f64
24+
! CHECK: fir.store %[[result1:.*]] to %[[r1:.*]] : !fir.ref<f64>
25+
26+
x3 = fraction(x3)
27+
! CHECK: %[[temp2:.*]] = fir.load %[[r2:.*]] : !fir.ref<f80>
28+
! CHECK: %[[result2:.*]] = fir.call @_FortranAFraction10(%[[temp2:.*]]) : (f80) -> f80
29+
! CHECK: fir.store %[[result2:.*]] to %[[r2:.*]] : !fir.ref<f80>
30+
31+
x4 = fraction(x4)
32+
! CHECK: %[[temp3:.*]] = fir.load %[[r3:.*]] : !fir.ref<f128>
33+
! CHECK: %[[result3:.*]] = fir.call @_FortranAFraction16(%[[temp3:.*]]) : (f128) -> f128
34+
! CHECK: fir.store %[[result3:.*]] to %[[r3:.*]] : !fir.ref<f128>
35+
end subroutine fraction_test
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! CHECK-LABEL: func @_QPmodulo_testr(
4+
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<f64>{{.*}}, %[[arg1:.*]]: !fir.ref<f64>{{.*}}, %[[arg2:.*]]: !fir.ref<f64>{{.*}}) {
5+
subroutine modulo_testr(r, a, p)
6+
real(8) :: r, a, p
7+
! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<f64>
8+
! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<f64>
9+
! CHECK-DAG: %[[rem:.*]] = arith.remf %[[a]], %[[p]] : f64
10+
! CHECK-DAG: %[[zero:.*]] = arith.constant 0.000000e+00 : f64
11+
! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpf une, %[[rem]], %[[zero]] : f64
12+
! CHECK-DAG: %[[aNeg:.*]] = arith.cmpf olt, %[[a]], %[[zero]] : f64
13+
! CHECK-DAG: %[[pNeg:.*]] = arith.cmpf olt, %[[p]], %[[zero]] : f64
14+
! CHECK-DAG: %[[signDifferent:.*]] = arith.xori %[[aNeg]], %[[pNeg]] : i1
15+
! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1
16+
! CHECK-DAG: %[[remPlusP:.*]] = arith.addf %[[rem]], %[[p]] : f64
17+
! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : f64
18+
! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<f64>
19+
r = modulo(a, p)
20+
end subroutine
21+
22+
! CHECK-LABEL: func @_QPmodulo_testi(
23+
! CHECK-SAME: %[[arg0:.*]]: !fir.ref<i64>{{.*}}, %[[arg1:.*]]: !fir.ref<i64>{{.*}}, %[[arg2:.*]]: !fir.ref<i64>{{.*}}) {
24+
subroutine modulo_testi(r, a, p)
25+
integer(8) :: r, a, p
26+
! CHECK-DAG: %[[a:.*]] = fir.load %[[arg1]] : !fir.ref<i64>
27+
! CHECK-DAG: %[[p:.*]] = fir.load %[[arg2]] : !fir.ref<i64>
28+
! CHECK-DAG: %[[rem:.*]] = arith.remsi %[[a]], %[[p]] : i64
29+
! CHECK-DAG: %[[argXor:.*]] = arith.xori %[[a]], %[[p]] : i64
30+
! CHECK-DAG: %[[signDifferent:.*]] = arith.cmpi slt, %[[argXor]], %c0{{.*}} : i64
31+
! CHECK-DAG: %[[remNotZero:.*]] = arith.cmpi ne, %[[rem]], %c0{{.*}} : i64
32+
! CHECK-DAG: %[[mustAddP:.*]] = arith.andi %[[remNotZero]], %[[signDifferent]] : i1
33+
! CHECK-DAG: %[[remPlusP:.*]] = arith.addi %[[rem]], %[[p]] : i64
34+
! CHECK: %[[res:.*]] = arith.select %[[mustAddP]], %[[remPlusP]], %[[rem]] : i64
35+
! CHECK: fir.store %[[res]] to %[[arg0]] : !fir.ref<i64>
36+
r = modulo(a, p)
37+
end subroutine
38+

flang/test/Lower/Intrinsics/nint.f90

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
! RUN: bbc -emit-fir %s -o - | FileCheck %s
2+
3+
! CHECK-LABEL: nint_test1
4+
subroutine nint_test1(i, a)
5+
integer :: i
6+
real :: a
7+
i = nint(a)
8+
! CHECK: fir.call @llvm.lround.i32.f32
9+
end subroutine
10+
! CHECK-LABEL: nint_test2
11+
subroutine nint_test2(i, a)
12+
integer(8) :: i
13+
real(8) :: a
14+
i = nint(a, 8)
15+
! CHECK: fir.call @llvm.lround.i64.f64
16+
end subroutine
17+

0 commit comments

Comments
 (0)