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}