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.code.*; 026 027import com.oracle.graal.compiler.common.type.*; 028import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shr; 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 RightShiftNode extends ShiftNode<Shr> { 038 039 public static final NodeClass<RightShiftNode> TYPE = NodeClass.create(RightShiftNode.class); 040 041 public RightShiftNode(ValueNode x, ValueNode y) { 042 super(TYPE, ArithmeticOpTable::getShr, 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 (forX.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { 053 return new UnsignedRightShiftNode(forX, forY); 054 } 055 056 if (forY.isConstant()) { 057 int amount = forY.asJavaConstant().asInt(); 058 int originalAmout = amount; 059 int mask = getShiftAmountMask(); 060 amount &= mask; 061 if (amount == 0) { 062 return forX; 063 } 064 if (forX instanceof ShiftNode) { 065 ShiftNode<?> other = (ShiftNode<?>) forX; 066 if (other.getY().isConstant()) { 067 int otherAmount = other.getY().asJavaConstant().asInt() & mask; 068 if (other instanceof RightShiftNode) { 069 int total = amount + otherAmount; 070 if (total != (total & mask)) { 071 assert other.getX().stamp() instanceof IntegerStamp; 072 IntegerStamp istamp = (IntegerStamp) other.getX().stamp(); 073 074 if (istamp.isPositive()) { 075 return ConstantNode.forIntegerKind(getKind(), 0); 076 } 077 if (istamp.isStrictlyNegative()) { 078 return ConstantNode.forIntegerKind(getKind(), -1L); 079 } 080 081 /* 082 * if we cannot replace both shifts with a constant, replace them by a 083 * full shift for this kind 084 */ 085 assert total >= mask; 086 return new RightShiftNode(other.getX(), ConstantNode.forInt(mask)); 087 } 088 return new RightShiftNode(other.getX(), ConstantNode.forInt(total)); 089 } 090 } 091 } 092 if (originalAmout != amount) { 093 return new RightShiftNode(forX, ConstantNode.forInt(amount)); 094 } 095 } 096 return this; 097 } 098 099 @Override 100 public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) { 101 nodeValueMap.setResult(this, gen.emitShr(nodeValueMap.operand(getX()), nodeValueMap.operand(getY()))); 102 } 103 104 @Override 105 public boolean isNarrowable(int resultBits) { 106 if (super.isNarrowable(resultBits)) { 107 /* 108 * For signed right shifts, the narrow can be done before the shift if the cut off bits 109 * are all equal to the sign bit of the input. That's equivalent to the condition that 110 * the input is in the signed range of the narrow type. 111 */ 112 IntegerStamp inputStamp = (IntegerStamp) getX().stamp(); 113 return CodeUtil.minValue(resultBits) <= inputStamp.lowerBound() && inputStamp.upperBound() <= CodeUtil.maxValue(resultBits); 114 } else { 115 return false; 116 } 117 } 118}