001/* 002 * Copyright (c) 2011, 2015, 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.nodes.calc; 024 025import jdk.internal.jvmci.meta.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.UShr; 029import com.oracle.graal.graph.*; 030import com.oracle.graal.graph.spi.*; 031import com.oracle.graal.lir.gen.*; 032import com.oracle.graal.nodeinfo.*; 033import com.oracle.graal.nodes.*; 034import com.oracle.graal.nodes.spi.*; 035 036@NodeInfo(shortName = ">>>") 037public final class UnsignedRightShiftNode extends ShiftNode<UShr> { 038 039 public static final NodeClass<UnsignedRightShiftNode> TYPE = NodeClass.create(UnsignedRightShiftNode.class); 040 041 public UnsignedRightShiftNode(ValueNode x, ValueNode y) { 042 super(TYPE, ArithmeticOpTable::getUShr, x, y); 043 } 044 045 @Override 046 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 047 ValueNode ret = super.canonical(tool, forX, forY); 048 if (ret != this) { 049 return ret; 050 } 051 052 if (forY.isConstant()) { 053 int amount = forY.asJavaConstant().asInt(); 054 int originalAmout = amount; 055 int mask = getShiftAmountMask(); 056 amount &= mask; 057 if (amount == 0) { 058 return forX; 059 } 060 if (forX instanceof ShiftNode) { 061 ShiftNode<?> other = (ShiftNode<?>) forX; 062 if (other.getY().isConstant()) { 063 int otherAmount = other.getY().asJavaConstant().asInt() & mask; 064 if (other instanceof UnsignedRightShiftNode) { 065 int total = amount + otherAmount; 066 if (total != (total & mask)) { 067 return ConstantNode.forIntegerKind(getKind(), 0); 068 } 069 return new UnsignedRightShiftNode(other.getX(), ConstantNode.forInt(total)); 070 } else if (other instanceof LeftShiftNode && otherAmount == amount) { 071 if (getKind() == Kind.Long) { 072 return new AndNode(other.getX(), ConstantNode.forLong(-1L >>> amount)); 073 } else { 074 assert getKind() == Kind.Int; 075 return new AndNode(other.getX(), ConstantNode.forInt(-1 >>> amount)); 076 } 077 } 078 } 079 } 080 if (originalAmout != amount) { 081 return new UnsignedRightShiftNode(forX, ConstantNode.forInt(amount)); 082 } 083 } 084 return this; 085 } 086 087 @Override 088 public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) { 089 nodeValueMap.setResult(this, gen.emitUShr(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()))); 090 } 091 092 @Override 093 public boolean isNarrowable(int resultBits) { 094 if (super.isNarrowable(resultBits)) { 095 /* 096 * For unsigned right shifts, the narrow can be done before the shift if the cut off 097 * bits are all zero. 098 */ 099 IntegerStamp inputStamp = (IntegerStamp) getX().stamp(); 100 return (inputStamp.upMask() & ~(resultBits - 1)) == 0; 101 } else { 102 return false; 103 } 104 } 105}