mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-10-29 02:17:15 +08:00
Clang generated ~35% more instructions per float than GCC on identical code (canada.txt, 64-bit: 276 vs 200 i/f on a Xeon Gold 6548N). Two causes, confirmed with exact instruction traces: 1. Clang declines to inline the parser (from_chars_caller<T>::call) into its callers, so parse_options stays a runtime value and every format flag is re-tested on every conversion: javascript, skip_white_space, allow_leading_plus, fixed/scientific, the decimal point, the JSON dispatch. GCC inlines the whole parser into each call site, where chars_format::general is a constant, and all of it folds away. Fix: from_chars dispatches chars_format::general to a from_chars_fixed_format<T, UC, Fmt> instantiation, so the format is a compile-time constant inside the parser body whether or not the user's call is inlined. The call forwarder gets fastfloat_clang_really_inline so that it folds into that instantiation. 2. Clang if-converts the rare over/underflow fix-ups at the end of compute_float and the result_out_of_range test into cmov chains that every conversion executes. Marking them fastfloat_clang_unlikely keeps them as never-taken branches. Both are applied under clang only, and GCC's generated code is identical to before (verified on the object code). That is on purpose: forcing always_inline on from_chars, or even on the trivial call forwarder, regressed GCC by up to 14% on mesh.txt by changing its inlining order; dispatching to the fixed-format instantiation made it stop inlining into the loop; and the unlikely hints alone cost it 2-6% on mesh.txt by reordering blocks (GCC already emits branches there). realbenchmark, cycles per float, 5 interleaved rounds, medians: clang 21, Xeon Gold 6548N before after canada.txt ASCII (64) 49.7 44.6 -10% canada.txt UTF-16 (64) 57.4 52.0 -9% mesh.txt ASCII (64) 26.5 22.4 -16% mesh.txt UTF-16 (64) 28.1 24.0 -15% (32-bit: -8% to -14%) gcc 14, same machine: generated code unchanged. Apple clang 17, arm64: +3% to +18% Mfloat/s. |
||
|---|---|---|
| .. | ||
| fast_float | ||