Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for fixed unsafe array buffers #200

Merged
merged 6 commits into from
Jul 23, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ Src/ILGPU.Tests/CompareFloatOperations.cs
Src/ILGPU.Tests/CompareIntOperations.cs
Src/ILGPU.Tests/ConvertFloatOperations.cs
Src/ILGPU.Tests/ConvertIntOperations.cs
Src/ILGPU.Tests/FixedBuffers.cs
Src/ILGPU.Tests/MemoryBufferOperations.cs
Src/ILGPU.Tests/UnaryIntOperations.cs

Expand Down
1 change: 1 addition & 0 deletions Src/ILGPU.Tests/Configurations.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ DebugTests: Debug, Release, O2
DisassemblerTests: Debug, Release, O2
EnumValues: Debug, Release, O2
ExchangeBufferOperations: Debug, Release, O2
FixedBuffers: Debug, Release, O2
KernelEntryPoints: Debug, Release, O2
MemoryBufferOperations : Debug, Release, O2
MemoryCacheOperations : Debug, Release, O2
Expand Down
118 changes: 118 additions & 0 deletions Src/ILGPU.Tests/FixedBuffers.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ include file="Generic/ConfigurationBase.tt" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".cs" #>
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using Xunit;
using Xunit.Abstractions;

#pragma warning disable CA1815 // Override equals and operator equals on value types
#pragma warning disable CA1051 // Do not declare visible instance fields
#pragma warning disable CA2231 // Overload operator equals on overriding value type Equals
#pragma warning disable CS0659 // Type overrides Object.Equals(object o) but does not
// override Object.GetHashCode()

