# optimized-routines: hand-tuned library functions for Arm processors

> ARM-software/optimized-routines collects assembly and C implementations of common library functions written for Arm architectures, split into math, string, networking and floating-point subprojects with a plain make build. It is a good fit when compiler builtins or the system libm are not good enough, and a poor fit for anything that needs a stable upstreaming path or a wide range of architectures.

**ARM-software/optimized-routines** — Optimized implementations of various library functions for ARM architecture processors

- Repository: https://github.com/ARM-software/optimized-routines
- Stars: 718 · Forks: 126
- Language: C
- License: NOASSERTION
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/arm-software-optimized-routines

## A collection of routines, not a drop-in libc

This repository is Arm's collection of optimized implementations of library functions, written in C and assembly for Arm processors. The stated audience covers embedded systems, mobile devices and high-performance computing, and the claim is that the routines are designed to maximize efficiency and performance on Arm platforms.

What it is not is a complete C library. There is no stdio, no malloc, no process management and no system call layer. It is a set of specific function implementations that sit alongside, or in place of, individual routines from a system library. The scope is visible in the four subproject directories: fp for floating-point basic arithmetic, math for elementary math, string for string routines and networking for networking functions.

That framing matters for expectations. Nobody links this and gets a faster system. A team links it, or copies the relevant source file, because a specific function such as a particular string routine or an elementary math operation shows up in a profile and the system implementation is not fast enough on the Arm core they target.

The project also states that Arm is a registered trademark of Arm Limited, which is the usual way an Arm-authored repository handles the name, and the copyright in the Makefile header is Arm Limited, so this is first-party work rather than a community collection. The primary language is C, and the .S assembly files in the tree are compiled by the same make rules as the .c files.

## Four subprojects, each with its own Dir.mk and its own maintainers

The build system is a plain make setup, and the structure of the repository explains how it works. The top-level Makefile lists the subprojects in one variable, SUBS = math string networking fp, and then includes a per-subproject make fragment for each of them with a foreach over that list, pulling in $(srcdir)/$(sub)/Dir.mk.

That fragment per subproject is the contract, and the Makefile spells out the required targets: a subproject named foo must provide all-foo, check-foo, clean-foo and install-foo, plus a foo-files variable listing the built outputs, all of which live in build/. The comment in the Makefile makes clear that the per-subproject variables come either from foo/Dir.mk or from config.mk.

The build output directory is created by the build process itself, which is why the repository structure section of the project description lists build/ alongside the four source directories. The make rules compile both .c and .S sources into build/%.o and build/%.os, and objects destined for a shared library get the -fPIC flag added on top of the common flags.

The governance is as federated as the build. Each subdirectory may have its own README.md with specific contribution requirements, each subdirectory has its own maintainers, and MAINTAINERS.md at the root lists who to contact. CODEOWNERS is present as well, which is the GitHub mechanism for routing review requests to the right subproject owner.

## Building and testing with make, one subproject or all of them

The build starts from a clone and a configuration file. The documented steps are:

```bash
   git clone https://github.com/ARM-software/optimized-routines.git
   cd optimized-routines
```

Then you copy the distribution configuration and edit it:

```bash
   cp config.mk.dist config.mk
   # Edit config.mk as needed
```

And build and test:

```bash
   make
   make check
```

The compile flags are visible in the Makefile rather than hidden in a wrapper script. Both the host and target compilers are set to -std=c99 -O2, with CFLAGS_ALL adding an include path for build/include, and the host compiler defaults to cc but can be overridden with HOST_CC. The tests are linked with TEST_BIN_FLAGS = -static, so the check binaries are statically linked, which matters for cross-testing where the target's dynamic loader may not be present on the build machine.

The subproject targets follow the same pattern with a suffix, and the project documents them as:

```bash
   make all-<sub>
   make check-<sub>
   make prefix=/path/to/install install-<sub>
```

The Makefile also notes that instead of building subprojects one at a time, the config.mk file can be updated to specify a list of subprojects, which is the way to configure the build once rather than typing suffixed targets.

## Installing to /usr by default, and crossing to another target

The install step is one make target with a prefix variable, and the default is worth knowing before you run it:

```bash
   make prefix=/path/to/install install
```

The Makefile sets prefix = /usr, deriving bindir, libdir and includedir from it, so a plain make install writes into the system prefix. Passing prefix is how you stage into a different tree, which is what a packaging step wants.

Cross-building works the same way, with two settings in config.mk. Setting CROSS_COMPILE prefixes the archiver and the ranlib tool, since AR and RANLIB are defined as $(CROSS_COMPILE)ar and $(CROSS_COMPILE)ranlib, and the compiler is taken from the usual CC variable. For testing the cross-built binaries you also define EMULATOR, and the project description gives qemu-user or remote access to a target machine as the examples. The config.mk.dist file is where those settings are demonstrated.

One detail in the Makefile shows how the project is cautious about host versus target. The host compiler flags are separate variables from the target ones, and the comment above the library dependency list notes that the math dependencies, which include -lm, -lc, -lmpfr, -lgmp and -lmpc, can be adjusted in the config file if necessary, for instance on Msys.

