001/* 002 * Copyright (c) 2011, 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.replacements.amd64; 024 025import static com.oracle.graal.compiler.target.Backend.*; 026 027import com.oracle.graal.compiler.common.spi.*; 028import com.oracle.graal.graph.Node.ConstantNodeParameter; 029import com.oracle.graal.graph.Node.NodeIntrinsic; 030import com.oracle.graal.nodes.extended.*; 031import com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation; 032 033// JaCoCo Exclude 034 035/** 036 * Substitutions for some {@link java.lang.Math} methods that leverage AMD64 instructions for 037 * selected input values. 038 */ 039public class AMD64MathSubstitutions { 040 041 private static final double PI_4 = Math.PI / 4; 042 043 /** 044 * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). 045 */ 046 public static double pow(double x, double y) { 047 // If the second argument is positive or negative zero, then the result is 1.0. 048 if (y == 0.0D) { 049 return 1; 050 } 051 052 // If the second argument is 1.0, then the result is the same as the first argument. 053 if (y == 1.0D) { 054 return x; 055 } 056 057 // If the second argument is NaN, then the result is NaN. 058 if (Double.isNaN(y)) { 059 return Double.NaN; 060 } 061 062 // If the first argument is NaN and the second argument is nonzero, then the result is NaN. 063 if (Double.isNaN(x) && y != 0.0D) { 064 return Double.NaN; 065 } 066 067 // x**-1 = 1/x 068 if (y == -1.0D) { 069 return 1 / x; 070 } 071 072 // x**2 = x*x 073 if (y == 2.0D) { 074 return x * x; 075 } 076 077 // x**0.5 = sqrt(x) 078 if (y == 0.5D && x >= 0.0D) { 079 return Math.sqrt(x); 080 } 081 return callDouble2(ARITHMETIC_POW, x, y); 082 } 083 084 // NOTE on snippets below: 085 // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the 086 // exact result, but x87 trigonometric FPU instructions are only that 087 // accurate within [-pi/4, pi/4]. Examine the passed value and provide 088 // a slow path for inputs outside of that interval. 089 090 public static double sin(double x) { 091 if (Math.abs(x) < PI_4) { 092 return AMD64MathIntrinsicNode.compute(x, Operation.SIN); 093 } else { 094 return callDouble1(ARITHMETIC_SIN, x); 095 } 096 } 097 098 public static double cos(double x) { 099 if (Math.abs(x) < PI_4) { 100 return AMD64MathIntrinsicNode.compute(x, Operation.COS); 101 } else { 102 return callDouble1(ARITHMETIC_COS, x); 103 } 104 } 105 106 public static double tan(double x) { 107 if (Math.abs(x) < PI_4) { 108 return AMD64MathIntrinsicNode.compute(x, Operation.TAN); 109 } else { 110 return callDouble1(ARITHMETIC_TAN, x); 111 } 112 } 113 114 @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) 115 private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); 116 117 @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) 118 private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); 119}