1 /*
   2  * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 
  25 package org.graalvm.compiler.hotspot.amd64;
  26 
  27 import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.COS;
  28 import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG;
  29 import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.LOG10;
  30 import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.SIN;
  31 import static org.graalvm.compiler.hotspot.amd64.AMD64HotSpotMathIntrinsicOp.IntrinsicOpcode.TAN;
  32 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_64;
  33 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_1;
  34 
  35 import org.graalvm.compiler.core.common.LIRKind;
  36 import org.graalvm.compiler.core.common.type.FloatStamp;
  37 import org.graalvm.compiler.core.common.type.PrimitiveStamp;
  38 import org.graalvm.compiler.core.common.type.Stamp;
  39 import org.graalvm.compiler.debug.GraalError;
  40 import org.graalvm.compiler.graph.NodeClass;
  41 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
  42 import org.graalvm.compiler.lir.Variable;
  43 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
  44 import org.graalvm.compiler.nodeinfo.NodeInfo;
  45 import org.graalvm.compiler.nodes.ConstantNode;
  46 import org.graalvm.compiler.nodes.NodeView;
  47 import org.graalvm.compiler.nodes.ValueNode;
  48 import org.graalvm.compiler.nodes.calc.UnaryNode;
  49 import org.graalvm.compiler.nodes.spi.LIRLowerable;
  50 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
  51 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
  52 
  53 import jdk.vm.ci.meta.Value;
  54 
  55 @NodeInfo(nameTemplate = "X87MathIntrinsic#{p#operation/s}", cycles = CYCLES_64, size = SIZE_1)
  56 public final class AMD64X87MathIntrinsicNode extends UnaryNode implements LIRLowerable {
  57 
  58     public static final NodeClass<AMD64X87MathIntrinsicNode> TYPE = NodeClass.create(AMD64X87MathIntrinsicNode.class);
  59     protected final UnaryOperation operation;
  60 
  61     protected AMD64X87MathIntrinsicNode(ValueNode value, UnaryOperation op) {
  62         super(TYPE, op.computeStamp(value.stamp(NodeView.DEFAULT)), value);
  63         assert value.stamp(NodeView.DEFAULT) instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp(NodeView.DEFAULT)) == 64;
  64         this.operation = op;
  65     }
  66 
  67     @Override
  68     public Stamp foldStamp(Stamp valueStamp) {
  69         return operation.computeStamp(valueStamp);
  70     }
  71 
  72     @Override
  73     public void generate(NodeLIRBuilderTool generator) {
  74         LIRGeneratorTool gen = generator.getLIRGeneratorTool();
  75         Value input = generator.operand(getValue());
  76         Variable result = gen.newVariable(LIRKind.combine(input));
  77 
  78         switch (operation) {
  79             case SIN:
  80                 gen.append(new AMD64HotSpotMathIntrinsicOp(SIN, result, gen.asAllocatable(input)));
  81                 break;
  82             case COS:
  83                 gen.append(new AMD64HotSpotMathIntrinsicOp(COS, result, gen.asAllocatable(input)));
  84                 break;
  85             case TAN:
  86                 gen.append(new AMD64HotSpotMathIntrinsicOp(TAN, result, gen.asAllocatable(input)));
  87                 break;
  88             case LOG:
  89                 gen.append(new AMD64HotSpotMathIntrinsicOp(LOG, result, gen.asAllocatable(input)));
  90                 break;
  91             case LOG10:
  92                 gen.append(new AMD64HotSpotMathIntrinsicOp(LOG10, result, gen.asAllocatable(input)));
  93                 break;
  94             default:
  95                 throw GraalError.shouldNotReachHere();
  96         }
  97         generator.setResult(this, result);
  98     }
  99 
 100     @Override
 101     public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
 102         if (forValue.isConstant()) {
 103             return ConstantNode.forDouble(operation.compute(forValue.asJavaConstant().asDouble()));
 104         }
 105         return this;
 106     }
 107 
 108     @NodeIntrinsic
 109     public static native double compute(double value, @ConstantNodeParameter UnaryOperation op);
 110 
 111 }