Skip to content

Commit

Permalink
Merge pull request #462 from mairooni/feat/pointer_copies
Browse files Browse the repository at this point in the history
Support conditional copy-by-reference in local memory
  • Loading branch information
jjfumero authored Jun 26, 2024
2 parents 469765f + fadb5ea commit 1be5451
Show file tree
Hide file tree
Showing 20 changed files with 997 additions and 12 deletions.
1 change: 1 addition & 0 deletions tornado-assembly/src/bin/tornado-test
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ __TEST_THE_WORLD__ = [
## TornadoVM standard test-suite
TestEntry("uk.ac.manchester.tornado.unittests.TestHello"),
TestEntry("uk.ac.manchester.tornado.unittests.arrays.TestArrays"),
TestEntry("uk.ac.manchester.tornado.unittests.arrays.TestArrayCopies"),
TestEntry("uk.ac.manchester.tornado.unittests.functional.TestLambdas"),
TestEntry("uk.ac.manchester.tornado.unittests.vectortypes.TestFloats"),
TestEntry("uk.ac.manchester.tornado.unittests.vectortypes.TestHalfFloats"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,22 @@ public static class OCLBinaryTemplate extends OCLBinaryOp {
public static final OCLBinaryTemplate NEW_PRIVATE_SHORT_ARRAY = new OCLBinaryTemplate("new private array short", "__private short %s[%s]");
public static final OCLBinaryTemplate NEW_PRIVATE_BYTE_ARRAY = new OCLBinaryTemplate("new private array byte", "__private byte %s[%s]");

public static final OCLBinaryTemplate PRIVATE_INT_ARRAY_PTR = new OCLBinaryTemplate("private pointer array int", "__private int* %s = %s");
public static final OCLBinaryTemplate PRIVATE_CHAR_ARRAY_PTR = new OCLBinaryTemplate("private pointer array char", "__private char* %s = %s");
public static final OCLBinaryTemplate PRIVATE_FLOAT_ARRAY_PTR = new OCLBinaryTemplate("private pointer array float", "__private float* %s = %s");
public static final OCLBinaryTemplate PRIVATE_DOUBLE_ARRAY_PTR = new OCLBinaryTemplate("private pointer array double", "__private double* %s = %s");
public static final OCLBinaryTemplate PRIVATE_LONG_ARRAY_PTR = new OCLBinaryTemplate("private pointer array long", "__private long* %s = %s");
public static final OCLBinaryTemplate PRIVATE_SHORT_ARRAY_PTR = new OCLBinaryTemplate("private pointer array short", "__private short* %s = %s");
public static final OCLBinaryTemplate PRIVATE_BYTE_ARRAY_PTR = new OCLBinaryTemplate("private pointer array byte", "__private byte* %s = %s");

public static final OCLBinaryTemplate PRIVATE_INT_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array int", "__private int* %s = ((__private int *) %s)");
public static final OCLBinaryTemplate PRIVATE_CHAR_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array char", "__private char* %s = ((__private char *) %s)");
public static final OCLBinaryTemplate PRIVATE_FLOAT_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array float", "__private float* %s = ((__private float *) %s)");
public static final OCLBinaryTemplate PRIVATE_DOUBLE_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array double", "__private double* %s = ((__private double *) %s)");
public static final OCLBinaryTemplate PRIVATE_LONG_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array long", "__private long* %s = ((__private long *) %s)");
public static final OCLBinaryTemplate PRIVATE_SHORT_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array short", "__private short* %s = ((__private short *) %s)");
public static final OCLBinaryTemplate PRIVATE_BYTE_ARRAY_PTR_COPY = new OCLBinaryTemplate("private pointer copy array byte", "__private byte* %s = ((__private byte *) %s)");

public static final OCLBinaryTemplate NEW_LOCAL_FLOAT_ARRAY = new OCLBinaryTemplate("local memory array float", "__local float %s[%s]");
public static final OCLBinaryTemplate NEW_LOCAL_INT_ARRAY = new OCLBinaryTemplate("local memory array int", "__local int %s[%s]");
public static final OCLBinaryTemplate NEW_LOCAL_DOUBLE_ARRAY = new OCLBinaryTemplate("local memory array double", "__local double %s[%s]");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import uk.ac.manchester.tornado.drivers.opencl.graal.phases.OCLFPGAThreadScheduler;
import uk.ac.manchester.tornado.drivers.opencl.graal.phases.TornadoAtomicsParametersPhase;
import uk.ac.manchester.tornado.drivers.opencl.graal.phases.TornadoAtomicsScheduling;
import uk.ac.manchester.tornado.drivers.opencl.graal.phases.TornadoFixedArrayCopyPhase;
import uk.ac.manchester.tornado.drivers.opencl.graal.phases.TornadoHalfFloatVectorOffset;
import uk.ac.manchester.tornado.runtime.common.TornadoOptions;
import uk.ac.manchester.tornado.runtime.graal.compiler.TornadoLowTier;
Expand Down Expand Up @@ -76,6 +77,8 @@ public OCLLowTier(OptionValues options, TornadoDeviceContext tornadoDeviceContex
}
appendPhase(new UseTrappingNullChecksPhase());

appendPhase(new TornadoFixedArrayCopyPhase());

appendPhase(new AddressLoweringByNodePhase(addressLowering));

appendPhase(new DeadCodeEliminationPhase(DeadCodeEliminationPhase.Optionality.Required));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import uk.ac.manchester.tornado.drivers.opencl.graal.OCLArchitecture;
import uk.ac.manchester.tornado.drivers.opencl.graal.OCLArchitecture.OCLMemoryBase;
import uk.ac.manchester.tornado.drivers.opencl.graal.nodes.FixedArrayNode;
import uk.ac.manchester.tornado.drivers.opencl.graal.nodes.FixedArrayCopyNode;
import uk.ac.manchester.tornado.drivers.opencl.graal.nodes.LocalArrayNode;
import uk.ac.manchester.tornado.runtime.graal.nodes.calc.TornadoAddressArithmeticNode;

Expand All @@ -45,6 +46,8 @@ public AddressNode lower(ValueNode base, ValueNode offset) {
OCLMemoryBase memoryRegister = OCLArchitecture.globalSpace;
if (base instanceof FixedArrayNode fixedArrayNode) {
memoryRegister = fixedArrayNode.getMemoryRegister();
} else if (base instanceof FixedArrayCopyNode fixedArrayCopyNode) {
memoryRegister = fixedArrayCopyNode.getMemoryRegister();
} else if (base instanceof LocalArrayNode localArrayNode) {
memoryRegister = localArrayNode.getMemoryRegister();
} else if (!((base instanceof TornadoAddressArithmeticNode) || (base instanceof ParameterNode) || (base instanceof ReadNode) || (base instanceof FloatingReadNode) || (base instanceof PiNode))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,32 @@ public static OCLAssembler.OCLBinaryTemplate resolvePrivateTemplateType(JavaKind
return null;
}

public static OCLAssembler.OCLBinaryTemplate resolvePrivatePointerTemplate(JavaKind type) {
return switch (type) {
case Int -> OCLAssembler.OCLBinaryTemplate.PRIVATE_INT_ARRAY_PTR;
case Double -> OCLAssembler.OCLBinaryTemplate.PRIVATE_DOUBLE_ARRAY_PTR;
case Float -> OCLAssembler.OCLBinaryTemplate.PRIVATE_FLOAT_ARRAY_PTR;
case Short -> OCLAssembler.OCLBinaryTemplate.PRIVATE_SHORT_ARRAY_PTR;
case Long -> OCLAssembler.OCLBinaryTemplate.PRIVATE_LONG_ARRAY_PTR;
case Char -> OCLAssembler.OCLBinaryTemplate.PRIVATE_CHAR_ARRAY_PTR;
case Byte -> OCLAssembler.OCLBinaryTemplate.PRIVATE_BYTE_ARRAY_PTR;
default -> null;
};
}

public static OCLAssembler.OCLBinaryTemplate resolvePrivatePointerCopyTemplate(JavaKind type) {
return switch (type) {
case Int -> OCLAssembler.OCLBinaryTemplate.PRIVATE_INT_ARRAY_PTR_COPY;
case Double -> OCLAssembler.OCLBinaryTemplate.PRIVATE_DOUBLE_ARRAY_PTR_COPY;
case Float -> OCLAssembler.OCLBinaryTemplate.PRIVATE_FLOAT_ARRAY_PTR_COPY;
case Short -> OCLAssembler.OCLBinaryTemplate.PRIVATE_SHORT_ARRAY_PTR_COPY;
case Long -> OCLAssembler.OCLBinaryTemplate.PRIVATE_LONG_ARRAY_PTR_COPY;
case Char -> OCLAssembler.OCLBinaryTemplate.PRIVATE_CHAR_ARRAY_PTR_COPY;
case Byte -> OCLAssembler.OCLBinaryTemplate.PRIVATE_BYTE_ARRAY_PTR_COPY;
default -> null;
};
}

public static OCLAssembler.OCLBinaryTemplate resolveTemplateType(JavaKind type) {
if (type == JavaKind.Int) {
return OCLAssembler.OCLBinaryTemplate.NEW_LOCAL_INT_ARRAY;
Expand Down Expand Up @@ -283,6 +309,14 @@ public static OCLAssembler.OCLBinaryTemplate resolvePrivateTemplateType(Resolved
return resolvePrivateTemplateType(type.getJavaKind());
}

public static OCLAssembler.OCLBinaryTemplate resolvePrivatePointerTemplate(ResolvedJavaType type) {
return resolvePrivatePointerTemplate(type.getJavaKind());
}

public static OCLAssembler.OCLBinaryTemplate resolvePrivatePointerCopyTemplate(ResolvedJavaType type) {
return resolvePrivatePointerCopyTemplate(type.getJavaKind());
}

public static OCLKind resolveToVectorKind(ResolvedJavaType type) {
if (!type.isPrimitive() && type.getAnnotation(Vector.class) != null) {
String typeName = type.getName();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (c) 2024, APT Group, Department of Computer Science,
* School of Engineering, The University of Manchester. All rights reserved.
* Copyright (c) 2009, 2017, 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.
*
*/
package uk.ac.manchester.tornado.drivers.opencl.graal.nodes;

import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.ResolvedJavaType;
import jdk.vm.ci.meta.Value;
import org.graalvm.compiler.core.common.LIRKind;
import org.graalvm.compiler.core.common.type.StampFactory;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.lir.Variable;
import org.graalvm.compiler.nodeinfo.NodeInfo;
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.calc.FloatingNode;
import org.graalvm.compiler.nodes.spi.LIRLowerable;
import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;

import uk.ac.manchester.tornado.drivers.opencl.graal.OCLArchitecture;
import uk.ac.manchester.tornado.drivers.opencl.graal.asm.OCLAssembler;
import uk.ac.manchester.tornado.drivers.opencl.graal.lir.OCLBinary;
import uk.ac.manchester.tornado.drivers.opencl.graal.lir.OCLLIRStmt;
import uk.ac.manchester.tornado.drivers.opencl.graal.lir.OCLKind;

/**
* This node generates a pointer copy between two arrays in private memory.
*/
@NodeInfo
public class FixedArrayCopyNode extends FloatingNode implements LIRLowerable {

public static final NodeClass<FixedArrayCopyNode> TYPE = NodeClass.create(FixedArrayCopyNode.class);

@Input
protected ValuePhiNode conditionalPhiNode;

protected ResolvedJavaType elementType;
protected OCLAssembler.OCLBinaryTemplate pointerCopyTemplate;
protected OCLArchitecture.OCLMemoryBase memoryRegister;

public FixedArrayCopyNode(ValuePhiNode conditionalPhiNode, ResolvedJavaType elementType, OCLArchitecture.OCLMemoryBase memoryRegister) {
super(TYPE, StampFactory.forKind(JavaKind.Object));
this.conditionalPhiNode = conditionalPhiNode;
this.elementType = elementType;
this.memoryRegister = memoryRegister;
this.pointerCopyTemplate = OCLKind.resolvePrivatePointerCopyTemplate(elementType);
}

public OCLArchitecture.OCLMemoryBase getMemoryRegister() {
return memoryRegister;
}

@Override
public void generate(NodeLIRBuilderTool gen) {
LIRKind lirKind = LIRKind.value(gen.getLIRGeneratorTool().target().arch.getWordKind());
final Variable ptr = gen.getLIRGeneratorTool().newVariable(lirKind);
Value fixedArrayValue = gen.operand(conditionalPhiNode);
final OCLBinary.Expr declarationPtr = new OCLBinary.Expr(pointerCopyTemplate, lirKind, ptr, fixedArrayValue);
final OCLLIRStmt.ExprStmt ptrExpr = new OCLLIRStmt.ExprStmt(declarationPtr);
gen.getLIRGeneratorTool().append(ptrExpr);
gen.setResult(this, ptr);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2020, APT Group, Department of Computer Science,
* Copyright (c) 2018, 2020, 2024, APT Group, Department of Computer Science,
* The University of Manchester. All rights reserved.
* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
Expand Down Expand Up @@ -52,6 +52,7 @@ public class FixedArrayNode extends FixedNode implements LIRLowerable {
protected OCLMemoryBase memoryRegister;
protected ResolvedJavaType elementType;
protected OCLBinaryTemplate arrayTemplate;
protected OCLBinaryTemplate pointerTemplate;

public FixedArrayNode(OCLMemoryBase memoryRegister, ResolvedJavaType elementType, ConstantNode length) {
super(TYPE, StampFactory.objectNonNull(TypeReference.createTrustedWithoutAssumptions(elementType.getArrayClass())));
Expand All @@ -60,6 +61,7 @@ public FixedArrayNode(OCLMemoryBase memoryRegister, ResolvedJavaType elementType
this.elementType = elementType;
this.elementKind = OCLKind.fromResolvedJavaType(elementType);
this.arrayTemplate = OCLKind.resolvePrivateTemplateType(elementType);
this.pointerTemplate = OCLKind.resolvePrivatePointerTemplate(elementType);
}

public OCLMemoryBase getMemoryRegister() {
Expand All @@ -70,16 +72,24 @@ public ConstantNode getLength() {
return length;
}

public ResolvedJavaType getElementType() {
return elementType;
}

@Override
public void generate(NodeLIRBuilderTool gen) {
// generate declaration of private array
final Value lengthValue = gen.operand(length);

LIRKind lirKind = LIRKind.value(gen.getLIRGeneratorTool().target().arch.getWordKind());
final Variable variable = gen.getLIRGeneratorTool().newVariable(lirKind);
final OCLBinary.Expr declaration = new OCLBinary.Expr(arrayTemplate, lirKind, variable, lengthValue);

final OCLLIRStmt.ExprStmt expr = new OCLLIRStmt.ExprStmt(declaration);
gen.getLIRGeneratorTool().append(expr);
gen.setResult(this, variable);
final OCLLIRStmt.ExprStmt arrayExpr = new OCLLIRStmt.ExprStmt(declaration);
gen.getLIRGeneratorTool().append(arrayExpr);
// generate pointer to private array
final Variable ptr = gen.getLIRGeneratorTool().newVariable(lirKind);
final OCLBinary.Expr declarationPtr = new OCLBinary.Expr(pointerTemplate, lirKind, ptr, variable);
final OCLLIRStmt.ExprStmt ptrExpr = new OCLLIRStmt.ExprStmt(declarationPtr);
gen.getLIRGeneratorTool().append(ptrExpr);
gen.setResult(this, ptr);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
* Copyright (c) 2024, APT Group, Department of Computer Science,
* The University of Manchester. All rights reserved.
* Copyright (c) 2009, 2017, 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.
*
*/
package uk.ac.manchester.tornado.drivers.opencl.graal.phases;

import jdk.vm.ci.meta.ResolvedJavaType;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.nodes.GraphState;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.nodes.ValuePhiNode;
import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
import org.graalvm.compiler.phases.Phase;

import uk.ac.manchester.tornado.api.exceptions.TornadoCompilationException;
import uk.ac.manchester.tornado.drivers.opencl.graal.OCLArchitecture;
import uk.ac.manchester.tornado.drivers.opencl.graal.nodes.FixedArrayCopyNode;
import uk.ac.manchester.tornado.drivers.opencl.graal.nodes.FixedArrayNode;

import java.util.Optional;

/**
* This phase examines if a copy takes place between two arrays in private memory based on
* an if condition and, if so, inserts a {@link FixedArrayCopyNode} to generate an update in the references.
*/
public class TornadoFixedArrayCopyPhase extends Phase {

@Override
public Optional<NotApplicable> notApplicableTo(GraphState graphState) {
return ALWAYS_APPLICABLE;
}

protected void run(StructuredGraph graph) {
for (ValuePhiNode phiNode : graph.getNodes().filter(ValuePhiNode.class)) {
if (isFixedArrayCopied(phiNode)) {
FixedArrayNode fixedArrayNode = phiNode.values().filter(FixedArrayNode.class).first();
ResolvedJavaType resolvedJavaType = fixedArrayNode.getElementType();
OCLArchitecture.OCLMemoryBase oclMemoryBase = fixedArrayNode.getMemoryRegister();
OffsetAddressNode offsetAddressNode = phiNode.usages().filter(OffsetAddressNode.class).first();
FixedArrayCopyNode fixedArrayCopyNode = new FixedArrayCopyNode(phiNode, resolvedJavaType, oclMemoryBase);
graph.addWithoutUnique(fixedArrayCopyNode);
offsetAddressNode.replaceFirstInput(phiNode, fixedArrayCopyNode);
// finally, since we know that the data accessed is a fixed array, fix the offset
ValuePhiNode privateIndex = getPrivateArrayIndex(offsetAddressNode.getOffset());
if (privateIndex == null) {
throw new TornadoCompilationException("Index of FixedArrayNode is null.");
}
offsetAddressNode.setOffset(privateIndex);
}
}
}

private static boolean isFixedArrayCopied(ValuePhiNode phiNode) {
return phiNode.usages().filter(OffsetAddressNode.class).isNotEmpty() && phiNode.values().filter(FixedArrayNode.class).isNotEmpty();
}

private static ValuePhiNode getPrivateArrayIndex(Node node) {
// identify the index
for (Node input : node.inputs()) {
if (input instanceof ValuePhiNode phiNode) {
return phiNode;
} else {
return getPrivateArrayIndex(input);
}
}
return null;
}

}
Loading

0 comments on commit 1be5451

Please sign in to comment.