[flang] Lower F08 bit population count intrinsics
authorTarun Prabhu <tarun.prabhu@gmail.com>
Fri, 22 Jul 2022 05:05:33 +0000 (23:05 -0600)
committerTarun Prabhu <tarun.prabhu@gmail.com>
Fri, 22 Jul 2022 05:09:05 +0000 (23:09 -0600)
Lower F08 bit population count intrinsics popcnt, poppar, leadz and trailz. popcnt, leadz and trailz are implemented using the corresponding MLIR math intrinsics. poppar is implemented in terms of popcnt.

Differential Revision: https://reviews.llvm.org/D129584

flang/lib/Lower/IntrinsicCall.cpp
flang/test/Lower/Intrinsics/leadz.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/popcnt.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/poppar.f90 [new file with mode: 0644]
flang/test/Lower/Intrinsics/trailz.f90 [new file with mode: 0644]

index 7d8aac5..7bdfe50 100644 (file)
@@ -510,6 +510,7 @@ struct IntrinsicLibrary {
   mlir::Value genIshft(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIshftc(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genLeadz(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genLen(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genLenTrim(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genMatmul(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
@@ -527,6 +528,8 @@ struct IntrinsicLibrary {
   mlir::Value genNot(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genNull(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genPack(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genPopcnt(mlir::Type, llvm::ArrayRef<mlir::Value>);
+  mlir::Value genPoppar(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genPresent(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genProduct(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   void genRandomInit(llvm::ArrayRef<fir::ExtendedValue>);
@@ -547,6 +550,7 @@ struct IntrinsicLibrary {
   fir::ExtendedValue genSpread(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genSum(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
   void genSystemClock(llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genTrailz(mlir::Type, llvm::ArrayRef<mlir::Value>);
   fir::ExtendedValue genTransfer(mlir::Type,
                                  llvm::ArrayRef<fir::ExtendedValue>);
   fir::ExtendedValue genTranspose(mlir::Type,
@@ -793,6 +797,7 @@ static constexpr IntrinsicHandler handlers[]{
      &I::genLbound,
      {{{"array", asInquired}, {"dim", asValue}, {"kind", asValue}}},
      /*isElemental=*/false},
+    {"leadz", &I::genLeadz},
     {"len",
      &I::genLen,
      {{{"string", asInquired}, {"kind", asValue}}},
@@ -857,6 +862,8 @@ static constexpr IntrinsicHandler handlers[]{
        {"mask", asBox},
        {"vector", asBox, handleDynamicOptional}}},
      /*isElemental=*/false},
+    {"popcnt", &I::genPopcnt},
+    {"poppar", &I::genPoppar},
     {"present",
      &I::genPresent,
      {{{"a", asInquired}}},
@@ -925,6 +932,7 @@ static constexpr IntrinsicHandler handlers[]{
      &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 @@ mlir::Value IntrinsicLibrary::genIshftc(mlir::Type resultType,
   return builder.create<mlir::arith::SelectOp>(loc, shiftIsNop, I, res);
 }
 
+// LEADZ
+mlir::Value IntrinsicLibrary::genLeadz(mlir::Type resultType,
+                                       llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 1);
+
+  mlir::Value result =
+      builder.create<mlir::math::CountLeadingZerosOp>(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 @@ IntrinsicLibrary::genPack(mlir::Type resultType,
                            "unexpected result for PACK");
 }
 
+// POPCNT
+mlir::Value IntrinsicLibrary::genPopcnt(mlir::Type resultType,
+                                        llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 1);
+
+  mlir::Value count = builder.create<mlir::math::CtPopOp>(loc, args);
+
+  return builder.createConvert(loc, resultType, count);
+}
+
+// POPPAR
+mlir::Value IntrinsicLibrary::genPoppar(mlir::Type resultType,
+                                        llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 1);
+
+  mlir::Value count = genPopcnt(resultType, args);
+  mlir::Value one = builder.createIntegerConstant(loc, resultType, 1);
+
+  return builder.create<mlir::arith::AndIOp>(loc, count, one);
+}
+
 // PRESENT
 fir::ExtendedValue
 IntrinsicLibrary::genPresent(mlir::Type,
@@ -3776,6 +3816,17 @@ IntrinsicLibrary::genSize(mlir::Type resultType,
       .getResults()[0];
 }
 
+// TRAILZ
+mlir::Value IntrinsicLibrary::genTrailz(mlir::Type resultType,
+                                        llvm::ArrayRef<mlir::Value> args) {
+  assert(args.size() == 1);
+
+  mlir::Value result =
+      builder.create<mlir::math::CountTrailingZerosOp>(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 (file)
index 0000000..33efe45
--- /dev/null
@@ -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<i8>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine leadz1_test(a, b)
+  integer(1) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i8>
+  b = leadz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i8
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine leadz1_test
+
+! CHECK-LABEL: leadz2_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i16>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine leadz2_test(a, b)
+  integer(2) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i16>
+  b = leadz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i16
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine leadz2_test
+
+! CHECK-LABEL: leadz4_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i32>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine leadz4_test(a, b)
+  integer(4) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i32>
+  b = leadz(a)
+  ! CHECK:  %[[RESULT:.*]] = math.ctlz %[[AVAL]] : i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine leadz4_test
+
+! CHECK-LABEL: leadz8_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i64>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine leadz8_test(a, b)
+  integer(8) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i64>
+  b = leadz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i64
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine leadz8_test
+
+! CHECK-LABEL: leadz16_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i128>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine leadz16_test(a, b)
+  integer(16) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i128>
+  b = leadz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctlz %[[AVAL]] : i128
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine leadz16_test
diff --git a/flang/test/Lower/Intrinsics/popcnt.f90 b/flang/test/Lower/Intrinsics/popcnt.f90
new file mode 100644 (file)
index 0000000..7e5785d
--- /dev/null
@@ -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<i8>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine popcnt1_test(a, b)
+  integer(1) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i8>
+  b = popcnt(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i8
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine popcnt1_test
+
+! CHECK-LABEL: popcnt2_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i16>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine popcnt2_test(a, b)
+  integer(2) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i16>
+  b = popcnt(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i16
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine popcnt2_test
+
+! CHECK-LABEL: popcnt4_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i32>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine popcnt4_test(a, b)
+  integer(4) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i32>
+  b = popcnt(a)
+  ! CHECK:  %[[RESULT:.*]] = math.ctpop %[[AVAL]] : i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine popcnt4_test
+
+! CHECK-LABEL: popcnt8_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i64>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine popcnt8_test(a, b)
+  integer(8) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i64>
+  b = popcnt(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i64
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine popcnt8_test
+
+! CHECK-LABEL: popcnt16_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i128>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine popcnt16_test(a, b)
+  integer(16) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i128>
+  b = popcnt(a)
+  ! CHECK:  %[[COUNT:.*]] = math.ctpop %[[AVAL]] : i128
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine popcnt16_test
diff --git a/flang/test/Lower/Intrinsics/poppar.f90 b/flang/test/Lower/Intrinsics/poppar.f90
new file mode 100644 (file)
index 0000000..7141829
--- /dev/null
@@ -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<i8>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine poppar1_test(a, b)
+  integer(1) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i8>
+  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<i32>
+end subroutine poppar1_test
+
+! CHECK-LABEL: poppar2_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i16>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine poppar2_test(a, b)
+  integer(2) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i16>
+  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<i32>
+end subroutine poppar2_test
+
+! CHECK-LABEL: poppar4_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i32>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine poppar4_test(a, b)
+  integer(4) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i32>
+  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<i32>
+end subroutine poppar4_test
+
+! CHECK-LABEL: poppar8_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i64>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine poppar8_test(a, b)
+  integer(8) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i64>
+  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<i32>
+end subroutine poppar8_test
+
+! CHECK-LABEL: poppar16_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i128>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine poppar16_test(a, b)
+  integer(16) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i128>
+  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<i32>
+end subroutine poppar16_test
diff --git a/flang/test/Lower/Intrinsics/trailz.f90 b/flang/test/Lower/Intrinsics/trailz.f90
new file mode 100644 (file)
index 0000000..db05f31
--- /dev/null
@@ -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<i8>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine trailz1_test(a, b)
+  integer(1) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i8>
+  b = trailz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.cttz %[[AVAL]] : i8
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i8) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine trailz1_test
+
+! CHECK-LABEL: trailz2_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i16>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine trailz2_test(a, b)
+  integer(2) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i16>
+  b = trailz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.cttz %[[AVAL]] : i16
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i16) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine trailz2_test
+
+! CHECK-LABEL: trailz4_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i32>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine trailz4_test(a, b)
+  integer(4) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i32>
+  b = trailz(a)
+  ! CHECK:  %[[RESULT:.*]] = math.cttz %[[AVAL]] : i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine trailz4_test
+
+! CHECK-LABEL: trailz8_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i64>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine trailz8_test(a, b)
+  integer(8) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i64>
+  b = trailz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.cttz %[[AVAL]] : i64
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i64) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine trailz8_test
+
+! CHECK-LABEL: trailz16_test
+! CHECK-SAME: %[[AREF:.*]]: !fir.ref<i128>{{.*}}, %[[BREF:.*]]: !fir.ref<i32>{{.*}}
+subroutine trailz16_test(a, b)
+  integer(16) :: a
+  integer :: b
+
+  ! CHECK:  %[[AVAL:.*]] = fir.load %[[AREF]] : !fir.ref<i128>
+  b = trailz(a)
+  ! CHECK:  %[[COUNT:.*]] = math.cttz %[[AVAL]] : i128
+  ! CHECK:  %[[RESULT:.*]] = fir.convert %[[COUNT]] : (i128) -> i32
+  ! CHECK:  fir.store %[[RESULT]] to %[[BREF]] : !fir.ref<i32>
+end subroutine trailz16_test