001/*
002 * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.
008 *
009 * This code is distributed in the hope that it will be useful, but WITHOUT
010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
011 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
012 * version 2 for more details (a copy is included in the LICENSE file that
013 * accompanied this code).
014 *
015 * You should have received a copy of the GNU General Public License version
016 * 2 along with this work; if not, write to the Free Software Foundation,
017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
018 *
019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
020 * or visit www.oracle.com if you need additional information or have any
021 * questions.
022 */
023package com.oracle.graal.replacements.test;
024
025import jdk.internal.jvmci.meta.*;
026
027import org.junit.*;
028
029import com.oracle.graal.compiler.common.type.*;
030import com.oracle.graal.compiler.test.*;
031import com.oracle.graal.nodes.*;
032import com.oracle.graal.nodes.StructuredGraph.AllowAssumptions;
033import com.oracle.graal.phases.common.*;
034import com.oracle.graal.phases.common.inlining.*;
035import com.oracle.graal.phases.tiers.*;
036import com.oracle.graal.replacements.nodes.*;
037
038public class BitOpNodesTest extends GraalCompilerTest {
039
040    private static final int INT_CONSTANT_1 = 0x80100010;
041    private static final int INT_CONSTANT_2 = 0x00011110;
042    private static final int INT_CONSTANT_3 = 0x00000000;
043
044    private static final long LONG_CONSTANT_1 = 0x8000000000100010L;
045    private static final long LONG_CONSTANT_2 = 0x0000000000011110L;
046    private static final long LONG_CONSTANT_3 = 0x0000000000000000L;
047
048    public static long dummyField;
049
050    /*
051     * Tests for BitCountNode canonicalizations.
052     */
053
054    public static int bitCountIntConstantSnippet() {
055        return Integer.bitCount(INT_CONSTANT_1) + Integer.bitCount(INT_CONSTANT_2) + Integer.bitCount(INT_CONSTANT_3);
056    }
057
058    @Test
059    public void testBitCountIntConstant() {
060        ValueNode result = parseAndInline("bitCountIntConstantSnippet");
061        Assert.assertEquals(7, result.asJavaConstant().asInt());
062    }
063
064    public static int bitCountLongConstantSnippet() {
065        return Long.bitCount(LONG_CONSTANT_1) + Long.bitCount(LONG_CONSTANT_2) + Long.bitCount(LONG_CONSTANT_3);
066    }
067
068    public static int bitCountIntSnippet(int v) {
069        return Integer.bitCount(v & 0xFFFFFF | 0xFF);
070    }
071
072    @Test
073    public void testBitCountInt() {
074        ValueNode result = parseAndInline("bitCountIntSnippet");
075        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 24), result.stamp());
076    }
077
078    public static int bitCountIntEmptySnippet(int v) {
079        return Integer.bitCount(v & 0xFFFFFF);
080    }
081
082    @Test
083    public void testBitCountIntEmpty() {
084        ValueNode result = parseAndInline("bitCountIntEmptySnippet");
085        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 24), result.stamp());
086    }
087
088    @Test
089    public void testBitCountLongConstant() {
090        ValueNode result = parseAndInline("bitCountLongConstantSnippet");
091        Assert.assertEquals(7, result.asJavaConstant().asInt());
092    }
093
094    public static int bitCountLongSnippet(long v) {
095        return Long.bitCount(v & 0xFFFFFFFFFFL | 0xFFL);
096    }
097
098    @Test
099    public void testBitCountLong() {
100        ValueNode result = parseAndInline("bitCountLongSnippet");
101        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 8, 40), result.stamp());
102    }
103
104    public static int bitCountLongEmptySnippet(long v) {
105        return Long.bitCount(v & 0xFFFFFFFFFFL);
106    }
107
108    @Test
109    public void testBitCountLongEmpty() {
110        ValueNode result = parseAndInline("bitCountLongEmptySnippet");
111        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 0, 40), result.stamp());
112    }
113
114    /*
115     * Tests for BitScanForwardNode
116     */
117
118    public static int scanForwardIntConstantSnippet() {
119        return Integer.numberOfTrailingZeros(INT_CONSTANT_1) + Integer.numberOfTrailingZeros(INT_CONSTANT_2) + Integer.numberOfTrailingZeros(INT_CONSTANT_3);
120    }
121
122    @Test
123    public void testScanForwardIntConstant() {
124        ValueNode result = parseAndInline("scanForwardIntConstantSnippet");
125        Assert.assertEquals(40, result.asJavaConstant().asInt());
126    }
127
128    public static int scanForwardIntSnippet(int v) {
129        return Integer.numberOfTrailingZeros(v & 0xFFF0 | 0xFF00);
130    }
131
132    @Test
133    public void testScanForwardInt() {
134        ValueNode result = parseAndInline("scanForwardIntSnippet");
135        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 4, 8), result.stamp());
136    }
137
138    public static int scanForwardLongConstantSnippet() {
139        return Long.numberOfTrailingZeros(LONG_CONSTANT_1) + Long.numberOfTrailingZeros(LONG_CONSTANT_2) + Long.numberOfTrailingZeros(LONG_CONSTANT_3);
140    }
141
142    @Test
143    public void testScanForwardLongConstant() {
144        ValueNode result = parseAndInline("scanForwardLongConstantSnippet");
145        Assert.assertEquals(72, result.asJavaConstant().asInt());
146    }
147
148    public static int scanForwardLongSnippet(long v) {
149        return Long.numberOfTrailingZeros(v & 0xFFFF000000L | 0xFF00000000L);
150    }
151
152    @Test
153    public void testScanForwardLong() {
154        ValueNode result = parseAndInline("scanForwardLongSnippet");
155        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 32), result.stamp());
156    }
157
158    public static int scanForwardLongEmptySnippet(long v) {
159        int result = Long.numberOfTrailingZeros(v & 0xFFFF000000L);
160        dummyField = result;
161        return result;
162    }
163
164    @Test
165    public void testScanForwardLongEmpty() {
166        ValueNode result = parseAndInline("scanForwardLongEmptySnippet");
167        Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp());
168    }
169
170    /*
171     * Tests for BitScanReverseNode
172     */
173
174    public static int scanReverseIntConstantSnippet() {
175        return Integer.numberOfLeadingZeros(INT_CONSTANT_1) + Integer.numberOfLeadingZeros(INT_CONSTANT_2) + Integer.numberOfLeadingZeros(INT_CONSTANT_3);
176    }
177
178    @Test
179    public void testScanReverseIntConstant() {
180        ValueNode result = parseAndInline("scanReverseIntConstantSnippet");
181        Assert.assertEquals(47, result.asJavaConstant().asInt());
182    }
183
184    public static int scanReverseIntSnippet(int v) {
185        return Integer.numberOfLeadingZeros(v & 0xFFF0 | 0xFF0);
186    }
187
188    @Test
189    public void testScanReverseInt() {
190        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
191        ValueNode result = parseAndInline("scanReverseIntSnippet", BitScanReverseNode.class);
192        if (result != null) {
193            Assert.assertEquals(StampFactory.forInteger(Kind.Int, 16, 20), result.stamp());
194        }
195    }
196
197    public static int scanReverseLongConstantSnippet() {
198        return Long.numberOfLeadingZeros(LONG_CONSTANT_1) + Long.numberOfLeadingZeros(LONG_CONSTANT_2) + Long.numberOfLeadingZeros(LONG_CONSTANT_3);
199    }
200
201    @Test
202    public void testScanReverseLongConstant() {
203        ValueNode result = parseAndInline("scanReverseLongConstantSnippet");
204        Assert.assertEquals(111, result.asJavaConstant().asInt());
205    }
206
207    public static int scanReverseLongSnippet(long v) {
208        int result = Long.numberOfLeadingZeros(v & 0xFFF0);
209        dummyField = result;
210        return result;
211    }
212
213    @Test
214    public void testScanReverseLong() {
215        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
216        ValueNode result = parseAndInline("scanReverseLongSnippet", BitScanReverseNode.class);
217        if (result != null) {
218            Assert.assertEquals(StampFactory.forInteger(Kind.Int, 48, 64), result.stamp());
219        }
220    }
221
222    public static int scanReverseLongEmptySnippet(long v) {
223        int result = Long.numberOfLeadingZeros(v & 0xFFFF000000L);
224        dummyField = result;
225        return result;
226    }
227
228    @Test
229    public void testScanReverseLongEmpty() {
230        /* This test isn't valid unless the BitScanReverseNode intrinsic is used. */
231        ValueNode result = parseAndInline("scanReverseLongEmptySnippet", BitScanReverseNode.class);
232        if (result != null) {
233            Assert.assertEquals(StampFactory.forInteger(Kind.Int, 24, 64), result.stamp());
234        }
235    }
236
237    private ValueNode parseAndInline(String name) {
238        return parseAndInline(name, null);
239    }
240
241    /**
242     * Parse and optimize {@code name}. If {@code expectedClass} is non-null and a node of that type
243     * isn't found simply return null. Otherwise return the node returned by the graph.
244     *
245     * @param name
246     * @param expectedClass
247     * @return the returned value or null if {@code expectedClass} is not found in the graph.
248     */
249    private ValueNode parseAndInline(String name, Class<? extends ValueNode> expectedClass) {
250        StructuredGraph graph = parseEager(name, AllowAssumptions.YES);
251        HighTierContext context = getDefaultHighTierContext();
252        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
253        canonicalizer.apply(graph, context);
254        new InliningPhase(canonicalizer).apply(graph, context);
255        canonicalizer.apply(graph, context);
256        Assert.assertEquals(1, graph.getNodes(ReturnNode.TYPE).count());
257        if (expectedClass != null) {
258            if (graph.getNodes().filter(expectedClass).count() == 0) {
259                return null;
260            }
261        }
262        return graph.getNodes(ReturnNode.TYPE).first().result();
263    }
264}