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.*; 026import jdk.internal.jvmci.meta.*; 027 028import com.oracle.graal.compiler.common.calc.*; 029import com.oracle.graal.compiler.common.type.*; 030import com.oracle.graal.graph.*; 031import com.oracle.graal.graph.spi.*; 032import com.oracle.graal.nodeinfo.*; 033import com.oracle.graal.nodes.*; 034import com.oracle.graal.nodes.util.*; 035 036@NodeInfo(shortName = "|<|") 037public final class IntegerBelowNode extends CompareNode { 038 public static final NodeClass<IntegerBelowNode> TYPE = NodeClass.create(IntegerBelowNode.class); 039 040 public IntegerBelowNode(ValueNode x, ValueNode y) { 041 super(TYPE, Condition.BT, false, x, y); 042 assert x.stamp() instanceof IntegerStamp; 043 assert y.stamp() instanceof IntegerStamp; 044 } 045 046 public static LogicNode create(ValueNode x, ValueNode y, ConstantReflectionProvider constantReflection) { 047 LogicNode result = CompareNode.tryConstantFold(Condition.BT, x, y, constantReflection, false); 048 if (result != null) { 049 return result; 050 } else { 051 result = findSynonym(x, y); 052 if (result != null) { 053 return result; 054 } 055 return new IntegerBelowNode(x, y); 056 } 057 } 058 059 @Override 060 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 061 ValueNode result = super.canonical(tool, forX, forY); 062 if (result != this) { 063 return result; 064 } 065 LogicNode synonym = findSynonym(forX, forY); 066 if (synonym != null) { 067 return synonym; 068 } 069 if (forX.isConstant() && forX.asJavaConstant().asLong() == 0) { 070 // 0 |<| y is the same as 0 != y 071 return LogicNegationNode.create(CompareNode.createCompareNode(Condition.EQ, forX, forY, tool.getConstantReflection())); 072 } 073 return this; 074 } 075 076 private static LogicNode findSynonym(ValueNode forX, ValueNode forY) { 077 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { 078 return LogicConstantNode.contradiction(); 079 } else if (forX.stamp() instanceof IntegerStamp && forY.stamp() instanceof IntegerStamp) { 080 IntegerStamp xStamp = (IntegerStamp) forX.stamp(); 081 IntegerStamp yStamp = (IntegerStamp) forY.stamp(); 082 if (yStamp.isPositive()) { 083 if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { 084 return LogicConstantNode.tautology(); 085 } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { 086 return LogicConstantNode.contradiction(); 087 } 088 } 089 } 090 return null; 091 } 092 093 @Override 094 protected CompareNode duplicateModified(ValueNode newX, ValueNode newY) { 095 return new IntegerBelowNode(newX, newY); 096 } 097 098 @Override 099 public Stamp getSucceedingStampForX(boolean negated) { 100 Stamp xStampGeneric = getX().stamp(); 101 Stamp yStampGeneric = getY().stamp(); 102 if (xStampGeneric instanceof IntegerStamp) { 103 IntegerStamp xStamp = (IntegerStamp) xStampGeneric; 104 int bits = xStamp.getBits(); 105 if (yStampGeneric instanceof IntegerStamp) { 106 IntegerStamp yStamp = (IntegerStamp) yStampGeneric; 107 assert yStamp.getBits() == bits; 108 if (negated) { 109 // x >= y 110 if (xStamp.isPositive() && yStamp.isPositive()) { 111 long xLowerBound = xStamp.lowerBound(); 112 long yLowerBound = yStamp.lowerBound(); 113 if (yLowerBound > xLowerBound) { 114 return new IntegerStamp(bits, yLowerBound, xStamp.upperBound(), xStamp.downMask(), xStamp.upMask()); 115 } 116 } 117 } else { 118 // x < y 119 if (yStamp.isStrictlyPositive()) { 120 // x >= 0 && x < y 121 long xUpperBound = xStamp.upperBound(); 122 long yUpperBound = yStamp.upperBound(); 123 if (yUpperBound <= xUpperBound || !xStamp.isPositive()) { 124 return new IntegerStamp(bits, Math.max(0, xStamp.lowerBound()), Math.min(xUpperBound, yUpperBound - 1), xStamp.downMask(), xStamp.upMask()); 125 } 126 } 127 } 128 } 129 } 130 return null; 131 } 132 133 @Override 134 public Stamp getSucceedingStampForY(boolean negated) { 135 Stamp xStampGeneric = getX().stamp(); 136 Stamp yStampGeneric = getY().stamp(); 137 if (xStampGeneric instanceof IntegerStamp) { 138 IntegerStamp xStamp = (IntegerStamp) xStampGeneric; 139 int bits = xStamp.getBits(); 140 if (yStampGeneric instanceof IntegerStamp) { 141 IntegerStamp yStamp = (IntegerStamp) yStampGeneric; 142 assert yStamp.getBits() == bits; 143 if (negated) { 144 // y <= x 145 if (xStamp.isPositive()) { 146 long xUpperBound = xStamp.upperBound(); 147 long yUpperBound = yStamp.upperBound(); 148 if (xUpperBound < yUpperBound || !yStamp.isPositive()) { 149 return new IntegerStamp(bits, Math.max(0, yStamp.lowerBound()), Math.min(xUpperBound, yUpperBound), yStamp.downMask(), yStamp.upMask()); 150 } 151 } 152 } else { 153 // y > x 154 if (xStamp.isPositive() && yStamp.isPositive()) { 155 long xLowerBound = xStamp.lowerBound(); 156 long yLowerBound = yStamp.lowerBound(); 157 if (xLowerBound == CodeUtil.maxValue(bits)) { 158 return null; 159 } else if (xLowerBound >= yLowerBound) { 160 assert xLowerBound != CodeUtil.maxValue(bits); 161 return new IntegerStamp(bits, xLowerBound + 1, yStamp.upperBound(), yStamp.downMask(), yStamp.upMask()); 162 } 163 } 164 } 165 } 166 } 167 return null; 168 } 169 170 @Override 171 public TriState tryFold(Stamp xStampGeneric, Stamp yStampGeneric) { 172 if (xStampGeneric instanceof IntegerStamp) { 173 IntegerStamp xStamp = (IntegerStamp) xStampGeneric; 174 if (yStampGeneric instanceof IntegerStamp) { 175 IntegerStamp yStamp = (IntegerStamp) yStampGeneric; 176 if (yStamp.isPositive()) { 177 if (xStamp.isPositive() && xStamp.upperBound() < yStamp.lowerBound()) { 178 return TriState.TRUE; 179 } else if (xStamp.isStrictlyNegative() || xStamp.lowerBound() >= yStamp.upperBound()) { 180 return TriState.FALSE; 181 } 182 } 183 } 184 } 185 return TriState.UNKNOWN; 186 } 187}