On Mon, 10 Aug 2026 15:13:10 GMT, Andrew Haley <[email protected]> wrote:
>> Unfortunately this change would reintroduce cross-call and dead-code >> elimination with C2, while still biasing against opaqueness with intrinsics. >> I've spent the past week going through different designs to keep the >> benchmark relatively close to the original, like you have, with the goal of >> preventing optimizations. For better or for worse, C2 is too good at >> identifying targets and will quite elegantly remove any code that doesn't >> contribute to said target. > > Can you explain what is happening here? I wonder if this may not be a problem > with the benchmark, but with the `conditionalSet()` code itself. > > You talk about "cross-call" optimization, but what is really happening? If C2 > really can see that `conditionalSet(0)` doesn't need to be executed, or that > repeated invocations of `conditionalSet` don't do anything, then that is a > problem with the crypto code. If it is the latter, then it needs to be fixed > in the crypto code, for security reasons. The existing arbitrary `conditionalSet()` benchmark is not necessarily indicative of susceptibility to a side-channel attack in production code due to a number reasons, including the use of non-constant input arguments and the dependencies of intermediate operations due to adding between successive `lookup()` calls when calculating point multiplication, as an example. As a result, the problem being addressed is a benchmark issue, as the current conditional set benchmark is nothing like what is utilized in EC production operations. This is why I lifted the existing `lookup()` logic as a form of measuring conditional set performance, which better emulates a production state. The above code uses flag arguments that are incorrect which would generate invalid bit masks, subsequently corrupting the associated limbs during conditional sets. Even with non-binary flags, because the pair-wise assignments use the same input, C2 could perform a bitwise OR of the two masks and use the resulting mask only once for the conditional assignment. As a result C2 may i) not need to reload registers for the second call, ii) not need to store the result to memory from the first call when the second call would overwrite the first, and iii) keep the intermediate limbs in registers. Correcting the flag arguments to binary would make it even easier for inlining as it could eliminate the the first call if the second call has a 1 flag. In aggregate, this likely contributes to the 18% drop in performance with intrinsics when using the above code, compared to a 52% performance gain when using intrinsics with the originally proposed solution. The goal is to try to reproduce the same shape that we see in production EC operations. ------------- PR Review Comment: https://git.openjdk.org/jdk/pull/32047#discussion_r3755877190
