# HG changeset patch # User Doug Simon # Date 1428523745 -7200 # Node ID 3081a57f95fd088c842b0b65b7b9a466137fe783 # Parent a74c785068e0a34534da98219c58f0bbf8222942 converted @MethodSubstitutions for java.lang.Math to MethodSubstitutionPlugins moved support for AMD64 specific Math intrinsics into AMD64 specific name spaces diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64LIRGenerator.java Wed Apr 08 22:09:05 2015 +0200 @@ -73,7 +73,7 @@ /** * This class implements the AMD64 specific portion of the LIR generator. */ -public abstract class AMD64LIRGenerator extends LIRGenerator { +public abstract class AMD64LIRGenerator extends LIRGenerator implements AMD64ArithmeticLIRGenerator { private static final RegisterValue RCX_I = AMD64.rcx.asValue(LIRKind.value(Kind.Int)); diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java --- a/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.compiler.sparc/src/com/oracle/graal/compiler/sparc/SPARCLIRGenerator.java Wed Apr 08 22:09:05 2015 +0200 @@ -44,6 +44,7 @@ import com.oracle.graal.lir.sparc.SPARCArithmetic.BinaryRegReg; import com.oracle.graal.lir.sparc.SPARCArithmetic.MulHighOp; import com.oracle.graal.lir.sparc.SPARCArithmetic.RemOp; +import com.oracle.graal.lir.sparc.SPARCArithmetic.SPARCLMulccOp; import com.oracle.graal.lir.sparc.SPARCArithmetic.Unary2Op; import com.oracle.graal.lir.sparc.SPARCCompare.CompareOp; import com.oracle.graal.lir.sparc.SPARCControlFlow.BranchOp; @@ -467,34 +468,6 @@ } @Override - public Value emitMathLog(Value input, boolean base10) { - Variable result = newVariable(LIRKind.derive(input)); - append(new SPARCMathIntrinsicOp(LOG, result, asAllocatable(input))); - return result; - } - - @Override - public Value emitMathCos(Value input) { - Variable result = newVariable(LIRKind.derive(input)); - append(new SPARCMathIntrinsicOp(COS, result, asAllocatable(input))); - return result; - } - - @Override - public Value emitMathSin(Value input) { - Variable result = newVariable(LIRKind.derive(input)); - append(new SPARCMathIntrinsicOp(SIN, result, asAllocatable(input))); - return result; - } - - @Override - public Value emitMathTan(Value input) { - Variable result = newVariable(LIRKind.derive(input)); - append(new SPARCMathIntrinsicOp(TAN, result, asAllocatable(input))); - return result; - } - - @Override public Variable emitByteSwap(Value input) { Variable result = newVariable(LIRKind.derive(input)); append(new SPARCByteSwapOp(this, result, input)); diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/target/Backend.java Wed Apr 08 22:09:05 2015 +0200 @@ -44,6 +44,11 @@ private final Providers providers; + public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class); + public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class); + public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class); + public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class); + protected Backend(Providers providers) { this.providers = providers; } diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotHostForeignCallsProvider.java Wed Apr 08 22:09:05 2015 +0200 @@ -44,7 +44,6 @@ import static com.oracle.graal.hotspot.stubs.UnwindExceptionToCallerStub.*; import static com.oracle.graal.nodes.java.ForeignCallDescriptors.*; import static com.oracle.graal.replacements.Log.*; -import static com.oracle.graal.replacements.MathSubstitutionsX86.*; import java.util.*; diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.lir.amd64/src/com/oracle/graal/lir/amd64/AMD64ArithmeticLIRGenerator.java Wed Apr 08 22:09:05 2015 +0200 @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.lir.amd64; + +import com.oracle.graal.api.meta.*; + +/** + * This interface can be used to generate AMD64 LIR for arithmetic operations. + */ +public interface AMD64ArithmeticLIRGenerator { + + Value emitMathLog(Value input, boolean base10); + + Value emitMathCos(Value input); + + Value emitMathSin(Value input); + + Value emitMathTan(Value input); +} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java --- a/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.lir.sparc/src/com/oracle/graal/lir/sparc/SPARCMathIntrinsicOp.java Wed Apr 08 22:09:05 2015 +0200 @@ -35,11 +35,6 @@ public enum IntrinsicOpcode { SQRT, - SIN, - COS, - TAN, - LOG, - LOG10, ABS } @@ -83,11 +78,6 @@ GraalInternalError.shouldNotReachHere(); } break; - case LOG: - case LOG10: - case SIN: - case COS: - case TAN: default: throw GraalInternalError.shouldNotReachHere(); } diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java --- a/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.lir/src/com/oracle/graal/lir/gen/ArithmeticLIRGenerator.java Wed Apr 08 22:09:05 2015 +0200 @@ -87,12 +87,4 @@ Value emitMathAbs(Value input); Value emitMathSqrt(Value input); - - Value emitMathLog(Value input, boolean base10); - - Value emitMathCos(Value input); - - Value emitMathSin(Value input); - - Value emitMathTan(Value input); } diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64GraphBuilderPlugins.java Wed Apr 08 22:09:05 2015 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.replacements.amd64; -import static com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation.*; +import static com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation.*; import sun.misc.*; import com.oracle.graal.amd64.*; @@ -34,7 +34,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.java.*; import com.oracle.graal.replacements.*; -import com.oracle.graal.replacements.nodes.*; public class AMD64GraphBuilderPlugins { @@ -86,16 +85,20 @@ Registration r = new Registration(plugins, Math.class); r.register1("log", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG))); + b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG))); return true; } }); r.register1("log10", Double.TYPE, new InvocationPlugin() { public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode value) { - b.push(Kind.Double, b.recursiveAppend(MathIntrinsicNode.create(value, LOG10))); + b.push(Kind.Double, b.recursiveAppend(AMD64MathIntrinsicNode.create(value, LOG10))); return true; } }); + r.registerMethodSubstitution(AMD64MathSubstitutions.class, "sin", double.class); + r.registerMethodSubstitution(AMD64MathSubstitutions.class, "cos", double.class); + r.registerMethodSubstitution(AMD64MathSubstitutions.class, "tan", double.class); + r.registerMethodSubstitution(AMD64MathSubstitutions.class, "pow", double.class, double.class); } private static void registerUnsafePlugins(InvocationPlugins plugins) { diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathIntrinsicNode.java Wed Apr 08 22:09:05 2015 +0200 @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.amd64; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.amd64.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.calc.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo +public final class AMD64MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { + + public static final NodeClass TYPE = NodeClass.create(AMD64MathIntrinsicNode.class); + protected final Operation operation; + + public enum Operation { + LOG, + LOG10, + SIN, + COS, + TAN + } + + public Operation operation() { + return operation; + } + + public static ValueNode create(ValueNode value, Operation op) { + ValueNode c = tryConstantFold(value, op); + if (c != null) { + return c; + } + return new AMD64MathIntrinsicNode(value, op); + } + + protected static ValueNode tryConstantFold(ValueNode value, Operation op) { + if (value.isConstant()) { + double ret = doCompute(value.asJavaConstant().asDouble(), op); + return ConstantNode.forDouble(ret); + } + return null; + } + + protected AMD64MathIntrinsicNode(ValueNode value, Operation op) { + super(TYPE, StampFactory.forKind(Kind.Double), value); + assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; + this.operation = op; + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator lirGen) { + AMD64ArithmeticLIRGenerator gen = (AMD64ArithmeticLIRGenerator) lirGen; + Value input = builder.operand(getValue()); + Value result; + switch (operation()) { + case LOG: + result = gen.emitMathLog(input, false); + break; + case LOG10: + result = gen.emitMathLog(input, true); + break; + case SIN: + result = gen.emitMathSin(input); + break; + case COS: + result = gen.emitMathCos(input); + break; + case TAN: + result = gen.emitMathTan(input); + break; + default: + throw GraalInternalError.shouldNotReachHere(); + } + builder.setResult(this, result); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + ValueNode c = tryConstantFold(forValue, operation()); + if (c != null) { + return c; + } + return this; + } + + @NodeIntrinsic + public static native double compute(double value, @ConstantNodeParameter Operation op); + + private static double doCompute(double value, Operation op) { + switch (op) { + case LOG: + return Math.log(value); + case LOG10: + return Math.log10(value); + case SIN: + return Math.sin(value); + case COS: + return Math.cos(value); + case TAN: + return Math.tan(value); + default: + throw new GraalInternalError("unknown op %s", op); + } + } +} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.replacements.amd64/src/com/oracle/graal/replacements/amd64/AMD64MathSubstitutions.java Wed Apr 08 22:09:05 2015 +0200 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.graal.replacements.amd64; + +import static com.oracle.graal.compiler.target.Backend.*; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.graph.Node.ConstantNodeParameter; +import com.oracle.graal.graph.Node.NodeIntrinsic; +import com.oracle.graal.nodes.extended.*; +import com.oracle.graal.replacements.amd64.AMD64MathIntrinsicNode.Operation; + +/** + * Substitutions for some {@link java.lang.Math} methods that leverage AMD64 instructions for + * selected input values. + */ +public class AMD64MathSubstitutions { + + private static final double PI_4 = Math.PI / 4; + + /** + * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). + */ + public static double pow(double x, double y) { + // If the second argument is positive or negative zero, then the result is 1.0. + if (y == 0.0D) { + return 1; + } + + // If the second argument is 1.0, then the result is the same as the first argument. + if (y == 1.0D) { + return x; + } + + // If the second argument is NaN, then the result is NaN. + if (Double.isNaN(y)) { + return Double.NaN; + } + + // If the first argument is NaN and the second argument is nonzero, then the result is NaN. + if (Double.isNaN(x) && y != 0.0D) { + return Double.NaN; + } + + // x**-1 = 1/x + if (y == -1.0D) { + return 1 / x; + } + + // x**2 = x*x + if (y == 2.0D) { + return x * x; + } + + // x**0.5 = sqrt(x) + if (y == 0.5D && x >= 0.0D) { + return Math.sqrt(x); + } + return callDouble2(ARITHMETIC_POW, x, y); + } + + // NOTE on snippets below: + // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the + // exact result, but x87 trigonometric FPU instructions are only that + // accurate within [-pi/4, pi/4]. Examine the passed value and provide + // a slow path for inputs outside of that interval. + + public static double sin(double x) { + if (Math.abs(x) < PI_4) { + return AMD64MathIntrinsicNode.compute(x, Operation.SIN); + } else { + return callDouble1(ARITHMETIC_SIN, x); + } + } + + public static double cos(double x) { + if (Math.abs(x) < PI_4) { + return AMD64MathIntrinsicNode.compute(x, Operation.COS); + } else { + return callDouble1(ARITHMETIC_COS, x); + } + } + + public static double tan(double x) { + if (Math.abs(x) < PI_4) { + return AMD64MathIntrinsicNode.compute(x, Operation.TAN); + } else { + return callDouble1(ARITHMETIC_TAN, x); + } + } + + @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); + + @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) + private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); +} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/GraalMethodSubstitutions.java Wed Apr 08 11:24:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import static com.oracle.graal.compiler.common.GraalOptions.*; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.api.runtime.*; -import com.oracle.graal.nodes.spi.*; - -/** - * Method substitutions that are VM-independent. - */ -@ServiceProvider(ReplacementsProvider.class) -public class GraalMethodSubstitutions implements ReplacementsProvider { - - public void registerReplacements(MetaAccessProvider metaAccess, LoweringProvider loweringProvider, SnippetReflectionProvider snippetReflection, Replacements replacements, TargetDescription target) { - if (Intrinsify.getValue()) { - replacements.registerSubstitutions(Math.class, MathSubstitutionsX86.class); - } - } -} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/MathSubstitutionsX86.java Wed Apr 08 11:24:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.api.replacements.*; -import com.oracle.graal.graph.Node.ConstantNodeParameter; -import com.oracle.graal.graph.Node.NodeIntrinsic; -import com.oracle.graal.nodes.extended.*; -import com.oracle.graal.replacements.nodes.*; -import com.oracle.graal.replacements.nodes.MathIntrinsicNode.Operation; - -/** - * Substitutions for {@link java.lang.Math} methods. - */ -@ClassSubstitution(value = java.lang.Math.class) -public class MathSubstitutionsX86 { - - private static final double PI_4 = Math.PI / 4; - - /** - * Special cases from {@link Math#pow} and __ieee754_pow (in sharedRuntimeTrans.cpp). - */ - @MethodSubstitution(guard = MathGuard.class) - public static double pow(double x, double y) { - // If the second argument is positive or negative zero, then the result is 1.0. - if (y == 0.0D) { - return 1; - } - - // If the second argument is 1.0, then the result is the same as the first argument. - if (y == 1.0D) { - return x; - } - - // If the second argument is NaN, then the result is NaN. - if (Double.isNaN(y)) { - return Double.NaN; - } - - // If the first argument is NaN and the second argument is nonzero, then the result is NaN. - if (Double.isNaN(x) && y != 0.0D) { - return Double.NaN; - } - - // x**-1 = 1/x - if (y == -1.0D) { - return 1 / x; - } - - // x**2 = x*x - if (y == 2.0D) { - return x * x; - } - - // x**0.5 = sqrt(x) - if (y == 0.5D && x >= 0.0D) { - return Math.sqrt(x); - } - return callDouble2(ARITHMETIC_POW, x, y); - } - - // NOTE on snippets below: - // Math.sin(), .cos() and .tan() guarantee a value within 1 ULP of the - // exact result, but x87 trigonometric FPU instructions are only that - // accurate within [-pi/4, pi/4]. Examine the passed value and provide - // a slow path for inputs outside of that interval. - - @MethodSubstitution(guard = MathGuard.class) - public static double sin(double x) { - if (Math.abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.SIN); - } else { - return callDouble1(ARITHMETIC_SIN, x); - } - } - - @MethodSubstitution(guard = MathGuard.class) - public static double cos(double x) { - if (Math.abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.COS); - } else { - return callDouble1(ARITHMETIC_COS, x); - } - } - - @MethodSubstitution(guard = MathGuard.class) - public static double tan(double x) { - if (Math.abs(x) < PI_4) { - return MathIntrinsicNode.compute(x, Operation.TAN); - } else { - return callDouble1(ARITHMETIC_TAN, x); - } - } - - public static class MathGuard implements SubstitutionGuard { - public boolean execute() { - // FIXME should return whether the current compilation target supports these - String arch = System.getProperty("os.arch"); - return arch.equals("amd64") || arch.equals("x86_64"); - } - } - - public static final ForeignCallDescriptor ARITHMETIC_SIN = new ForeignCallDescriptor("arithmeticSin", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_COS = new ForeignCallDescriptor("arithmeticCos", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_TAN = new ForeignCallDescriptor("arithmeticTan", double.class, double.class); - public static final ForeignCallDescriptor ARITHMETIC_POW = new ForeignCallDescriptor("arithmeticPow", double.class, double.class, double.class); - - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) - private static native double callDouble1(@ConstantNodeParameter ForeignCallDescriptor descriptor, double value); - - @NodeIntrinsic(value = ForeignCallNode.class, setStampFromReturnType = true) - private static native double callDouble2(@ConstantNodeParameter ForeignCallDescriptor descriptor, double a, double b); -} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Apr 08 11:24:16 2015 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/StandardGraphBuilderPlugins.java Wed Apr 08 22:09:05 2015 +0200 @@ -301,17 +301,6 @@ return true; } }); - r.register2("pow", Double.TYPE, Double.TYPE, new InvocationPlugin() { - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode x, ValueNode y) { - ValueNode folded = MathPowNode.tryFold(x, y); - if (folded != null) { - b.addPush(Kind.Double, folded); - } else { - b.addPush(Kind.Double, new MathPowNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnType(), x, y)); - } - return true; - } - }); } public static class UnsignedMathPlugin implements InvocationPlugin { diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathIntrinsicNode.java Wed Apr 08 11:24:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.gen.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.calc.*; -import com.oracle.graal.nodes.spi.*; - -@NodeInfo -public final class MathIntrinsicNode extends UnaryNode implements ArithmeticLIRLowerable { - - public static final NodeClass TYPE = NodeClass.create(MathIntrinsicNode.class); - protected final Operation operation; - - public enum Operation { - LOG, - LOG10, - SIN, - COS, - TAN - } - - public Operation operation() { - return operation; - } - - public static ValueNode create(ValueNode value, Operation op) { - ValueNode c = tryConstantFold(value, op); - if (c != null) { - return c; - } - return new MathIntrinsicNode(value, op); - } - - protected static ValueNode tryConstantFold(ValueNode value, Operation op) { - if (value.isConstant()) { - double ret = doCompute(value.asJavaConstant().asDouble(), op); - return ConstantNode.forDouble(ret); - } - return null; - } - - protected MathIntrinsicNode(ValueNode value, Operation op) { - super(TYPE, StampFactory.forKind(Kind.Double), value); - assert value.stamp() instanceof FloatStamp && PrimitiveStamp.getBits(value.stamp()) == 64; - this.operation = op; - } - - @Override - public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value input = builder.operand(getValue()); - Value result; - switch (operation()) { - case LOG: - result = gen.emitMathLog(input, false); - break; - case LOG10: - result = gen.emitMathLog(input, true); - break; - case SIN: - result = gen.emitMathSin(input); - break; - case COS: - result = gen.emitMathCos(input); - break; - case TAN: - result = gen.emitMathTan(input); - break; - default: - throw GraalInternalError.shouldNotReachHere(); - } - builder.setResult(this, result); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - ValueNode c = tryConstantFold(forValue, operation()); - if (c != null) { - return c; - } - return this; - } - - @NodeIntrinsic - public static native double compute(double value, @ConstantNodeParameter Operation op); - - private static double doCompute(double value, Operation op) { - switch (op) { - case LOG: - return Math.log(value); - case LOG10: - return Math.log10(value); - case SIN: - return Math.sin(value); - case COS: - return Math.cos(value); - case TAN: - return Math.tan(value); - default: - throw new GraalInternalError("unknown op %s", op); - } - } -} diff -r a74c785068e0 -r 3081a57f95fd graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/MathPowNode.java Wed Apr 08 11:24:16 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.graal.replacements.nodes; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.graph.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.CallTargetNode.InvokeKind; - -@NodeInfo -public final class MathPowNode extends MacroStateSplitNode implements Canonicalizable.Binary { - - public static final NodeClass TYPE = NodeClass.create(MathPowNode.class); - - public MathPowNode(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, int bci, JavaType returnType, ValueNode x, ValueNode y) { - super(TYPE, invokeKind, targetMethod, bci, returnType, x, y); - } - - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - ValueNode folded = tryFold(forX, forY); - return folded != null ? folded : this; - } - - public static ValueNode tryFold(ValueNode x, ValueNode y) { - if (x.isConstant() && y.isConstant()) { - double xPrim = x.asJavaConstant().asDouble(); - double yPrim = y.asJavaConstant().asDouble(); - return ConstantNode.forDouble(Math.pow(xPrim, yPrim)); - } - return null; - } - - public ValueNode getX() { - return arguments.get(0); - } - - public ValueNode getY() { - return arguments.get(1); - } -} diff -r a74c785068e0 -r 3081a57f95fd mx/suite.py --- a/mx/suite.py Wed Apr 08 11:24:16 2015 +0200 +++ b/mx/suite.py Wed Apr 08 22:09:05 2015 +0200 @@ -598,6 +598,7 @@ "dependencies" : [ "com.oracle.graal.replacements", "com.oracle.graal.amd64", + "com.oracle.graal.lir.amd64", ], "checkstyle" : "com.oracle.graal.graph", "javaCompliance" : "1.8",