The Makefile header also states that it requires GNU make, which is consistent with the foreach and eval constructs used to include the subproject fragments.

## Dual licensed, with a contributor agreement for upstreaming

The licensing arrangement is the first thing to read. The project is dual licensed, letting you choose between the MIT License and the Apache License 2.0 with LLVM Exceptions, with the full terms in the LICENSE file. The Makefile header records the same choice as a single SPDX identifier, MIT OR Apache-2.0 WITH LLVM-exception, which is the standard way to express a dual licence that the toolchain understands.

For a project that wants to be upstreamed elsewhere, the contribution path has a gate. Contributors are asked to sign a Contributor Assignment Agreement, with the instructions in contributor-agreement.pdf, and the stated reason is that this step is necessary to allow upstreaming code to projects that require copyright assignment. The general guidelines live in CONTRIBUTING.md, and the per-subproject README files add their own requirements on top.

That is the deal you are accepting by contributing rather than just consuming. You can use the code under either licence without signing anything, and the licences are permissive enough for commercial use. If you intend to send a patch upstream into a project that demands assignment, the CLA is the price of admission, and the per-subproject maintainers decide whether to accept a patch.

The release cadence is regular and the naming is predictable. Releases are tagged biannually as vYY.MM, with v26.07 dated 2026-07-29, v26.01 dated 2026-01-12 and v25.07 dated 2025-07-14, which is a clean twice-a-year pattern at the start of each half. The repository is not archived and the last push was on 2026-10-16, so the master branch is ahead of the newest tag.

## Where the collection is the wrong answer

The first limitation is that there are no published performance figures. The project ships implementations, a build system and a test suite, but the documentation contains no benchmarks, no instruction counts and no comparison against a system libm or a compiler builtin. That means every adoption starts with the same work: profile your own workload, replace one function, measure it. For a team that cannot instrument its hot path, this is a library with no measurable justification.

The second is that the routines target Arm processors specifically, and the Makefile compiles them with the host and target flags set to the same -std=c99 -O2 baseline. There is no x86 path and no generic C fallback path in the visible build, so the library is not a portable optimisation. Any codebase that must build on more than one architecture has to keep the system library available and select at build time, which is more integration work than dropping in a single implementation.

The third is the granularity of the payoff. These are individual functions, so a typical adoption is a hand-off of one routine in a hot loop, not a library-level speedup. A code review now has to cover assembly as well as C, and the copyright and licensing of a copied file needs to be tracked with the rest of the project.

The fourth is the upstreaming requirement. The CLA is not a barrier for consumption, but it does mean the project is structured for code to be moved into other codebases, and the per-subproject maintainer model means acceptance of a patch is decided by whoever owns that directory. If your goal is a routine that will be maintained in one place by many people, this repository is set up for that already, which is the case in its favour.

## Conclusion

optimized-routines suits a team writing Arm-targeted C that has measured a hot path where the system library or the compiler's builtins are the bottleneck, and the per-subproject build targets make it easy to take only the string or math subproject rather than the whole collection. It is the wrong choice for a portable codebase, for a project that needs the routines to be upstreamed into another project under a copyright assignment process you do not want, or for a team expecting a general performance win from swapping in a library. Before adopting it, run make and make check on your target, then measure the specific routine you intend to replace against your current libc, because the project publishes implementations and a build system but no benchmark numbers, and the last push was on 2026-10-16 with the newest release tagged v26.07 on 2026-07-29.

## FAQ

### How do I build the Arm optimized-routines library?

Clone the repository, copy config.mk.dist to config.mk and edit it, then run make to build and make check to run the tests. Subprojects can be built individually with targets such as make all-<sub> and make check-<sub>.

### Which subprojects does optimized-routines contain?

Four: fp for floating-point basic arithmetic, math for elementary math, string for string routines and networking for networking functions, as listed in the Makefile SUBS variable.

### How do I cross-build optimized-routines for another Arm target?

Set CROSS_COMPILE in config.mk so the archiver and ranlib use the cross toolchain, and define EMULATOR for cross-testing, for example with qemu-user or a remote target machine. Examples are provided in config.mk.dist.

### What licence applies to optimized-routines?

The project is dual licensed, letting you choose between the MIT License and the Apache License 2.0 with LLVM Exceptions, and the full terms are in the LICENSE file.

### How often are optimized-routines releases published?

Regularly, twice a year, tagged as vYY.MM. The latest release is v26.07, dated 2026-07-29, and the last push to the repository was on 2026-10-16.

## Sources

- [ARM-software/optimized-routines on GitHub](https://github.com/ARM-software/optimized-routines)
- [Issues](https://github.com/ARM-software/optimized-routines/issues)
- [README](https://github.com/ARM-software/optimized-routines/blob/master/README.md)
- [Releases](https://github.com/ARM-software/optimized-routines/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/arm-software-optimized-routines
