/*
 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */
package org.graalvm.compiler.replacements.test;

import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;

import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.core.test.GraalCompilerTest;
import org.graalvm.compiler.nodes.ReturnNode;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
import org.graalvm.compiler.nodes.ValueNode;
import org.graalvm.compiler.phases.common.CanonicalizerPhase;
import org.graalvm.compiler.phases.common.inlining.InliningPhase;
import org.graalvm.compiler.phases.tiers.HighTierContext;
import org.graalvm.compiler.replacements.nodes.BitScanReverseNode;

import jdk.vm.ci.amd64.AMD64;
import jdk.vm.ci.code.Architecture;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.sparc.SPARC;

public class BitOpNodesTest extends GraalCompilerTest {

    private static final int INT_CONSTANT_1 = 0x80100010;
    private static final int INT_CONSTANT_2 = 0x00011110;
    private static final int INT_CONSTANT_3 = 0x00000000;

    private static final long LONG_CONSTANT_1 = 0x8000000000100010L;
    private static final long LONG_CONSTANT_2 = 0x0000000000011110L;
    private static final long LONG_CONSTANT_3 = 0x0000000000000000L;

    public static long dummyField;

    /*
     * Tests for BitCountNode canonicalizations.
     */

    public static int bitCountIntConstantSnippet() {
        return Integer.bitCount(INT_CONSTANT_1) + Integer.bitCount(INT_CONSTANT_2) + Integer.bitCount(INT_CONSTANT_3);
    }

    @Test
    public void testBitCountIntConstant() {
        ValueNode result = parseAndInline("bitCountIntConstantSnippet");
        Assert.assertEquals(7, result.asJavaConstant().asInt());
    }

    public static int bitCountLongConstantSnippet() {
        return Long.bitCount(LONG_CONSTANT_1) + Long.bitCount(LONG_CONSTANT_2) + Long.bitCount(LONG_CONSTANT_3);
    }

    public static int bitCountIntSnippet(int v) {
        return Integer.bitCount(v & 0xFFFFFF | 0xFF);
    }

    @Test
    public void testBitCountInt() {
        Architecture arch = getBackend().getTarget().arch;
        boolean isAmd64WithPopCount = arch instanceof AMD64 && ((AMD64) arch).getFeatures().contains(AMD64.CPUFeature.POPCNT);
        boolean isSparc = arch instanceof SPARC;
        Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc);
        ValueNode result = parseAndInline("bitCountIntSnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 24), result.stamp());
    }

    public static int bitCountIntEmptySnippet(int v) {
        return Integer.bitCount(v & 0xFFFFFF);
    }

    @Test
    public void testBitCountIntEmpty() {
        Architecture arch = getBackend().getTarget().arch;
        boolean isAmd64WithPopCount = arch instanceof AMD64 && ((AMD64) arch).getFeatures().contains(AMD64.CPUFeature.POPCNT);
        boolean isSparc = arch instanceof SPARC;
        Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc);
        ValueNode result = parseAndInline("bitCountIntEmptySnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 24), result.stamp());
    }

    @Test
    public void testBitCountLongConstant() {
        ValueNode result = parseAndInline("bitCountLongConstantSnippet");
        Assert.assertEquals(7, result.asJavaConstant().asInt());
    }

    public static int bitCountLongSnippet(long v) {
        return Long.bitCount(v & 0xFFFFFFFFFFL | 0xFFL);
    }

    @Test
    public void testBitCountLong() {
        Architecture arch = getBackend().getTarget().arch;
        boolean isAmd64WithPopCount = arch instanceof AMD64 && ((AMD64) arch).getFeatures().contains(AMD64.CPUFeature.POPCNT);
        boolean isSparc = arch instanceof SPARC;
        Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc);
        ValueNode result = parseAndInline("bitCountLongSnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 8, 40), result.stamp());
    }

    public static int bitCountLongEmptySnippet(long v) {
        return Long.bitCount(v & 0xFFFFFFFFFFL);
    }

