/// <summary> /// Creates a set of instructions to realize a generic lea operation. /// </summary> /// <param name="sourceType">The source address type (pointer or view).</param> /// <param name="elementIndex">The current element index (the offset).</param> /// <param name="targetAddressRegister">The allocated target pointer register to write to.</param> /// <param name="address">The source address.</param> private void MakeLoadElementAddress( AddressSpaceType sourceType, PrimitiveRegister elementIndex, PrimitiveRegister targetAddressRegister, PrimitiveRegister address) { var elementSize = ABI.GetSizeOf(sourceType.ElementType); var offsetRegister = AllocatePlatformRegister(out RegisterDescription _); using (var command = BeginCommand( PTXInstructions.GetLEAMulOperation(ABI.PointerArithmeticType))) { command.AppendArgument(offsetRegister); command.AppendArgument(elementIndex); command.AppendConstant(elementSize); } using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Add, ABI.PointerArithmeticType, false))) { command.AppendArgument(targetAddressRegister); command.AppendArgument(address); command.AppendArgument(offsetRegister); } FreeRegister(offsetRegister); }
/// <summary cref="IBackendCodeGenerator.GenerateCode(LoadFieldAddress)"/> public void GenerateCode(LoadFieldAddress value) { var source = LoadPrimitive(value.Source); var fieldOffset = value.StructureType.GetOffset( value.FieldSpan.Access); if (fieldOffset != 0) { var targetRegister = AllocatePlatformRegister( value, out RegisterDescription _); using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Add, Backend.PointerArithmeticType, false)); command.AppendArgument(targetRegister); command.AppendArgument(source); command.AppendConstant(fieldOffset); } else { Alias(value, value.Source); } }
/// <summary cref="IBackendCodeGenerator.GenerateCode(LoadElementAddress)"/> public void GenerateCode(LoadElementAddress value) { var elementIndex = LoadPrimitive(value.ElementIndex); var targetAddressRegister = AllocatePlatformRegister( value, out RegisterDescription _); Debug.Assert(value.IsPointerAccess, "Invalid pointer access"); var address = LoadPrimitive(value.Source); var sourceType = value.Source.Type as AddressSpaceType; var elementSize = sourceType.ElementType.Size; var offsetRegister = AllocatePlatformRegister(out RegisterDescription _); using (var command = BeginCommand( PTXInstructions.GetLEAMulOperation(Backend.PointerArithmeticType))) { command.AppendArgument(offsetRegister); command.AppendArgument(elementIndex); command.AppendConstant(elementSize); } using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Add, Backend.PointerArithmeticType, false))) { command.AppendArgument(targetAddressRegister); command.AppendArgument(address); command.AppendArgument(offsetRegister); } FreeRegister(offsetRegister); }
/// <summary cref="IBackendCodeGenerator.GenerateCode(LoadElementAddress)"/> public void GenerateCode(LoadElementAddress value) { var elementIndex = LoadPrimitive(value.Offset); var targetAddressRegister = AllocatePlatformRegister( value, out RegisterDescription _); Debug.Assert(value.IsPointerAccess, "Invalid pointer access"); var address = LoadPrimitive(value.Source); var sourceType = value.Source.Type as AddressSpaceType; var elementSize = sourceType.ElementType.Size; if (value.Is32BitAccess) { // Perform two efficient operations TODO var offsetRegister = AllocatePlatformRegister(out RegisterDescription _); using (var command = BeginCommand( PTXInstructions.GetLEAMulOperation(Backend.PointerArithmeticType))) { command.AppendArgument(offsetRegister); command.AppendArgument(elementIndex); command.AppendConstant(elementSize); } using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Add, Backend.PointerArithmeticType, Backend.Capabilities, false))) { command.AppendArgument(targetAddressRegister); command.AppendArgument(address); command.AppendArgument(offsetRegister); } FreeRegister(offsetRegister); } else { // Use an efficient MAD instruction to compute the effective address using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( TernaryArithmeticKind.MultiplyAdd, Backend.PointerArithmeticType)); command.AppendArgument(targetAddressRegister); command.AppendArgument(elementIndex); command.AppendConstant(elementSize); command.AppendArgument(address); } }
/// <summary cref="IBackendCodeGenerator.GenerateCode(UnaryArithmeticValue)"/> public void GenerateCode(UnaryArithmeticValue value) { var argument = LoadPrimitive(value.Value); var targetRegister = AllocateHardware(value); using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( value.Kind, value.ArithmeticBasicValueType, FastMath)); command.AppendArgument(targetRegister); command.AppendArgument(argument); }
/// <summary cref="IBackendCodeGenerator.GenerateCode(BinaryArithmeticValue)"/> public void GenerateCode(BinaryArithmeticValue value) { var left = LoadPrimitive(value.Left); var right = LoadPrimitive(value.Right); var targetRegister = Allocate(value, left.Description); using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( value.Kind, value.ArithmeticBasicValueType, FastMath)); command.AppendArgument(targetRegister); command.AppendArgument(left); command.AppendArgument(right); }
/// <summary cref="IValueVisitor.Visit(CompareValue)"/> public void Visit(CompareValue value) { var left = LoadPrimitive(value.Left); var right = LoadPrimitive(value.Right); var targetRegister = AllocatePrimitive(value); if (left.Kind == PTXRegisterKind.Predicate) { // Predicate registers require a special treatment using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Xor, ArithmeticBasicValueType.UInt1, false))) { command.AppendArgument(targetRegister); command.AppendArgument(left); command.AppendArgument(right); } if (value.Kind == CompareKind.Equal) { using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( UnaryArithmeticKind.Not, ArithmeticBasicValueType.UInt1, false))) { command.AppendArgument(targetRegister); command.AppendArgument(targetRegister); } } } else { using (var command = BeginCommand( PTXInstructions.GetCompareOperation( value.Kind, value.CompareType))) { command.AppendArgument(targetRegister); command.AppendArgument(left); command.AppendArgument(right); } } }
/// <summary cref="IBackendCodeGenerator.GenerateCode(TernaryArithmeticValue)"/> public void GenerateCode(TernaryArithmeticValue value) { var first = LoadPrimitive(value.First); var second = LoadPrimitive(value.Second); var third = LoadPrimitive(value.Third); var targetRegister = Allocate(value, first.Description); using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( value.Kind, value.ArithmeticBasicValueType)); command.AppendArgument(targetRegister); command.AppendArgument(first); command.AppendArgument(second); command.AppendArgument(third); }
/// <summary cref="IValueVisitor.Visit(ViewCast)"/> public void Visit(ViewCast value) { var source = LoadAs <ViewImplementationRegister>(value.Value); var pointer = source.Pointer; var length = source.Length; var sourceElementSize = ABI.GetSizeOf(value.SourceElementType); var targetElementSize = ABI.GetSizeOf(value.TargetElementType); // var newLength = length * sourceElementSize / targetElementSize; var lengthTimesSourceElementSize = AllocateRegister(length.Description); var newLength = AllocateRegister(length.Description); using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Mul, ArithmeticBasicValueType.Int32, FastMath))) { command.AppendArgument(lengthTimesSourceElementSize); command.AppendArgument(length); command.AppendConstant(sourceElementSize); } using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Div, ArithmeticBasicValueType.Int32, FastMath))) { command.AppendArgument(newLength); command.AppendArgument(lengthTimesSourceElementSize); command.AppendConstant(targetElementSize); } var newView = new ViewImplementationRegister( value.Type as ViewType, pointer, newLength); Bind(value, newView); FreeRegister(lengthTimesSourceElementSize); }
/// <summary cref="IBackendCodeGenerator.GenerateCode(DynamicMemoryLengthValue)"/> public void GenerateCode(DynamicMemoryLengthValue value) { if (value.AddressSpace != MemoryAddressSpace.Shared) { throw new InvalidCodeGenerationException(); } // Load the dynamic memory size (in bytes) from the PTX special register // and divide by the size in bytes of the array element. var lengthRegister = AllocateHardware(value); var dynamicMemorySizeRegister = MoveFromIntrinsicRegister( PTXRegisterKind.DynamicSharedMemorySize); using var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Div, ArithmeticBasicValueType.UInt32, Backend.Capabilities, false)); command.AppendArgument(lengthRegister); command.AppendArgument(dynamicMemorySizeRegister); command.AppendConstant(value.ElementType.Size); }
/// <summary cref="IValueVisitor.Visit(LoadFieldAddress)"/> public void Visit(LoadFieldAddress value) { var source = LoadPrimitive(value.Source); var fieldOffset = ABI.GetOffsetOf(value.StructureType, value.FieldIndex); if (fieldOffset != 0) { var targetRegister = AllocatePlatformRegister(value, out RegisterDescription _); using (var command = BeginCommand( PTXInstructions.GetArithmeticOperation( BinaryArithmeticKind.Add, ABI.PointerArithmeticType, false))) { command.AppendArgument(targetRegister); command.AppendArgument(source); command.AppendConstant(fieldOffset); } } else { Alias(value, value.Source); } }