llvm/llvm-project

[C++20] [Modules] Duplicate-mangled-name codegen error for SSE intrinsics when two module partitions both `#include <emmintrin.h>` in their global module fragment

Open

#195661 opened on May 4, 2026

View on GitHub
 (11 comments) (0 reactions) (0 assignees)C++ (26,378 stars) (10,782 forks)batch import
clang:headersclang:moduleshelp wanted

Description

Compiler

$ clang++-21 --version
Ubuntu clang version 21.1.8 (++20251221032922+2078da43e25a-1~exp1~20251221153059.70)
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/lib/llvm-21/bin

Problem

Got compile error: error: definition with same mangled name '_ZL13_mm_set_epi16ssssssss' as another definition when two C++20 module partitions of the same primary module each #include <emmintrin.h> in their global module fragment and each contain an inline function whose body calls the same SSE intrinsic (e.g. _mm_set_epi16). A consumer TU that imports the primary module fails to compile.

Reproduce

a.cppm:

module;
#include <emmintrin.h>
export module mymod:a;

export inline int a_make() noexcept {
    __m128i x = _mm_set_epi16(0, 1, 2, 3, 4, 5, 6, 7);
    alignas(16) short out[8];
    _mm_store_si128(reinterpret_cast<__m128i*>(out), x);
    return out[0];
}

b.cppm:

module;
#include <emmintrin.h>
export module mymod:b;

export inline int b_make() noexcept {
    __m128i x = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0);
    alignas(16) short out[8];
    _mm_store_si128(reinterpret_cast<__m128i*>(out), x);
    return out[0];
}

m.cppm:

export module mymod;
export import :a;
export import :b;

main.cpp:

import mymod;

int main() {
    return a_make() + b_make();
}

build.sh:

#!/usr/bin/env bash
set -euo pipefail
CXX=clang++-21
FLAGS="-std=c++20 -msse2"

$CXX $FLAGS -x c++-module --precompile -o mymod-a.pcm a.cppm
$CXX $FLAGS -x c++-module --precompile -o mymod-b.pcm b.cppm
$CXX $FLAGS -fmodule-file=mymod:a=mymod-a.pcm -fmodule-file=mymod:b=mymod-b.pcm \
    -x c++-module --precompile -o mymod.pcm m.cppm
$CXX $FLAGS -fmodule-file=mymod=mymod.pcm \
    -fmodule-file=mymod:a=mymod-a.pcm -fmodule-file=mymod:b=mymod-b.pcm \
    -c main.cpp -o main.o

Output

In module 'mymod' imported from main.cpp:1:
In module 'mymod:b' imported from m.cppm:3:
/usr/lib/llvm-21/lib/clang/21/include/emmintrin.h:3605:1: error: definition with same mangled name '_ZL13_mm_set_epi16ssssssss' as another definition
 3605 | _mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3,
      | ^
/usr/lib/llvm-21/lib/clang/21/include/emmintrin.h:3605:1: note: previous definition is here
 3605 | _mm_set_epi16(short __w7, short __w6, short __w5, short __w4, short __w3,
      | ^
1 error generated.

In our larger codebase the same pattern produces three errors at once (_mm_set_epi8, _mm_set1_epi8, _mm_add_epi8) — any SSE intrinsic used identically in both partition bodies surfaces.

What is NOT required to trigger

I bisected the trigger by adding/removing flags and structural elements against the minimal four files above. None of these affect the result; the bug fires either way:

  • -fno-exceptions, -fno-rtti, -pthread
  • -march=native, -O3, -DNDEBUG
  • -std=c++23, -std=c++26, -std=gnu++26
  • --gcc-toolchain=… (libstdc++ from GCC)
  • import std; in the partitions or the consumer
  • A shared :detail partition imported by both partitions
  • Concept constraints on the inline functions
  • Templates instead of plain inline functions
  • Whether the intrinsic header is <emmintrin.h> or <immintrin.h>

What IS required: each partition must contain at least one inline function whose body calls the same intrinsic. Empty partitions (just module; #include <emmintrin.h>; export module mymod:a;) compile cleanly.

Expected behavior

Per [basic.link]p17 and Clang's own documentation, declarations in the global module fragment have internal linkage and should be private to each TU. Two partitions independently including <emmintrin.h> in their GMFs should each have their own internal-linkage copy of the intrinsic definitions; codegen should not reject them as duplicates.

Actual behavior

Codegen emits two definitions of _mm_set_epi16 with the same mangled internal-linkage name and rejects the consumer TU compile.

Workaround we adopted

Restructure so that only one partition #includes the intrinsic header. The other partition's SSE-using helpers are moved into the first partition and exported. This avoids the dual-emission. [[gnu::noinline]] does NOT help — the duplicate fires on the static-inline functions from <emmintrin.h> itself, not on user code.

Related issues

  • #98021 / #104701 — fixed a related lookup-time issue (intrinsics not found in modules). Different code path; that fix did not address the codegen-level duplicate-mangling.
  • #90259 — anonymous-namespace internal-linkage variables conflicting across partitions. Same general area but a different surface.
  • #53232 / Bugzilla #33924 — same error message text, but for lambdas in modules, not intrinsic headers.

Contributor guide