changeset 11739:b8695542d41b

added HSAIL register configuration The main change was to override Backend.newFrameMap() in HSAILBackend to use the HSAIL register configuration. Contributed-by: Vasanth Venkatachalam <vasanth.venkatachalam@amd.com>
author Doug Simon <doug.simon@oracle.com>
date Fri, 20 Sep 2013 21:58:38 +0200
parents aa10794f1574
children a402610bc52b
files graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java
diffstat 3 files changed, 234 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Fri Sep 20 21:14:24 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILBackend.java	Fri Sep 20 21:58:38 2013 +0200
@@ -59,9 +59,12 @@
         paramTypeMap.put("HotSpotResolvedPrimitiveType<long>", "s64");
     }
 
+    /**
+     * Use the HSAIL register set when the compilation target is HSAIL.
+     */
     @Override
     public FrameMap newFrameMap() {
-        return new HSAILFrameMap(runtime(), target, runtime().lookupRegisterConfig());
+        return new HSAILFrameMap(runtime(), target, new HSAILRegisterConfig());
     }
 
     @Override
--- a/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Fri Sep 20 21:14:24 2013 +0200
+++ b/graal/com.oracle.graal.compiler.hsail/src/com/oracle/graal/compiler/hsail/HSAILCompilationResult.java	Fri Sep 20 21:58:38 2013 +0200
@@ -23,33 +23,25 @@
 
 package com.oracle.graal.compiler.hsail;
 
-import static com.oracle.graal.api.code.CodeUtil.*;
-
+import java.lang.reflect.*;
 import java.util.logging.*;
 
 import com.oracle.graal.api.code.*;
-import com.oracle.graal.api.code.CallingConvention.*;
-import com.oracle.graal.api.runtime.Graal;
-import com.oracle.graal.compiler.GraalCompiler;
-import com.oracle.graal.java.GraphBuilderConfiguration;
-import com.oracle.graal.java.GraphBuilderPhase;
-import com.oracle.graal.nodes.StructuredGraph;
-import com.oracle.graal.nodes.spi.GraalCodeCacheProvider;
-import com.oracle.graal.phases.OptimisticOptimizations;
-import com.oracle.graal.phases.PhasePlan;
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.api.runtime.*;
+import com.oracle.graal.compiler.*;
+import com.oracle.graal.compiler.target.*;
+import com.oracle.graal.debug.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.hsail.*;
+import com.oracle.graal.java.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.PhasePlan.PhasePosition;
-import com.oracle.graal.api.meta.*;
-import com.oracle.graal.nodes.type.*;
-import com.oracle.graal.graph.GraalInternalError;
-import com.oracle.graal.debug.*;
-import com.oracle.graal.nodes.*;
-import com.oracle.graal.phases.*;
 import com.oracle.graal.phases.tiers.*;
-import com.oracle.graal.nodes.spi.Replacements;
-import com.oracle.graal.compiler.target.Backend;
-import com.oracle.graal.hsail.*;
-
-import java.lang.reflect.Method;
 
 /**
  * Class that represents a HSAIL compilation result. Includes the compiled HSAIL code.
@@ -96,6 +88,33 @@
         return getHSAILCompilationResult(graph);
     }
 
+    /**
+     * HSAIL doesn't have a calling convention as such. Function arguments are actually passed in
+     * memory but then loaded into registers in the function body. This routine makes sure that
+     * arguments to a kernel or function are loaded (by the kernel or function body) into registers
+     * of the appropriate sizes. For example, int and float parameters should appear in S registers,
+     * whereas double and long parameters should appear in d registers.
+     */
+    public static CallingConvention getHSAILCallingConvention(CallingConvention.Type type, TargetDescription target, ResolvedJavaMethod method, boolean stackOnly) {
+        Signature sig = method.getSignature();
+        JavaType retType = sig.getReturnType(null);
+        int sigCount = sig.getParameterCount(false);
+        JavaType[] argTypes;
+        int argIndex = 0;
+        if (!Modifier.isStatic(method.getModifiers())) {
+            argTypes = new JavaType[sigCount + 1];
+            argTypes[argIndex++] = method.getDeclaringClass();
+        } else {
+            argTypes = new JavaType[sigCount];
+        }
+        for (int i = 0; i < sigCount; i++) {
+            argTypes[argIndex++] = sig.getParameterType(i, null);
+        }
+
+        RegisterConfig registerConfig = new HSAILRegisterConfig();
+        return registerConfig.getCallingConvention(type, retType, argTypes, target, stackOnly);
+    }
+
     public static HSAILCompilationResult getHSAILCompilationResult(StructuredGraph graph) {
         Debug.dump(graph, "Graph");
         TargetDescription target = new TargetDescription(new HSAIL(), true, 8, 0, true);
@@ -105,7 +124,7 @@
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, graphBuilderPhase);
         phasePlan.addPhase(PhasePosition.AFTER_PARSING, new HSAILPhase());
         new HSAILPhase().apply(graph);
