001/* 002 * Copyright (c) 2014, 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.nodes.calc; 024 025import java.util.*; 026 027import jdk.internal.jvmci.meta.*; 028 029import com.oracle.graal.compiler.common.calc.*; 030import com.oracle.graal.compiler.common.type.*; 031import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; 032import com.oracle.graal.graph.*; 033import com.oracle.graal.graph.spi.*; 034import com.oracle.graal.lir.gen.*; 035import com.oracle.graal.nodeinfo.*; 036import com.oracle.graal.nodes.*; 037import com.oracle.graal.nodes.spi.*; 038 039/** 040 * A {@code FloatConvert} converts between integers and floating point numbers according to Java 041 * semantics. 042 */ 043@NodeInfo 044public final class FloatConvertNode extends UnaryArithmeticNode<FloatConvertOp> implements ConvertNode, Lowerable, ArithmeticLIRLowerable { 045 public static final NodeClass<FloatConvertNode> TYPE = NodeClass.create(FloatConvertNode.class); 046 047 protected final FloatConvert op; 048 049 private static final EnumMap<FloatConvert, SerializableUnaryFunction<FloatConvertOp>> getOps; 050 static { 051 getOps = new EnumMap<>(FloatConvert.class); 052 for (FloatConvert op : FloatConvert.values()) { 053 getOps.put(op, table -> table.getFloatConvert(op)); 054 } 055 } 056 057 public FloatConvertNode(FloatConvert op, ValueNode input) { 058 super(TYPE, getOps.get(op), input); 059 this.op = op; 060 } 061 062 public static ValueNode create(FloatConvert op, ValueNode input) { 063 ValueNode synonym = findSynonym(input, ArithmeticOpTable.forStamp(input.stamp()).getFloatConvert(op)); 064 if (synonym != null) { 065 return synonym; 066 } 067 return new FloatConvertNode(op, input); 068 } 069 070 public FloatConvert getFloatConvert() { 071 return op; 072 } 073 074 @Override 075 public Constant convert(Constant c, ConstantReflectionProvider constantReflection) { 076 return getOp(getValue()).foldConstant(c); 077 } 078 079 @Override 080 public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) { 081 FloatConvertOp reverse = ArithmeticOpTable.forStamp(stamp()).getFloatConvert(op.reverse()); 082 return reverse.foldConstant(c); 083 } 084 085 @Override 086 public boolean isLossless() { 087 switch (getFloatConvert()) { 088 case F2D: 089 case I2D: 090 return true; 091 default: 092 return false; 093 } 094 } 095 096 @Override 097 public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { 098 ValueNode ret = super.canonical(tool, forValue); 099 if (ret != this) { 100 return ret; 101 } 102 103 if (forValue instanceof FloatConvertNode) { 104 FloatConvertNode other = (FloatConvertNode) forValue; 105 if (other.isLossless() && other.op == this.op.reverse()) { 106 return other.getValue(); 107 } 108 } 109 return this; 110 } 111 112 public void lower(LoweringTool tool) { 113 tool.getLowerer().lower(this, tool); 114 } 115 116 public void generate(NodeValueMap nodeValueMap, ArithmeticLIRGenerator gen) { 117 nodeValueMap.setResult(this, gen.emitFloatConvert(getFloatConvert(), nodeValueMap.operand(getValue()))); 118 } 119}