[libc-commits] [libc] a5588b6 - [libc] implement `strings/ffs` (#129892)

via libc-commits libc-commits at lists.llvm.org
Fri Mar 7 17:31:21 PST 2025


Author: Connector Switch
Date: 2025-03-08T09:31:18+08:00
New Revision: a5588b6d20590a10db0f1a2046fba4d9f205ed68

URL: https://github.com/llvm/llvm-project/commit/a5588b6d20590a10db0f1a2046fba4d9f205ed68
DIFF: https://github.com/llvm/llvm-project/commit/a5588b6d20590a10db0f1a2046fba4d9f205ed68.diff

LOG: [libc] implement `strings/ffs` (#129892)

This patch adds the `strings/ffs` function.
ref: https://pubs.opengroup.org/onlinepubs/9799919799/functions/ffs.html
Closes: #122054.

Added: 
    libc/src/strings/ffs.cpp
    libc/src/strings/ffs.h
    libc/src/strings/ffsl.cpp
    libc/src/strings/ffsl.h
    libc/src/strings/ffsll.cpp
    libc/src/strings/ffsll.h
    libc/test/src/strings/ffs_test.cpp
    libc/test/src/strings/ffsl_test.cpp
    libc/test/src/strings/ffsll_test.cpp

Modified: 
    libc/config/linux/aarch64/entrypoints.txt
    libc/config/linux/x86_64/entrypoints.txt
    libc/include/strings.yaml
    libc/src/strings/CMakeLists.txt
    libc/test/src/strings/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/libc/config/linux/aarch64/entrypoints.txt b/libc/config/linux/aarch64/entrypoints.txt
index 6c2be4d3b0b99..c7beb3ef3fdfc 100644
--- a/libc/config/linux/aarch64/entrypoints.txt
+++ b/libc/config/linux/aarch64/entrypoints.txt
@@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.bcmp
     libc.src.strings.bcopy
     libc.src.strings.bzero
+    libc.src.strings.ffs
+    libc.src.strings.ffsl
+    libc.src.strings.ffsll
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp

diff  --git a/libc/config/linux/x86_64/entrypoints.txt b/libc/config/linux/x86_64/entrypoints.txt
index 779654422e35b..12dc87bf945fd 100644
--- a/libc/config/linux/x86_64/entrypoints.txt
+++ b/libc/config/linux/x86_64/entrypoints.txt
@@ -93,6 +93,9 @@ set(TARGET_LIBC_ENTRYPOINTS
     libc.src.strings.bcmp
     libc.src.strings.bcopy
     libc.src.strings.bzero
+    libc.src.strings.ffs
+    libc.src.strings.ffsl
+    libc.src.strings.ffsll
     libc.src.strings.index
     libc.src.strings.rindex
     libc.src.strings.strcasecmp

diff  --git a/libc/include/strings.yaml b/libc/include/strings.yaml
index b6aa8f6d60b27..802f6533585f8 100644
--- a/libc/include/strings.yaml
+++ b/libc/include/strings.yaml
@@ -29,6 +29,24 @@ functions:
     arguments:
       - type: void *
       - type: size_t
+  - name: ffs
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: int
+  - name: ffsl
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: long
+  - name: ffsll
+    standards:
+      - POSIX
+    return_type: int
+    arguments:
+      - type: long long
   - name: index
     standards:
       - BSDExtensions

diff  --git a/libc/src/strings/CMakeLists.txt b/libc/src/strings/CMakeLists.txt
index 5e84c7be1f7d6..6d86680e8e71f 100644
--- a/libc/src/strings/CMakeLists.txt
+++ b/libc/src/strings/CMakeLists.txt
@@ -54,6 +54,36 @@ add_entrypoint_object(
     bcopy.h
 )
 
+add_entrypoint_object(
+  ffs
+  SRCS
+    ffs.cpp
+  HDRS
+    ffs.h
+  DEPENDS
+    libc.src.__support.math_extras
+)
+
+add_entrypoint_object(
+  ffsl
+  SRCS
+    ffsl.cpp
+  HDRS
+    ffsl.h
+  DEPENDS
+    libc.src.__support.math_extras
+)
+
+add_entrypoint_object(
+  ffsll
+  SRCS
+    ffsll.cpp
+  HDRS
+    ffsll.h
+  DEPENDS
+    libc.src.__support.math_extras
+)
+
 add_entrypoint_object(
   index
   SRCS

diff  --git a/libc/src/strings/ffs.cpp b/libc/src/strings/ffs.cpp
new file mode 100644
index 0000000000000..5e1efafeab56a
--- /dev/null
+++ b/libc/src/strings/ffs.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ffs ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffs.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/math_extras.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, ffs, (int i)) {
+  return first_trailing_one(static_cast<unsigned>(i));
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/strings/ffs.h b/libc/src/strings/ffs.h
new file mode 100644
index 0000000000000..bf43c43caedb2
--- /dev/null
+++ b/libc/src/strings/ffs.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ffs ---------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STRINGS_FFS_H
+#define LLVM_LIBC_SRC_STRINGS_FFS_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int ffs(int i);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STRINGS_FFS_H

diff  --git a/libc/src/strings/ffsl.cpp b/libc/src/strings/ffsl.cpp
new file mode 100644
index 0000000000000..b1b25598e405b
--- /dev/null
+++ b/libc/src/strings/ffsl.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ffsl --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffsl.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/math_extras.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, ffsl, (long i)) {
+  return first_trailing_one(static_cast<unsigned long>(i));
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/strings/ffsl.h b/libc/src/strings/ffsl.h
new file mode 100644
index 0000000000000..1feca010b2ebb
--- /dev/null
+++ b/libc/src/strings/ffsl.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ffsl --------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STRINGS_FFSL_H
+#define LLVM_LIBC_SRC_STRINGS_FFSL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int ffsl(long i);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STRINGS_FFSL_H

diff  --git a/libc/src/strings/ffsll.cpp b/libc/src/strings/ffsll.cpp
new file mode 100644
index 0000000000000..be16e81a54711
--- /dev/null
+++ b/libc/src/strings/ffsll.cpp
@@ -0,0 +1,20 @@
+//===-- Implementation of ffsll -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffsll.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/math_extras.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+LLVM_LIBC_FUNCTION(int, ffsll, (long long i)) {
+  return first_trailing_one(static_cast<unsigned long long>(i));
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/src/strings/ffsll.h b/libc/src/strings/ffsll.h
new file mode 100644
index 0000000000000..f059b8ab89b4e
--- /dev/null
+++ b/libc/src/strings/ffsll.h
@@ -0,0 +1,20 @@
+//===-- Implementation header for ffsll -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIBC_SRC_STRINGS_FFSLL_H
+#define LLVM_LIBC_SRC_STRINGS_FFSLL_H
+
+#include "src/__support/macros/config.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+int ffsll(long long i);
+
+} // namespace LIBC_NAMESPACE_DECL
+
+#endif // LLVM_LIBC_SRC_STRINGS_FFSLL_H

diff  --git a/libc/test/src/strings/CMakeLists.txt b/libc/test/src/strings/CMakeLists.txt
index 10f96b8531f68..baa22bb449c6c 100644
--- a/libc/test/src/strings/CMakeLists.txt
+++ b/libc/test/src/strings/CMakeLists.txt
@@ -12,6 +12,36 @@ add_libc_test(
     LibcMemoryHelpers
 )
 
+add_libc_test(
+  ffs_test
+  SUITE
+    libc-strings-tests
+  SRCS
+    ffs_test.cpp
+  DEPENDS
+    libc.src.strings.ffs
+)
+
+add_libc_test(
+  ffsl_test
+  SUITE
+    libc-strings-tests
+  SRCS
+    ffsl_test.cpp
+  DEPENDS
+    libc.src.strings.ffsl
+)
+
+add_libc_test(
+  ffsll_test
+  SUITE
+    libc-strings-tests
+  SRCS
+    ffsll_test.cpp
+  DEPENDS
+    libc.src.strings.ffsll
+)
+
 add_libc_test(
   index_test
   SUITE

diff  --git a/libc/test/src/strings/ffs_test.cpp b/libc/test/src/strings/ffs_test.cpp
new file mode 100644
index 0000000000000..17cd412b2df05
--- /dev/null
+++ b/libc/test/src/strings/ffs_test.cpp
@@ -0,0 +1,32 @@
+//===-- Unittests for ffs -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffs.h"
+
+#include "src/__support/macros/config.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+TEST(LlvmLibcFfsTest, SimpleFfs) {
+  ASSERT_EQ(ffs(0x00000000), 0);
+  ASSERT_EQ(ffs(0x00000001), 1);
+  ASSERT_EQ(ffs(0x00000020), 6);
+  ASSERT_EQ(ffs(0x00000400), 11);
+  ASSERT_EQ(ffs(0x00008000), 16);
+  ASSERT_EQ(ffs(0x00010000), 17);
+  ASSERT_EQ(ffs(0x00200000), 22);
+  ASSERT_EQ(ffs(0x04000000), 27);
+  ASSERT_EQ(ffs(0x80000000), 32);
+  ASSERT_EQ(ffs(0xfbe71), 1);
+  ASSERT_EQ(ffs(0xfbe70), 5);
+  ASSERT_EQ(ffs(0x10), 5);
+  ASSERT_EQ(ffs(0x100), 9);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/test/src/strings/ffsl_test.cpp b/libc/test/src/strings/ffsl_test.cpp
new file mode 100644
index 0000000000000..cf5c32f2fec6b
--- /dev/null
+++ b/libc/test/src/strings/ffsl_test.cpp
@@ -0,0 +1,42 @@
+//===-- Unittests for ffsl ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffsl.h"
+
+#include "src/__support/macros/config.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+TEST(LlvmLibcFfslTest, SimpleFfsl) {
+  ASSERT_EQ(ffsl(0x00000000L), 0);
+  ASSERT_EQ(ffsl(0x00000001L), 1);
+  ASSERT_EQ(ffsl(0x00000020L), 6);
+  ASSERT_EQ(ffsl(0x00000400L), 11);
+  ASSERT_EQ(ffsl(0x00008000L), 16);
+  ASSERT_EQ(ffsl(0x00010000L), 17);
+  ASSERT_EQ(ffsl(0x00200000L), 22);
+  ASSERT_EQ(ffsl(0x04000000L), 27);
+  ASSERT_EQ(ffsl(0x80000000L), 32);
+#ifdef __LP64__
+  ASSERT_EQ(ffsl(0x0000000100000000L), 33);
+  ASSERT_EQ(ffsl(0x0000002000000000L), 38);
+  ASSERT_EQ(ffsl(0x0000040000000000L), 43);
+  ASSERT_EQ(ffsl(0x0000800000000000L), 48);
+  ASSERT_EQ(ffsl(0x0001000000000000L), 49);
+  ASSERT_EQ(ffsl(0x0020000000000000L), 54);
+  ASSERT_EQ(ffsl(0x0400000000000000L), 59);
+  ASSERT_EQ(ffsl(0x8000000000000000L), 64);
+#endif
+  ASSERT_EQ(ffsl(0xfbe71L), 1);
+  ASSERT_EQ(ffsl(0xfbe70L), 5);
+  ASSERT_EQ(ffsl(0x10L), 5);
+  ASSERT_EQ(ffsl(0x100L), 9);
+}
+
+} // namespace LIBC_NAMESPACE_DECL

diff  --git a/libc/test/src/strings/ffsll_test.cpp b/libc/test/src/strings/ffsll_test.cpp
new file mode 100644
index 0000000000000..bdd7a2ed30f3c
--- /dev/null
+++ b/libc/test/src/strings/ffsll_test.cpp
@@ -0,0 +1,40 @@
+//===-- Unittests for ffsll -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "src/strings/ffsll.h"
+
+#include "src/__support/macros/config.h"
+#include "test/UnitTest/Test.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+TEST(LlvmLibcFfsllTest, SimpleFfsll) {
+  ASSERT_EQ(ffsll(0x0000000000000000LL), 0);
+  ASSERT_EQ(ffsll(0x0000000000000001LL), 1);
+  ASSERT_EQ(ffsll(0x0000000000000020LL), 6);
+  ASSERT_EQ(ffsll(0x0000000000000400LL), 11);
+  ASSERT_EQ(ffsll(0x0000000000008000LL), 16);
+  ASSERT_EQ(ffsll(0x0000000000010000LL), 17);
+  ASSERT_EQ(ffsll(0x0000000000200000LL), 22);
+  ASSERT_EQ(ffsll(0x0000000004000000LL), 27);
+  ASSERT_EQ(ffsll(0x0000000080000000LL), 32);
+  ASSERT_EQ(ffsll(0x0000000100000000LL), 33);
+  ASSERT_EQ(ffsll(0x0000002000000000LL), 38);
+  ASSERT_EQ(ffsll(0x0000040000000000LL), 43);
+  ASSERT_EQ(ffsll(0x0000800000000000LL), 48);
+  ASSERT_EQ(ffsll(0x0001000000000000LL), 49);
+  ASSERT_EQ(ffsll(0x0020000000000000LL), 54);
+  ASSERT_EQ(ffsll(0x0400000000000000LL), 59);
+  ASSERT_EQ(ffsll(0x8000000000000000LL), 64);
+  ASSERT_EQ(ffsll(0xfbe71LL), 1);
+  ASSERT_EQ(ffsll(0xfbe70LL), 5);
+  ASSERT_EQ(ffsll(0x10LL), 5);
+  ASSERT_EQ(ffsll(0x100LL), 9);
+}
+
+} // namespace LIBC_NAMESPACE_DECL


        


More information about the libc-commits mailing list