diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -510,6 +510,7 @@ mlir::Value genIshft(mlir::Type, llvm::ArrayRef); mlir::Value genIshftc(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef); + mlir::Value genLeadz(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genLen(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genLenTrim(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genMatmul(mlir::Type, llvm::ArrayRef); @@ -527,6 +528,8 @@ mlir::Value genNot(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef); + mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef); + mlir::Value genPoppar(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genPresent(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genProduct(mlir::Type, llvm::ArrayRef); void genRandomInit(llvm::ArrayRef); @@ -547,6 +550,7 @@ fir::ExtendedValue genSpread(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef); void genSystemClock(llvm::ArrayRef); + mlir::Value genTrailz(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genTransfer(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genTranspose(mlir::Type, @@ -793,6 +797,7 @@ &I::genLbound, {{{"array", asInquired}, {"dim", asValue}, {"kind", asValue}}}, /*isElemental=*/false}, + {"leadz", &I::genLeadz}, {"len", &I::genLen, {{{"string", asInquired}, {"kind", asValue}}}, @@ -857,6 +862,8 @@ {"mask", asBox}, {"vector", asBox, handleDynamicOptional}}}, /*isElemental=*/false}, + {"popcnt", &I::genPopcnt}, + {"poppar", &I::genPoppar}, {"present", &I::genPresent, {{{"a", asInquired}}}, @@ -925,6 +932,7 @@ &I::genSystemClock, {{{"count", asAddr}, {"count_rate", asAddr}, {"count_max", asAddr}}}, /*isElemental=*/false}, + {"trailz", &I::genTrailz}, {"transfer", &I::genTransfer, {{{"source", asAddr}, {"mold", asAddr}, {"size", asValue}}}, @@ -3201,6 +3209,17 @@ return builder.create(loc, shiftIsNop, I, res); } +// LEADZ +mlir::Value IntrinsicLibrary::genLeadz(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + + mlir::Value result = + builder.create(loc, args); + + return builder.createConvert(loc, resultType, result); +} + // LEN // Note that this is only used for an unrestricted intrinsic LEN call. // Other uses of LEN are rewritten as descriptor inquiries by the front-end. @@ -3497,6 +3516,27 @@ "unexpected result for PACK"); } +// POPCNT +mlir::Value IntrinsicLibrary::genPopcnt(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + + mlir::Value count = builder.create(loc, args); + + return builder.createConvert(loc, resultType, count); +} + +// POPPAR +mlir::Value IntrinsicLibrary::genPoppar(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + + mlir::Value count = genPopcnt(resultType, args); + mlir::Value one = builder.createIntegerConstant(loc, resultType, 1); + + return builder.create(loc, count, one); +} + // PRESENT fir::ExtendedValue IntrinsicLibrary::genPresent(mlir::Type, @@ -3776,6 +3816,17 @@ .getResults()[0]; } +// TRAILZ +mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + + mlir::Value result = + builder.create(loc, args); + + return builder.createConvert(loc, resultType, result); +} + static bool hasDefaultLowerBound(const fir::ExtendedValue &exv) { return exv.match( [](const fir::ArrayBoxValue &arr) { return arr.getLBounds().empty(); }, diff --git a/flang/test/Lower/Intrinsics/leadz.f90 b/flang/test/Lower/Intrinsics/leadz.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/leadz.f90 @@ -0,0 +1,66 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: leadz1_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine leadz1_test(a, b) + integer(1) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = leadz(a) + ! CHECK: %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i8 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine leadz1_test + +! CHECK-LABEL: leadz2_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine leadz2_test(a, b) + integer(2) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = leadz(a) + ! CHECK: %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i16 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine leadz2_test + +! CHECK-LABEL: leadz4_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine leadz4_test(a, b) + integer(4) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = leadz(a) + ! CHECK: %[[RESULT:.*]] = math.ctlz %[[AVAL]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine leadz4_test + +! CHECK-LABEL: leadz8_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine leadz8_test(a, b) + integer(8) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = leadz(a) + ! CHECK: %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i64 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine leadz8_test + +! CHECK-LABEL: leadz16_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine leadz16_test(a, b) + integer(16) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = leadz(a) + ! CHECK: %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i128 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine leadz16_test diff --git a/flang/test/Lower/Intrinsics/popcnt.f90 b/flang/test/Lower/Intrinsics/popcnt.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/popcnt.f90 @@ -0,0 +1,66 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: popcnt1_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine popcnt1_test(a, b) + integer(1) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = popcnt(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i8 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine popcnt1_test + +! CHECK-LABEL: popcnt2_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine popcnt2_test(a, b) + integer(2) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = popcnt(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i16 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine popcnt2_test + +! CHECK-LABEL: popcnt4_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine popcnt4_test(a, b) + integer(4) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = popcnt(a) + ! CHECK: %[[RESULT:.*]] = math.ctpop %[[AVAL]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine popcnt4_test + +! CHECK-LABEL: popcnt8_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine popcnt8_test(a, b) + integer(8) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = popcnt(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i64 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine popcnt8_test + +! CHECK-LABEL: popcnt16_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine popcnt16_test(a, b) + integer(16) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = popcnt(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i128 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine popcnt16_test diff --git a/flang/test/Lower/Intrinsics/poppar.f90 b/flang/test/Lower/Intrinsics/poppar.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/poppar.f90 @@ -0,0 +1,76 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: poppar1_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine poppar1_test(a, b) + integer(1) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = poppar(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i8 + ! CHECK: %[[CONV:.*]] = fir.convert %[[COUNT]] : (i8) -> i32 + ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 + ! CHECK: %[[RESULT:.*]] = arith.andi %[[CONV]], %[[C1]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine poppar1_test + +! CHECK-LABEL: poppar2_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine poppar2_test(a, b) + integer(2) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = poppar(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i16 + ! CHECK: %[[CONV:.*]] = fir.convert %[[COUNT]] : (i16) -> i32 + ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 + ! CHECK: %[[RESULT:.*]] = arith.andi %[[CONV]], %[[C1]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine poppar2_test + +! CHECK-LABEL: poppar4_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine poppar4_test(a, b) + integer(4) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = poppar(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i32 + ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 + ! CHECK: %[[RESULT:.*]] = arith.andi %[[COUNT]], %[[C1]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine poppar4_test + +! CHECK-LABEL: poppar8_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine poppar8_test(a, b) + integer(8) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = poppar(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i64 + ! CHECK: %[[CONV:.*]] = fir.convert %[[COUNT]] : (i64) -> i32 + ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 + ! CHECK: %[[RESULT:.*]] = arith.andi %[[CONV]], %[[C1]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine poppar8_test + +! CHECK-LABEL: poppar16_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine poppar16_test(a, b) + integer(16) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = poppar(a) + ! CHECK: %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i128 + ! CHECK: %[[CONV:.*]] = fir.convert %[[COUNT]] : (i128) -> i32 + ! CHECK: %[[C1:.*]] = arith.constant 1 : i32 + ! CHECK: %[[RESULT:.*]] = arith.andi %[[CONV]], %[[C1]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine poppar16_test diff --git a/flang/test/Lower/Intrinsics/trailz.f90 b/flang/test/Lower/Intrinsics/trailz.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/trailz.f90 @@ -0,0 +1,66 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: trailz1_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine trailz1_test(a, b) + integer(1) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = trailz(a) + ! CHECK: %[[COUNT:.*]] = math.cttz %[[AVAL]] : i8 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine trailz1_test + +! CHECK-LABEL: trailz2_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine trailz2_test(a, b) + integer(2) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = trailz(a) + ! CHECK: %[[COUNT:.*]] = math.cttz %[[AVAL]] : i16 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine trailz2_test + +! CHECK-LABEL: trailz4_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine trailz4_test(a, b) + integer(4) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = trailz(a) + ! CHECK: %[[RESULT:.*]] = math.cttz %[[AVAL]] : i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine trailz4_test + +! CHECK-LABEL: trailz8_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine trailz8_test(a, b) + integer(8) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = trailz(a) + ! CHECK: %[[COUNT:.*]] = math.cttz %[[AVAL]] : i64 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine trailz8_test + +! CHECK-LABEL: trailz16_test +! CHECK-SAME: %[[AREF:.*]]: !fir.ref{{.*}}, %[[BREF:.*]]: !fir.ref{{.*}} +subroutine trailz16_test(a, b) + integer(16) :: a + integer :: b + + ! CHECK: %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref + b = trailz(a) + ! CHECK: %[[COUNT:.*]] = math.cttz %[[AVAL]] : i128 + ! CHECK: %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32 + ! CHECK: fir.store %[[RESULT]] to %[[BREF]] : !fir.ref +end subroutine trailz16_test