namespace ILGPU.Tests
{
<# foreach (var type in IntTypes) { #>
public unsafe struct FixedBufferStruct<#= type.Name #> :
IXunitSerializable,
IEquatable<FixedBufferStruct<#= type.Name #>>
{
public fixed <#= type.Type #> Data[FixedBuffers.Length];

public FixedBufferStruct<#= type.Name #>(<#= type.Type #> data)
{
for (int i = 0; i < FixedBuffers.Length; ++i)
Data[i] = data;
}

public void Deserialize(IXunitSerializationInfo info)
{
for (int i = 0; i < FixedBuffers.Length; ++i)
Data[i] = info.GetValue<<#= type.Type #>>(nameof(Data) + i);
}

public void Serialize(IXunitSerializationInfo info)
{
for (int i = 0; i < FixedBuffers.Length; ++i)
info.AddValue(nameof(Data) + i, Data[i]);
}

public bool Equals(FixedBufferStruct<#= type.Name #> buffer)
{
for (int i = 0; i < FixedBuffers.Length; ++i)
{
if (Data[i] != buffer.Data[i])
return false;
}
return true;
}

public override bool Equals(object obj) =>
obj is FixedBufferStruct<#= type.Name #> fixedStruct &&
Equals(fixedStruct);
}

<# } #>

public unsafe abstract class FixedBuffers : TestBase
{
public const int Length = 9;

protected FixedBuffers(ITestOutputHelper output, TestContext testContext)
: base(output, testContext)
{ }
<# foreach (var type in IntTypes) { #>

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void AdjustBuffer(
ref FixedBufferStruct<#= type.Name #> value,
<#= type.Type #> scalarValue)
{
for (int i = 0; i < Length; ++i)
value.Data[i] += scalarValue;
}

internal static void FixedBuffer<#= type.Name #>Kernel(
Index1 index,
ArrayView<<#= type.Type #>> data,
ArrayView<<#= type.Type #>> data2,
FixedBufferStruct<#= type.Name #> value,
<#= type.Type #> scalarValue)
{
data[index] = value.Data[index];
AdjustBuffer(ref value, scalarValue);
data2[index] = value.Data[index];
}

[Fact]
[KernelMethod(nameof(FixedBuffer<#= type.Name #>Kernel))]
public void FixedBuffer<#= type.Name #>()
{
using var buffer1 = Accelerator.Allocate<<#= type.Type #>>(Length);
using var buffer2 = Accelerator.Allocate<<#= type.Type #>>(Length);

<#= type.Type #> scalarValue = 2;
var fixedBufferData1 = new FixedBufferStruct<#= type.Name #>(scalarValue);
Execute(Length, buffer1.View, buffer2.View, fixedBufferData1, scalarValue);

var expected1 = Enumerable.Repeat(scalarValue, Length).ToArray();
var expected2 = Enumerable.Repeat(
(<#= type.Type #>)(scalarValue + scalarValue),
Length).ToArray();
Verify(buffer1, expected1);
Verify(buffer2, expected2);
}
<# } #>
}
}

#pragma warning restore CA2231 // Overload operator equals on overriding value type Equals
#pragma warning restore CA1051 // Do not declare visible instance fields
#pragma warning restore CA1815 // Override equals and operator equals on value types
#pragma warning restore CS0659 // Type overrides Object.Equals(object o) but does not
// override Object.GetHashCode()
14 changes: 14 additions & 0 deletions Src/ILGPU.Tests/ILGPU.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>ConvertIntOperations.tt</DependentUpon>
</None>
<None Include="FixedBuffers.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FixedBuffers.tt</DependentUpon>
</None>
<None Include="Generic\ConfigurationBase.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand Down Expand Up @@ -124,6 +129,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>ConvertIntOperations.tt</DependentUpon>
</Compile>
<Compile Update="FixedBuffers.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>FixedBuffers.tt</DependentUpon>
</Compile>
<Compile Update="Generic\ConfigurationBase.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
Expand Down Expand Up @@ -170,6 +180,10 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ConvertIntOperations.cs</LastGenOutput>
</None>
<None Update="FixedBuffers.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>FixedBuffers.cs</LastGenOutput>
</None>
<None Update="Generic\ConfigurationBase.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ConfigurationBase.cs</LastGenOutput>
Expand Down
4 changes: 4 additions & 0 deletions Src/ILGPU/Backends/IBackendCodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,10 @@ public BackendValueVisitor(TCodeGenerator codeGenerator)
public void Visit(ConvertValue value) =>
CodeGenerator.GenerateCode(value);

/// <summary cref="IValueVisitor.Visit(IntAsPointerCast)"/>
public void Visit(IntAsPointerCast value) =>
throw new InvalidCodeGenerationException();

/// <summary cref="IValueVisitor.Visit(PointerCast)"/>
public void Visit(PointerCast value) =>
CodeGenerator.GenerateCode(value);
Expand Down
10 changes: 7 additions & 3 deletions Src/ILGPU/Backends/OpenCL/CLBackend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using ILGPU.IR;
using ILGPU.IR.Analyses;
using ILGPU.IR.Transformations;
using ILGPU.IR.Types;
using ILGPU.Runtime;
using ILGPU.Runtime.OpenCL;
using System.Text;
Expand All @@ -36,8 +37,11 @@ public sealed partial class CLBackend :
/// </summary>
private sealed class CLAcceleratorSpecializer : AcceleratorSpecializer
{
public CLAcceleratorSpecializer()
: base(AcceleratorType.OpenCL, null)
public CLAcceleratorSpecializer(PrimitiveType pointerType)
: base(
AcceleratorType.OpenCL,
null,
pointerType)
{ }
}

Expand Down Expand Up @@ -76,7 +80,7 @@ public CLBackend(Context context, CLAcceleratorVendor vendor)
var transformerBuilder = Transformer.CreateBuilder(
TransformerConfiguration.Empty);
transformerBuilder.AddBackendOptimizations(
new CLAcceleratorSpecializer(),
new CLAcceleratorSpecializer(PointerType),
context.OptimizationLevel);
builder.Add(transformerBuilder.ToTransformer());
});
Expand Down
10 changes: 7 additions & 3 deletions Src/ILGPU/Backends/PTX/PTXBackend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using ILGPU.IR;
using ILGPU.IR.Analyses;
using ILGPU.IR.Transformations;
using ILGPU.IR.Types;
using ILGPU.Runtime;
using System.Text;

Expand Down Expand Up @@ -52,8 +53,11 @@ public sealed class PTXBackend :
/// </summary>
private sealed class PTXAcceleratorSpecializer : AcceleratorSpecializer
{
public PTXAcceleratorSpecializer()
: base(AcceleratorType.Cuda, PTXBackend.WarpSize)
public PTXAcceleratorSpecializer(PrimitiveType pointerType)
: base(
AcceleratorType.Cuda,
PTXBackend.WarpSize,
pointerType)
{ }
}

Expand Down Expand Up @@ -90,7 +94,7 @@ public PTXAcceleratorSpecializer()
var transformerBuilder = Transformer.CreateBuilder(
TransformerConfiguration.Empty);
transformerBuilder.AddBackendOptimizations(
new PTXAcceleratorSpecializer(),
new PTXAcceleratorSpecializer(PointerType),
context.OptimizationLevel);
builder.Add(transformerBuilder.ToTransformer());
});
Expand Down
67 changes: 57 additions & 10 deletions Src/ILGPU/Frontend/CodeGenerator/Arithmetic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
// ---------------------------------------------------------------------------------------

using ILGPU.IR;
using ILGPU.IR.Types;
using ILGPU.IR.Values;
using ILGPU.Resources;
using ILGPU.Util;
Expand All @@ -18,6 +19,27 @@ namespace ILGPU.Frontend
{
partial class CodeGenerator
{
/// <summary>
/// Tries to map the given IR value representing a raw integer-based value size
/// to a corresponding <see cref="BasicValueType"/> entry.
/// </summary>
/// <param name="value">The IR to map.</param>
/// <param name="valueType">The determined basic-value type (if any).</param>
/// <returns>
/// True, if the given IR node could be mapped to a basic value type.
/// </returns>
private static bool TryGetBasicValueSize(
Value value,
out BasicValueType valueType)
{
valueType =
value is PrimitiveValue size &&
size.BasicValueType.IsInt()
? PrimitiveType.GetBasicValueTypeBySize(size.Int32Value)
: BasicValueType.None;
return valueType != BasicValueType.None;
}

/// <summary>
/// Realizes an arithmetic operation.
/// </summary>
Expand All @@ -37,7 +59,7 @@ partial class CodeGenerator
arithmeticFlags |= ArithmeticFlags.Unsigned;
}

ValueReference result;
ValueReference result = default;
if (Block.PopArithmeticArgs(
Location,
convertFlags,
Expand All @@ -49,18 +71,43 @@ partial class CodeGenerator
if (!isLeftPointer)
Utilities.Swap(ref left, ref right);

if (kind != BinaryArithmeticKind.Add || right.Type.IsPointerType)
// Check for raw combinations of two pointer values
if (
!right.Type.IsPointerType &&
// Check whether this can be safely converted into a LEA value
kind == BinaryArithmeticKind.Add)
{
throw Location.GetNotSupportedException(
ErrorMessages.NotSupportedArithmeticArgumentType,
kind);
result = Builder.CreateLoadElementAddress(
Location,
left,
right);
}
// Check whether this operation on pointer values can be converted
// into a LEA instruction
// FIXME: remove this code once we add additional LEA nodes
else if (
kind == BinaryArithmeticKind.Add &&
right is BinaryArithmeticValue baseAddress &&
baseAddress.Kind == BinaryArithmeticKind.Mul &&
// Extract the element stride from the multiplication pattern
// (must be the right operand since we have moved all pointer
// values the left hand side by definition)
TryGetBasicValueSize(baseAddress.Right, out var strideType))
{
// Cast raw pointer into an appropriate target type
var targetElementType = Builder.GetPrimitiveType(strideType);
left = Builder.CreatePointerCast(
Location,
left,
targetElementType);
result = Builder.CreateLoadElementAddress(
Location,
left,
baseAddress.Left);
}
result = Builder.CreateLoadElementAddress(
Location,
left,
right);
}
else

if (!result.IsValid)
{
switch (kind)
{
Expand Down
4 changes: 2 additions & 2 deletions Src/ILGPU/Frontend/CodeGenerator/Convert.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ partial class CodeGenerator
targetPointerType.ElementType.IsRootType)
{
// Must be a reflection array call
// FIXME: note that we have to update this spot once
// we add support for class types
// FIXME: note that we have to update this spot once we add support
// for class types
Location.Assert(value.Type is StructureType);
return value;
}
Expand Down