Skip to content

<__msvc_int128.hpp>: optimize _Signed128::operator* with a branchless multiply - #6406

Open
KKoishi_ (Koishi-Satori) wants to merge 1 commit into
microsoft:mainfrom
Koishi-Satori:main
Open

<__msvc_int128.hpp>: optimize _Signed128::operator* with a branchless multiply#6406
KKoishi_ (Koishi-Satori) wants to merge 1 commit into
microsoft:mainfrom
Koishi-Satori:main

Conversation

@Koishi-Satori

Copy link
Copy Markdown

Resolves issue #6405.

std::_Signed128::operator* in <__msvc_int128.hpp> perform sign-normalizes before multiplying, but it is unnecessary and will cause performance issue.

The low 128 bits of a two's-complement product equal the unsigned product, so the sign handling is unnecessary. I replaced it with the same computation _Base128::_Multiply already performs.

I've tried to implement a version without sign handling, the new version has same behavior and will not break any ABI. The new version without sign-normalizing is more faster than current version in <__msvc_int128.hpp>.

This PR also adds a signed128_mul benchmark comparing the new implementation against a faithful replica of the old one.

@Koishi-Satori
KKoishi_ (Koishi-Satori) requested a review from a team as a code owner August 18, 2026 09:20
Copilot AI balanced review requested due to automatic review settings August 18, 2026 09:20
@github-project-automation github-project-automation Bot moved this to Initial Review in STL Code Reviews Aug 18, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Optimizes _Signed128 multiplication by avoiding sign normalization and adds a microbenchmark to compare new vs. old behavior/performance.

Changes:

  • Replaced _Signed128::operator* implementation with a direct low-128-bit product using _UMul128 + cross terms.
  • Added a new Google Benchmark program to compare the new multiplication vs. the previous implementation.
  • Registered the new benchmark target in the benchmarks CMake list.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 5 comments.

File Description
stl/inc/__msvc_int128.hpp Reworks _Signed128 multiplication implementation to compute the low 128 bits directly.
benchmarks/src/signed128_mul.cpp Adds a benchmark comparing new vs. old signed-128 multiplication.
benchmarks/CMakeLists.txt Adds the new signed128_mul benchmark target.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread stl/inc/__msvc_int128.hpp
// The low 128 bits of a two's-complement product equal the unsigned product, so the sign normalization in the old
// implementation was unnecessary.
_Signed128 _Result;
_Result._Word[0] = _UMul128(_Left._Word[0], _Right._Word[0], _Result._Word[1]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. _UMul128 is unconditionally constexpr.

Comment thread stl/inc/__msvc_int128.hpp
Comment on lines +1375 to +1376
_Signed128 _Result;
_Result._Word[0] = _UMul128(_Left._Word[0], _Right._Word[0], _Result._Word[1]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. _UMul128 is unconditionally provided.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is wrong. _UMul128 is unconditionally provided.

Thanks, it seems like _UMul128 has been unconditionally available since #6356

#include <array>
#include <cstdint>
#include <random>
#include <utility>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll also suggest including <vector>. But one should be also aware that the name _Signed128 is MSVC STL-specific if the name is already in the sight.

Comment on lines +25 to +26
vector<pair<_Signed128, _Signed128>> init_test_set() {
vector<pair<_Signed128, _Signed128>> vec(1'000'000);
Comment on lines +15 to +17
bool _negative = false;
_Left._Strip_negative(_negative);
_Right._Strip_negative(_negative);
@Koishi-Satori

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Comment thread stl/inc/__msvc_int128.hpp
_Result = -_Result;
}
// The low 128 bits of a two's-complement product equal the unsigned product, so the sign normalization in the old
// implementation was unnecessary.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a huge fan of comments about old versions of the code. That's what commit messages and git blame is for.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Initial Review

Development

Successfully merging this pull request may close these issues.

4 participants