-        CallingConvention cc = getCallingConvention(runtime, Type.JavaCallee, graph.method(), false);
+        CallingConvention cc = getHSAILCallingConvention(Type.JavaCallee, target, graph.method(), false);
         try {
             CompilationResult compResult = GraalCompiler.compileGraph(graph, cc, graph.method(), runtime, replacements, hsailBackend, target, null, phasePlan, OptimisticOptimizations.NONE,
                             new SpeculationLog(), suitesProvider.getDefaultSuites(), new CompilationResult());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.hsail/src/com/oracle/graal/hsail/HSAILRegisterConfig.java	Fri Sep 20 21:58:38 2013 +0200
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2009, 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.hsail;
+
+import com.oracle.graal.api.code.*;
+
+import com.oracle.graal.api.code.CallingConvention.Type;
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+
+import static com.oracle.graal.hsail.HSAIL.*;
+
+/**
+ * This class defines a higher level interface for the register allocator to be able to access info
+ * about the {@link HSAIL} register set.
+ * 
+ * Note: In HSAIL, the number of registers of each type is actually a variable number that must
+ * satisfy the equation: Total num of registers = No. of S registers + 2 * (No. of D registers) + 4
+ * * (No. of Q registers) = 128 In other words we can have up to 128S or 64 D or 32Q or a blend.
+ * 
+ * For now we haven't implemented support for a variable sized register file. Instead we've fixed
+ * the number of registers of each type so that they satisfy the above equation. See {@link HSAIL}
+ * for more details.
+ */
+public class HSAILRegisterConfig implements RegisterConfig {
+
+    private final Register[] allocatable = {s0, s1, s2, s3, s4, s5, s6, /* s7, */s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31,
+                    d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15, q0, q1, q2, q3, q4, q5, q6, q7, q8, q9, q10, q11, q12, q13, q14, q15};
+
+    private final Register[] regBitness32 = {s0, s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16, s17, s18, s19, s20, s21, s22, s23, s24, s25, s26, s27, s28, s29, s30, s31};
+    private final Register[] regBitness64 = {d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15};
+    private final RegisterAttributes[] attributesMap = RegisterAttributes.createMap(this, HSAIL.allRegisters);
+
+    @Override
+    public Register getReturnRegister(Kind kind) {
+        switch (kind) {
+            case Boolean:
+            case Byte:
+            case Char:
+            case Short:
+            case Int:
+            case Long:
+            case Object:
+                return s0;
+            case Float:
+            case Double:
+                return d0;
+            case Void:
+            case Illegal:
+                return null;
+            default:
+                throw new UnsupportedOperationException("no return register for type " + kind);
+        }
+    }
+
+    @Override
+    public Register getFrameRegister() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
+        return callingConvention(regBitness32, regBitness64, returnType, parameterTypes, type, target, stackOnly);
+    }
+
+    private CallingConvention callingConvention(Register[] generalParameterRegisters, Register[] longParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type,
+                    TargetDescription target, boolean stackOnly) {
+        AllocatableValue[] locations = new AllocatableValue[parameterTypes.length];
+
+        int currentRegs32 = 0;
+        int currentRegs64 = 0;
+        int currentStackOffset = 0;
+
+        for (int i = 0; i < parameterTypes.length; i++) {
+            final Kind kind = parameterTypes[i].getKind();
+
+            switch (kind) {
+                case Byte:
+                case Boolean:
+                case Short:
+                case Char:
+                case Int:
+                case Float:
+
+                    if (!stackOnly && currentRegs32 < generalParameterRegisters.length) {
+                        Register register = generalParameterRegisters[currentRegs32++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                case Long:
+                case Object:
+                case Double:
+                    if (!stackOnly && currentRegs64 < longParameterRegisters.length) {
+                        Register register = longParameterRegisters[currentRegs64++];
+                        locations[i] = register.asValue(kind);
+                    }
+                    break;
+                default:
+                    throw GraalInternalError.shouldNotReachHere();
+            }
+
+            if (locations[i] == null) {
+                locations[i] = StackSlot.get(kind.getStackKind(), currentStackOffset, !type.out);
+                currentStackOffset += Math.max(target.arch.getSizeInBytes(kind), target.wordSize);
+            }
+        }
+
+        Kind returnKind = returnType == null ? Kind.Void : returnType.getKind();
+        AllocatableValue returnLocation = returnKind == Kind.Void ? Value.ILLEGAL : getReturnRegister(returnKind).asValue(returnKind);
+        return new CallingConvention(currentStackOffset, returnLocation, locations);
+    }
+
+    @Override
+    public Register[] getCallingConventionRegisters(Type type, Kind kind) {
+        throw new GraalInternalError("getCallingConventinoRegisters unimplemented");
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters() {
+        return allocatable.clone();
+    }
+
+    @Override
+    public Register[] getAllocatableRegisters(PlatformKind kind) {
+        Kind k = (Kind) kind;
+        switch (k) {
+            case Int:
+            case Short:
+            case Byte:
+            case Float:
+                return regBitness32.clone();
+            case Long:
+            case Double:
+            case Object:
+                return regBitness64.clone();
+
+            default:
+                throw new GraalInternalError("unknown register allocation");
+        }
+    }
+
+    @Override
+    public Register[] getCallerSaveRegisters() {
+        // TODO Auto-generated method stub
+        return new Register[0];
+    }
+
+    @Override
+    public CalleeSaveLayout getCalleeSaveLayout() {
+        return null;
+    }
+
+    @Override
+    public RegisterAttributes[] getAttributesMap() {
+        return attributesMap.clone();
+    }
+
+    @Override
+    public Register getRegisterForRole(int id) {
+        throw new UnsupportedOperationException();
+    }
+
+    public HSAILRegisterConfig() {
+
+    }
+}