# HG changeset patch # User Doug Simon # Date 1389742496 -3600 # Node ID 1dabd01a73bd1af4af8113e1b80b1076a60b735b # Parent c07c88aca256e23047dda85782b680fed31fc482 PTX backend can alter compilation pipeline to offload selected code to the GPU diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Wed Jan 15 00:33:34 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.hsail/src/com/oracle/graal/hotspot/hsail/HSAILHotSpotBackendFactory.java Wed Jan 15 00:34:56 2014 +0100 @@ -29,6 +29,7 @@ import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hsail.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; @ServiceProvider(HotSpotBackendFactory.class) @@ -50,7 +51,7 @@ Providers p = new Providers(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, null); Replacements replacements = new HSAILHotSpotReplacementsImpl(p, assumptions, codeCache.getTarget(), host.getReplacements()); HotSpotDisassemblerProvider disassembler = host.getDisassembler(); - HotSpotSuitesProvider suites = host.getSuites(); + SuitesProvider suites = host.getSuites(); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); return new HSAILHotSpotBackend(runtime, providers); diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.ptx.test/src/com/oracle/graal/hotspot/ptx/test/PTXLaunchKernelTest.java --- a/graal/com.oracle.graal.hotspot.ptx.test/src/com/oracle/graal/hotspot/ptx/test/PTXLaunchKernelTest.java Wed Jan 15 00:33:34 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx.test/src/com/oracle/graal/hotspot/ptx/test/PTXLaunchKernelTest.java Wed Jan 15 00:34:56 2014 +0100 @@ -22,98 +22,42 @@ */ package com.oracle.graal.hotspot.ptx.test; -import static com.oracle.graal.api.code.CodeUtil.*; -import static com.oracle.graal.compiler.GraalCompiler.*; import static com.oracle.graal.hotspot.HotSpotGraalRuntime.*; import org.junit.*; import com.oracle.graal.api.code.*; -import com.oracle.graal.api.code.CallingConvention.Type; import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.target.*; import com.oracle.graal.compiler.test.*; -import com.oracle.graal.debug.*; -import com.oracle.graal.debug.Debug.Scope; -import com.oracle.graal.hotspot.*; -import com.oracle.graal.hotspot.bridge.*; -import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.hotspot.ptx.*; -import com.oracle.graal.lir.asm.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.phases.*; -import com.oracle.graal.phases.tiers.*; import com.oracle.graal.ptx.*; /** - * Tests the mechanism for launching a PTX kernel method via wrapper code generated by - * {@link PTXLaunchKernelGraphKit}. + * Tests the mechanism for launching a PTX kernel method via wrapper code. */ public class PTXLaunchKernelTest extends GraalCompilerTest { - public PTXLaunchKernelTest() { - super(); - } - /** * Compiles and installs PTX kernel code for a given method. */ - static class PTXKernel extends GraalCompilerTest { - public PTXKernel() { - super(PTX.class); - } - - static CompilerToGPU toGPU = HotSpotGraalRuntime.runtime().getCompilerToGPU(); - static boolean validDevice = toGPU.deviceInit(); - - @Override - protected CompilationResult compile(ResolvedJavaMethod method, StructuredGraph graph) { - Assume.assumeTrue(getBackend() instanceof PTXHotSpotBackend); - - /* - * Use Suites.createDefaultSuites() instead of GraalCompilerTest.suites. The - * GraalCompilerTest.suites variable contains the Suites for the HotSpotRuntime. This - * code will not run on HotSpot, so it should use the plain Graal default suites, - * without HotSpot specific phases. - * - * Ultimately we might want to have both the kernel and the code natively compiled for - * GPU fallback to CPU in cases of ECC failure on kernel invocation. - */ - CallingConvention cc = getCallingConvention(getCodeCache(), Type.JavaCallee, graph.method(), false); - Suites suites = Suites.createDefaultSuites(); - PTXHotSpotBackend ptxBackend = (PTXHotSpotBackend) getBackend(); - ExternalCompilationResult kernelResult = compileGraph(graph, cc, method, getProviders(), ptxBackend, ptxBackend.getTarget(), null, getDefaultGraphBuilderSuite(), - OptimisticOptimizations.NONE, getProfilingInfo(graph), new SpeculationLog(), suites, true, new ExternalCompilationResult(), CompilationResultBuilderFactory.Default); - - Assume.assumeTrue(validDevice); - Assert.assertTrue(kernelResult.getTargetCode() != null); - try (Scope ds = Debug.scope("GeneratingKernel")) { - long kernel = toGPU.generateKernel(kernelResult.getTargetCode(), method.getName()); - kernelResult.setEntryPoint(kernel); - } catch (Throwable e) { - throw Debug.handle(e); + StructuredGraph getKernelGraph(final ResolvedJavaMethod method) { + Backend backend = runtime().getBackend(PTX.class); + Assume.assumeTrue(backend instanceof PTXHotSpotBackend); + PTXHotSpotBackend ptxBackend = (PTXHotSpotBackend) backend; + Assume.assumeTrue(ptxBackend.isDeviceInitialized()); + return new PTXGraphProducer(runtime().getHostBackend(), ptxBackend) { + @Override + protected boolean canOffloadToGPU(ResolvedJavaMethod m) { + return m == method; } - return kernelResult; - } - - @Override - protected InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult) { - HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) getCodeCache(); - return codeCache.addExternalMethod(method, compResult); - } - - /** - * Compiles and installs PTX kernel code for {@code method}. - */ - InstalledCode getKernelCode(ResolvedJavaMethod method, StructuredGraph graph) { - return getCode(method, graph, true); - } + }.getGraphFor(method); } @Override protected InstalledCode getCode(ResolvedJavaMethod method, StructuredGraph graph) { - InstalledCode kernelCode = new PTXKernel().getKernelCode(method, graph); - StructuredGraph launchKernel = new PTXLaunchKernelGraphKit(method, kernelCode.getStart(), runtime().getHostProviders()).getGraph(); - return super.getCode(method, launchKernel); + return super.getCode(method, getKernelGraph(method)); } @Test diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXGraphProducer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXGraphProducer.java Wed Jan 15 00:34:56 2014 +0100 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2012, 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.hotspot.ptx; + +import static com.oracle.graal.api.code.CodeUtil.*; +import static com.oracle.graal.compiler.GraalCompiler.*; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.code.CallingConvention.Type; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.debug.*; +import com.oracle.graal.debug.Debug.Scope; +import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.HotSpotReplacementsImpl.GraphProducer; +import com.oracle.graal.hotspot.bridge.*; +import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.lir.asm.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class PTXGraphProducer implements GraphProducer { + private final CompilerToGPU toGPU; + private final HotSpotBackend hostBackend; + private final HotSpotBackend ptxBackend; + + public PTXGraphProducer(HotSpotBackend hostBackend, HotSpotBackend ptxBackend) { + this.hostBackend = hostBackend; + this.ptxBackend = ptxBackend; + this.toGPU = ptxBackend.getRuntime().getCompilerToGPU(); + } + + public StructuredGraph getGraphFor(ResolvedJavaMethod method) { + if (canOffloadToGPU(method)) { + + StructuredGraph graph = new StructuredGraph(method); + HotSpotProviders providers = ptxBackend.getProviders(); + CallingConvention cc = getCallingConvention(providers.getCodeCache(), Type.JavaCallee, method, false); + PhaseSuite graphBuilderSuite = providers.getSuites().getDefaultGraphBuilderSuite(); + Suites suites = providers.getSuites().getDefaultSuites(); + ExternalCompilationResult kernelResult = compileGraph(graph, cc, method, providers, ptxBackend, ptxBackend.getTarget(), null, graphBuilderSuite, OptimisticOptimizations.NONE, + getProfilingInfo(graph), new SpeculationLog(), suites, true, new ExternalCompilationResult(), CompilationResultBuilderFactory.Default); + + try (Scope ds = Debug.scope("GeneratingKernel")) { + long kernel = toGPU.generateKernel(kernelResult.getTargetCode(), method.getName()); + kernelResult.setEntryPoint(kernel); + } catch (Throwable e) { + throw Debug.handle(e); + } + + InstalledCode installedCode = providers.getCodeCache().addExternalMethod(method, kernelResult); + return new PTXLaunchKernelGraphKit(method, installedCode.getStart(), hostBackend.getProviders()).getGraph(); + } + return null; + } + + protected boolean canOffloadToGPU(ResolvedJavaMethod method) { + return method.getName().contains("lambda$main$") & method.isSynthetic(); + } +} diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Jan 15 00:33:34 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackend.java Wed Jan 15 00:34:56 2014 +0100 @@ -39,6 +39,8 @@ import com.oracle.graal.compiler.ptx.*; import com.oracle.graal.graph.*; import com.oracle.graal.hotspot.*; +import com.oracle.graal.hotspot.HotSpotReplacementsImpl.GraphProducer; +import com.oracle.graal.hotspot.bridge.*; import com.oracle.graal.hotspot.meta.*; import com.oracle.graal.lir.*; import com.oracle.graal.lir.LIRInstruction.OperandFlag; @@ -78,16 +80,35 @@ @Override public void completeInitialization() { HotSpotHostForeignCallsProvider hostForeignCalls = (HotSpotHostForeignCallsProvider) getRuntime().getHostProviders().getForeignCalls(); - long launchKernel = getRuntime().getCompilerToGPU().getLaunchKernelAddress(); - hostForeignCalls.registerForeignCall(LAUNCH_KERNEL, launchKernel, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + CompilerToGPU compilerToGPU = getRuntime().getCompilerToGPU(); + deviceInitialized = compilerToGPU.deviceInit(); + if (deviceInitialized) { + long launchKernel = compilerToGPU.getLaunchKernelAddress(); + hostForeignCalls.registerForeignCall(LAUNCH_KERNEL, launchKernel, NativeCall, DESTROYS_REGISTERS, NOT_LEAF, NOT_REEXECUTABLE, ANY_LOCATION); + } super.completeInitialization(); } + private boolean deviceInitialized; + @Override public FrameMap newFrameMap() { return new PTXFrameMap(getCodeCache()); } + public boolean isDeviceInitialized() { + return deviceInitialized; + } + + @Override + public GraphProducer getGraphProducer() { + if (!deviceInitialized) { + // GPU could not be initialized so offload is disabled + return null; + } + return new PTXGraphProducer(getRuntime().getHostBackend(), this); + } + static final class RegisterAnalysis extends ValueProcedure { private final SortedSet signed32 = new TreeSet<>(); private final SortedSet signed64 = new TreeSet<>(); diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java --- a/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Wed Jan 15 00:33:34 2014 +0100 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotBackendFactory.java Wed Jan 15 00:34:56 2014 +0100 @@ -27,7 +27,9 @@ import com.oracle.graal.api.runtime.*; import com.oracle.graal.hotspot.*; import com.oracle.graal.hotspot.meta.*; +import com.oracle.graal.java.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.ptx.*; @ServiceProvider(HotSpotBackendFactory.class) @@ -43,7 +45,7 @@ LoweringProvider lowerer = new PTXHotSpotLoweringProvider(host.getLowerer()); Replacements replacements = host.getReplacements(); HotSpotDisassemblerProvider disassembler = host.getDisassembler(); - HotSpotSuitesProvider suites = host.getSuites(); + SuitesProvider suites = new DefaultSuitesProvider(); HotSpotRegistersProvider registers = new HotSpotRegisters(PTX.tid, Register.None, Register.None); HotSpotProviders providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements, disassembler, suites, registers); return new PTXHotSpotBackend(runtime, providers); diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotSuitesProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.hotspot.ptx/src/com/oracle/graal/hotspot/ptx/PTXHotSpotSuitesProvider.java Wed Jan 15 00:34:56 2014 +0100 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2012, 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.hotspot.ptx; + +import com.oracle.graal.java.*; +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class PTXHotSpotSuitesProvider implements SuitesProvider { + + private final Suites defaultSuites; + private final PhaseSuite defaultGraphBuilderSuite; + + public PTXHotSpotSuitesProvider() { + this.defaultGraphBuilderSuite = createGraphBuilderSuite(); + this.defaultSuites = createSuites(); + } + + public Suites getDefaultSuites() { + return defaultSuites; + } + + public Suites createSuites() { + return Suites.createDefaultSuites(); + } + + public PhaseSuite getDefaultGraphBuilderSuite() { + return defaultGraphBuilderSuite; + } + + protected PhaseSuite createGraphBuilderSuite() { + PhaseSuite suite = new PhaseSuite<>(); + suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault())); + return suite; + } + +} diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Wed Jan 15 00:33:34 2014 +0100 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/meta/HotSpotProviders.java Wed Jan 15 00:34:56 2014 +0100 @@ -24,6 +24,7 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.phases.tiers.*; import com.oracle.graal.phases.util.*; /** @@ -33,11 +34,11 @@ public class HotSpotProviders extends Providers { private final HotSpotDisassemblerProvider disassembler; - private final HotSpotSuitesProvider suites; + private final SuitesProvider suites; private final HotSpotRegistersProvider registers; public HotSpotProviders(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, HotSpotForeignCallsProvider foreignCalls, - LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, HotSpotSuitesProvider suites, HotSpotRegistersProvider registers) { + LoweringProvider lowerer, Replacements replacements, HotSpotDisassemblerProvider disassembler, SuitesProvider suites, HotSpotRegistersProvider registers) { super(metaAccess, codeCache, constantReflection, foreignCalls, lowerer, replacements); this.disassembler = disassembler; this.suites = suites; @@ -63,7 +64,7 @@ return (HotSpotForeignCallsProvider) super.getForeignCalls(); } - public HotSpotSuitesProvider getSuites() { + public SuitesProvider getSuites() { return suites; } diff -r c07c88aca256 -r 1dabd01a73bd graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/DefaultSuitesProvider.java Wed Jan 15 00:34:56 2014 +0100 @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2012, 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.java; + +import com.oracle.graal.phases.*; +import com.oracle.graal.phases.tiers.*; + +public class DefaultSuitesProvider implements SuitesProvider { + + private final Suites defaultSuites; + private final PhaseSuite defaultGraphBuilderSuite; + + public DefaultSuitesProvider() { + this.defaultGraphBuilderSuite = createGraphBuilderSuite(); + this.defaultSuites = createSuites(); + } + + public Suites getDefaultSuites() { + return defaultSuites; + } + + public Suites createSuites() { + return Suites.createDefaultSuites(); + } + + public PhaseSuite getDefaultGraphBuilderSuite() { + return defaultGraphBuilderSuite; + } + + protected PhaseSuite createGraphBuilderSuite() { + PhaseSuite suite = new PhaseSuite<>(); + suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault())); + return suite; + } + +} diff -r c07c88aca256 -r 1dabd01a73bd src/share/vm/graal/graalCompilerToGPU.cpp --- a/src/share/vm/graal/graalCompilerToGPU.cpp Wed Jan 15 00:33:34 2014 +0100 +++ b/src/share/vm/graal/graalCompilerToGPU.cpp Wed Jan 15 00:34:56 2014 +0100 @@ -175,11 +175,16 @@ } C2V_END +JRT_ENTRY(jlong, invalidLaunchKernel(JavaThread* thread)) + SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_LinkageError(), "invalid kernel launch function"); + return 0L; +JRT_END + C2V_VMENTRY(jlong, getLaunchKernelAddress, (JNIEnv *env, jobject)) if (gpu::get_target_il_type() == gpu::PTX) { return (jlong) gpu::Ptx::execute_kernel_from_vm; } - return 0L; + return (jlong) invalidLaunchKernel; C2V_END C2V_VMENTRY(jboolean, deviceInit, (JNIEnv *env, jobject))