internal static void GenerateScanReduce <T, TScanReduce>( CLBackend backend, CLCodeGenerator codeGenerator, Value value, string scanReduceOperation) where T : struct where TScanReduce : struct, IScanReduceOperation <T> { // Allocate target and load source argument var reduce = value as MethodCall; var sourceValue = codeGenerator.Load(reduce[0]); var target = codeGenerator.Allocate(value); // Resolve OpenCL command TScanReduce scanReduce = default; var clCommand = scanReduce.CLCommand; if (string.IsNullOrWhiteSpace(clCommand)) { throw new InvalidCodeGenerationException(); } using var statement = codeGenerator.BeginStatement(target); statement.AppendCommand(scanReduceOperation + clCommand); statement.BeginArguments(); statement.AppendCast(typeof(T).GetArithmeticBasicValueType()); statement.Append(sourceValue); statement.EndArguments(); }
/// <summary> /// Generates an intrinsic reduce. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TReduction">The type of the reduction logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateReduce <T, TReduction>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TReduction : struct, IScanReduceOperation <T> => GenerateAllReduce <T, TReduction>( backend, codeGenerator, value);
/// <summary> /// Generates intrinsic math instructions for the following kinds: /// Rcp /// </summary> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateMathIntrinsic( CLBackend backend, CLCodeGenerator codeGenerator, Value value) { // Manually generate code for "1.0 / argument" var arithmeticValue = value as UnaryArithmeticValue; var argument = codeGenerator.Load(arithmeticValue.Value); var target = codeGenerator.Allocate(arithmeticValue); var operation = CLInstructions.GetArithmeticOperation( BinaryArithmeticKind.Div, arithmeticValue.BasicValueType.IsFloat(), out var isFunction); using var statement = codeGenerator.BeginStatement(target); statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); if (isFunction) { statement.AppendCommand(operation); statement.BeginArguments(); } else { statement.OpenParen(); } statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); if (arithmeticValue.BasicValueType == BasicValueType.Float32) { statement.AppendConstant(1.0f); } else { statement.AppendConstant(1.0); } if (!isFunction) { statement.AppendCommand(operation); } statement.AppendArgument(); statement.AppendCast(arithmeticValue.ArithmeticBasicValueType); statement.Append(argument); if (isFunction) { statement.EndArguments(); } else { statement.CloseParen(); } }
/// <summary> /// Generates an intrinsic scan. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TScanOperation">The type of the warp scan logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateInclusiveScan <T, TScanOperation>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TScanOperation : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TScanOperation>( backend, codeGenerator, value, "work_group_scan_inclusive_");
/// <summary> /// Generates an intrinsic reduce. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TReduction">The type of the reduction logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateAllReduce <T, TReduction>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : unmanaged where TReduction : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TReduction>( backend, codeGenerator, value, "work_group_reduce_");
/// <summary> /// Generates an intrinsic scan. /// </summary> /// <typeparam name="T">The element type.</typeparam> /// <typeparam name="TScanOperation">The type of the warp scan logic.</typeparam> /// <param name="backend">The current backend.</param> /// <param name="codeGenerator">The code generator.</param> /// <param name="value">The value to generate code for.</param> public static void GenerateExclusiveScan <T, TScanOperation>( CLBackend backend, CLCodeGenerator codeGenerator, Value value) where T : struct where TScanOperation : struct, IScanReduceOperation <T> => CLContext.GenerateScanReduce <T, TScanOperation>( backend, codeGenerator, value, "sub_group_scan_exclusive_");
/// <summary> /// The OpenCL implementation. /// </summary> /// <remarks> /// Note that this function signature corresponds to the OpenCL-backend specific /// delegate type <see cref="CLIntrinsic.Handler"/>. /// </remarks> static void GenerateCLCode( CLBackend backend, CLCodeGenerator codeGenerator, Value value) { // The passed value will be the call node in this case // Load X parameter variable (first argument) var xVariable = codeGenerator.Load(value[0]); // Allocate target variable to write our result to var target = codeGenerator.Allocate(value); // Emit our desired instructions using var statement = codeGenerator.BeginStatement(target); statement.Append(xVariable); statement.AppendCommand( CLInstructions.GetArithmeticOperation( BinaryArithmeticKind.Mul, false, out var _)); statement.AppendConstant(2); }