JDK-8031743 : C2: loadI2L_immI broken for negative memory values
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: hs25
  • Priority: P1
  • Status: Closed
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-01-14
  • Updated: 2014-10-15
  • Resolved: 2014-01-23
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8 JDK 9 Other
7u60Fixed 8Fixed 9Fixed hs25Fixed
instruct loadI2L_immI(iRegL dst, memory mem, immI mask, iRegI tmp) %{
  match(Set dst (ConvI2L (AndI (LoadI mem) mask)));

From inspection, it appears that this rule (on all platforms) only works if the result of the AndI
doesn't need to be sign-extended (>= 0).  My first attempt at a test program didn't work.  For
some reason when using an array, C2 only takes a fast path if the value is positive:

    static long foo(int[] x) {
        return x[0] & 0xfffffffe;

However, using a field instead doesn't have that problem.

% cat a.java
public class a {
    static int x;
    static long foo() {
        return x & 0xfffffffe;

    public static void main(String[] args) {
        x = -1;
        long l = 0;
        for (int i = 0; i < 100000; ++i) {
            l = foo();
% ./bin/java -Xint a
% ./bin/java -XX:-TieredCompilation -server a

7u60-critical-justification: A related issue to JDK-8032207 that the OpsCenter team is having. Fixing both issues is needed for a proper fix.

I'll push it today, I was waiting to check the nightlies in 9 first.

Release team: Approved for fixing

ILW=HHH=P1 Impact: Incorrect result (which is way worse than a crash), the test case is very simple. Likelihood: This reproduces all the time. Workaround: None Justification: This affects any code that does a bitwise AND with a integer loaded from memory and constant mask value with conversion to a long. The optimization transforms (ConvI2L (AndI (LoadI mem) mask)) to (AndI (LoadUI2L (mem) mask). If the mask constant has the highest bit set and the value is also negative the optimization behaves incorrectly and produces wrong result because the value is not sign-extended. The fix is low risk since it conservatively doesn't introduce any new code generation but rather restricts when the existing optimizations are being applied.

Suggest fix: http://cr.openjdk.java.net/~iveresov/8031743/webrev.00/

The bug exists on all platforms. x86, x64, sparc, arm

The optimization is incorrect, it would work only with mask <= 0x7fffffff. Predicating it off based on that should do the trick.

Uh-oh, that's extremely bad! This should be a P1.