    @Test
    public void testBitCountLongEmpty() {
        Architecture arch = getBackend().getTarget().arch;
        boolean isAmd64WithPopCount = arch instanceof AMD64 && ((AMD64) arch).getFeatures().contains(AMD64.CPUFeature.POPCNT);
        boolean isSparc = arch instanceof SPARC;
        Assume.assumeTrue("Only works on hardware with popcnt at the moment", isAmd64WithPopCount || isSparc);
        ValueNode result = parseAndInline("bitCountLongEmptySnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 0, 40), result.stamp());
    }

    /*
     * Tests for BitScanForwardNode
     */

    public static int scanForwardIntConstantSnippet() {
        return Integer.numberOfTrailingZeros(INT_CONSTANT_1) + Integer.numberOfTrailingZeros(INT_CONSTANT_2) + Integer.numberOfTrailingZeros(INT_CONSTANT_3);
    }

    @Test
    public void testScanForwardIntConstant() {
        ValueNode result = parseAndInline("scanForwardIntConstantSnippet");
        Assert.assertEquals(40, result.asJavaConstant().asInt());
    }

    public static int scanForwardIntSnippet(int v) {
        return Integer.numberOfTrailingZeros(v & 0xFFF0 | 0xFF00);
    }

    @Test
    public void testScanForwardInt() {
        ValueNode result = parseAndInline("scanForwardIntSnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 4, 8), result.stamp());
    }

    public static int scanForwardLongConstantSnippet() {
        return Long.numberOfTrailingZeros(LONG_CONSTANT_1) + Long.numberOfTrailingZeros(LONG_CONSTANT_2) + Long.numberOfTrailingZeros(LONG_CONSTANT_3);
    }

    @Test
    public void testScanForwardLongConstant() {
        ValueNode result = parseAndInline("scanForwardLongConstantSnippet");
        Assert.assertEquals(72, result.asJavaConstant().asInt());
    }

    public static int scanForwardLongSnippet(long v) {
        return Long.numberOfTrailingZeros(v & 0xFFFF000000L | 0xFF00000000L);
    }

    @Test
    public void testScanForwardLong() {
        ValueNode result = parseAndInline("scanForwardLongSnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 32), result.stamp());
    }

    public static int scanForwardLongEmptySnippet(long v) {
        int result = Long.numberOfTrailingZeros(v & 0xFFFF000000L);
        dummyField = result;
        return result;
    }

    @Test
    public void testScanForwardLongEmpty() {
        ValueNode result = parseAndInline("scanForwardLongEmptySnippet");
        Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp());
    }

    /*
     * Tests for BitScanReverseNode
     */

    public static int scanReverseIntConstantSnippet() {
        return Integer.numberOfLeadingZeros(INT_CONSTANT_1) + Integer.numberOfLeadingZeros(INT_CONSTANT_2) + Integer.numberOfLeadingZeros(INT_CONSTANT_3);
    }

    @Test
    public void testScanReverseIntConstant() {
        ValueNode result = parseAndInline("scanReverseIntConstantSnippet");
        Assert.assertEquals(47, result.asJavaConstant().asInt());
    }

    public static int scanReverseIntSnippet(int v) {
        return Integer.numberOfLeadingZeros(v & 0xFFF0 | 0xFF0);
    }

    @Test
    public void testScanReverseInt() {
        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
        ValueNode result = parseAndInline("scanReverseIntSnippet", BitScanReverseNode.class);
        if (result != null) {
            Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 16, 20), result.stamp());
        }
    }

    public static int scanReverseLongConstantSnippet() {
        return Long.numberOfLeadingZeros(LONG_CONSTANT_1) + Long.numberOfLeadingZeros(LONG_CONSTANT_2) + Long.numberOfLeadingZeros(LONG_CONSTANT_3);
    }

    @Test
    public void testScanReverseLongConstant() {
        ValueNode result = parseAndInline("scanReverseLongConstantSnippet");
        Assert.assertEquals(111, result.asJavaConstant().asInt());
    }

    public static int scanReverseLongSnippet(long v) {
        int result = Long.numberOfLeadingZeros(v & 0xFFF0);
        dummyField = result;
        return result;
    }

    @Test
    public void testScanReverseLong() {
        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
        ValueNode result = parseAndInline("scanReverseLongSnippet", BitScanReverseNode.class);
        if (result != null) {
            Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 48, 64), result.stamp());
        }
    }

    public static int scanReverseLongEmptySnippet(long v) {
        int result = Long.numberOfLeadingZeros(v & 0xFFFF000000L);
        dummyField = result;
        return result;
    }

    @Test
    public void testScanReverseLongEmpty() {
        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
        ValueNode result = parseAndInline("scanReverseLongEmptySnippet", BitScanReverseNode.class);
        if (result != null) {
            Assert.assertEquals(StampFactory.forInteger(JavaKind.Int, 24, 64), result.stamp());
        }
    }

    private ValueNode parseAndInline(String name) {
        return parseAndInline(name, null);
    }

    /**
     * Parse and optimize {@code name}. If {@code expectedClass} is non-null and a node of that type
     * isn't found simply return null. Otherwise return the node returned by the graph.
     *
     * @param name
     * @param expectedClass
     * @return the returned value or null if {@code expectedClass} is not found in the graph.
     */
    private ValueNode parseAndInline(String name, Class<? extends ValueNode> expectedClass) {
        StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
        HighTierContext context = getDefaultHighTierContext();
        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
        canonicalizer.apply(graph, context);
        new InliningPhase(canonicalizer).apply(graph, context);
        canonicalizer.apply(graph, context);
        Assert.assertEquals(1, graph.getNodes(ReturnNode.TYPE).count());
        if (expectedClass != null) {
            if (graph.getNodes().filter(expectedClass).count() == 0) {
                return null;
            }
        }
        return graph.getNodes(ReturnNode.TYPE).first().result();
    }
}
