Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GR-53019] Potential new optimisation for IntegerEqualsNode #8680

Open
default-jamc opened this issue Apr 2, 2024 · 0 comments
Open

[GR-53019] Potential new optimisation for IntegerEqualsNode #8680

default-jamc opened this issue Apr 2, 2024 · 0 comments
Assignees

Comments

@default-jamc
Copy link

Overview

Hi,

I noticed that there may be another optimisation that can be added to IntegerEqualsNode, a variant of (#6429). Specifically, comparing the Xor of two values against the Not of one of them is equivalent to comparing the other value to -1.

 ((x ^ y) == (~x)) -> (y == -1)

 Commutativity permutations:
 ((y ^ x) == (~x)) -> (y == -1)
 ((~x) == (x ^ y)) -> (y == -1)
 ((~x) == (y ^ x)) -> (y == -1)

This optimisation has also been formally verified in an interactive theorem prover (Isabelle/HOL).

Sample Program

To determine whether this optimisation provided a speed-up, I used the same sample program as in (#8679) but changed the unoptimised and optimised lines to:

condition = ((m ^ s) == ~m) // Unoptimised
condition = (s == -1)       // Optimised

The optimised version is around 35% faster than the unoptimised version, yielding runtimes of approximately 1.29s and 1.98s, respectively.

Unit Test

I've also written a JUnit test to check whether this optimisation is applied:

package jdk.graal.compiler.core.test;

import jdk.graal.compiler.nodes.StructuredGraph;
import jdk.graal.compiler.nodes.calc.IntegerEqualsNode;
import jdk.graal.compiler.nodes.calc.NotNode;
import jdk.graal.compiler.nodes.calc.XorNode;
import org.junit.Test;

public class NewOptimizationTest extends GraalCompilerTest {

    // ((x ^ y) == ~x) |-> (y == -1)
    public static boolean xorNotNeutral1(int x, int y) {
        return ((x ^ y) == ~x);
    }

    public static boolean xorNotNeutral2(int x, int y) {
        return ((y ^ x) == ~x);
    }

    public static boolean xorNotNeutral3(int x, int y) {
        return (~x == (x ^ y));
    }

    public static boolean xorNotNeutral4(int x, int y) {
        return (~x == (y ^ x));
    }

    private void checkNodes(String methodName) {
        StructuredGraph graph = parseForCompile(getResolvedJavaMethod(methodName));

        System.out.println("(Before) Nodes in graph: ");
        System.out.println("IntegerEquals: " + graph.getNodes().filter(IntegerEqualsNode.class).count());
        System.out.println("Xor: " + graph.getNodes().filter(XorNode.class).count());
        System.out.println("Not: " + graph.getNodes().filter(NotNode.class).count());

        createCanonicalizerPhase().apply(graph, getProviders());

        System.out.println("(After) Nodes in graph: ");
        System.out.println("IntegerEquals: " + graph.getNodes().filter(IntegerEqualsNode.class).count());
        System.out.println("Xor: " + graph.getNodes().filter(XorNode.class).count());
        System.out.println("Not: " + graph.getNodes().filter(NotNode.class).count());

        // If there are no XorNodes or NotNodes in the graph, the optimisation was applied
        assertTrue(graph.getNodes().filter(XorNode.class).count() == 0);
        assertTrue(graph.getNodes().filter(NotNode.class).count() == 0);
    }

    @Test
    public void testOptimization1() {
        checkNodes("xorNotNeutral1");
    }

    @Test
    public void testOptimization2() {
        checkNodes("xorNotNeutral2");
    }

    @Test
    public void testOptimization3() {
        checkNodes("xorNotNeutral3");
    }

    @Test
    public void testOptimization4() {
        checkNodes("xorNotNeutral4");
    }
}

Running this test produces the following output:

MxJUnitCore
JUnit version 4.12
.(Before) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
(After) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
E
testOptimization1(jdk.graal.compiler.core.test.NewOptimizationTest)
java.lang.AssertionError
	...
.(Before) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
(After) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
E
testOptimization2(jdk.graal.compiler.core.test.NewOptimizationTest)
java.lang.AssertionError
	...
.(Before) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
(After) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
E
testOptimization3(jdk.graal.compiler.core.test.NewOptimizationTest)
java.lang.AssertionError
	...
.(Before) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
(After) Nodes in graph: 
IntegerEquals: 1
Xor: 1
Not: 1
E
testOptimization4(jdk.graal.compiler.core.test.NewOptimizationTest)
java.lang.AssertionError
	...

Time: 0.673
There were 4 failures:
1) jdk.graal.compiler.core.test.NewOptimizationTest#testOptimization1
java.lang.AssertionError
	...
2) jdk.graal.compiler.core.test.NewOptimizationTest#testOptimization2
java.lang.AssertionError
	...
3) jdk.graal.compiler.core.test.NewOptimizationTest#testOptimization3
java.lang.AssertionError
	...
4) jdk.graal.compiler.core.test.NewOptimizationTest#testOptimization4
java.lang.AssertionError
	...

FAILURES!!!
Tests run: 4,  Failures: 4
...
@oubidar-Abderrahim oubidar-Abderrahim changed the title Potential new optimisation for IntegerEqualsNode [GR-53019] Potential new optimisation for IntegerEqualsNode Apr 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants