Esempio n. 1
0
        /// <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);
            }
        }
Esempio n. 2
0
        /// <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);
        }
Esempio n. 3
0
        /// <summary cref="IValueVisitor.Visit(GenericAtomic)"/>
        public void Visit(GenericAtomic atomic)
        {
            var target = LoadPrimitive(atomic.Target);
            var value  = LoadPrimitive(atomic.Value);

            var requiresResult  = atomic.Uses.HasAny || atomic.Kind == AtomicKind.Exchange;
            var atomicOperation = PTXInstructions.GetAtomicOperation(
                atomic.Kind,
                requiresResult);
            var suffix = PTXInstructions.GetAtomicOperationSuffix(
                atomic.Kind,
                atomic.ArithmeticBasicValueType);

            var targetRegister = requiresResult ? AllocatePrimitive(atomic) : default;

            using (var command = BeginCommand(atomicOperation))
            {
                command.AppendNonLocalAddressSpace(
                    (atomic.Target.Type as AddressSpaceType).AddressSpace);
                command.AppendSuffix(suffix);
                if (requiresResult)
                {
                    command.AppendArgument(targetRegister);
                }
                command.AppendArgumentValue(target);
                command.AppendArgument(value);
            }
        }
Esempio n. 4
0
        /// <summary cref="IValueVisitor.Visit(PredicateBarrier)"/>
        public void Visit(PredicateBarrier barrier)
        {
            var targetRegister  = AllocatePrimitive(barrier);
            var sourcePredicate = LoadPrimitive(barrier.Predicate);

            switch (barrier.Kind)
            {
            case PredicateBarrierKind.And:
            case PredicateBarrierKind.Or:
                using (var command = BeginCommand(
                           PTXInstructions.GetPredicateBarrier(barrier.Kind)))
                {
                    command.AppendArgument(targetRegister);
                    command.AppendConstant(0);
                    command.AppendArgument(sourcePredicate);
                }
                break;

            case PredicateBarrierKind.PopCount:
                using (var command = BeginCommand(
                           PTXInstructions.GetPredicateBarrier(barrier.Kind)))
                {
                    command.AppendArgument(targetRegister);
                    command.AppendConstant(0);
                    command.AppendArgument(sourcePredicate);
                }
                break;

            default:
                throw new InvalidCodeGenerationException();
            }
        }
Esempio n. 5
0
        /// <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);
        }
Esempio n. 6
0
        /// <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);
            }
        }
Esempio n. 7
0
        /// <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);
        }
Esempio n. 8
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(ConvertValue)"/>
        public void GenerateCode(ConvertValue value)
        {
            var sourceValue = LoadPrimitive(value.Value);

            var convertOperation = PTXInstructions.GetConvertOperation(
                value.SourceType,
                value.TargetType);

            var targetRegister = AllocateHardware(value);

            using var command = BeginCommand(convertOperation);
            command.AppendArgument(targetRegister);
            command.AppendArgument(sourceValue);
        }
Esempio n. 9
0
        /// <summary cref="IValueVisitor.Visit(Predicate)"/>
        public void Visit(Predicate predicate)
        {
            var condition  = LoadPrimitive(predicate.Condition);
            var trueValue  = Load(predicate.TrueValue);
            var falseValue = Load(predicate.FalseValue);

            var targetRegister = Allocate(predicate);

            EmitComplexCommand(
                PTXInstructions.GetSelectValueOperation(predicate.BasicValueType),
                new PredicateEmitter(condition),
                targetRegister,
                trueValue,
                falseValue);
        }
Esempio n. 10
0
        /// <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);
        }
Esempio n. 11
0
        /// <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);
                }
            }
        }
Esempio n. 12
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(Barrier)"/>
        public void GenerateCode(Barrier barrier)
        {
            using var command = BeginCommand(PTXInstructions.GetBarrier(barrier.Kind));
            switch (barrier.Kind)
            {
            case BarrierKind.WarpLevel:
                command.AppendConstant(
                    PTXInstructions.AllThreadsInAWarpMemberMask);
                break;

            case BarrierKind.GroupLevel:
                command.AppendConstant(0);
                break;

            default:
                throw new InvalidCodeGenerationException();
            }
        }
Esempio n. 13
0
        /// <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);
        }
Esempio n. 14
0
        /// <summary>
        /// Creates an address-space cast conversion.
        /// </summary>
        /// <param name="sourceRegister">The source register.</param>
        /// <param name="targetRegister">The target register.</param>
        /// <param name="sourceAddressSpace">The source address space.</param>
        /// <param name="targetAddressSpace">The target address space.</param>
        private void CreateAddressSpaceCast(
            PrimitiveRegister sourceRegister,
            HardwareRegister targetRegister,
            MemoryAddressSpace sourceAddressSpace,
            MemoryAddressSpace targetAddressSpace)
        {
            var toGeneric                   = targetAddressSpace == MemoryAddressSpace.Generic;
            var addressSpaceOperation       = PTXInstructions.GetAddressSpaceCast(toGeneric);
            var addressSpaceOperationSuffix =
                PTXInstructions.GetAddressSpaceCastSuffix(Backend);

            using var command = BeginCommand(addressSpaceOperation);
            command.AppendAddressSpace(
                toGeneric ? sourceAddressSpace : targetAddressSpace);
            command.AppendSuffix(addressSpaceOperationSuffix);
            command.AppendArgument(targetRegister);
            command.AppendArgument(sourceRegister);
        }
Esempio n. 15
0
        /// <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);
        }
Esempio n. 16
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(AddressSpaceCast)"/>
        public void GenerateCode(AddressSpaceCast value)
        {
            var sourceType           = value.SourceType as AddressSpaceType;
            var targetAdressRegister = AllocatePlatformRegister(
                value,
                out RegisterDescription _);

            Debug.Assert(value.IsPointerCast, "Invalid pointer access");

            var address                     = LoadPrimitive(value.Value);
            var toGeneric                   = value.TargetAddressSpace == MemoryAddressSpace.Generic;
            var addressSpaceOperation       = PTXInstructions.GetAddressSpaceCast(toGeneric);
            var addressSpaceOperationSuffix =
                PTXInstructions.GetAddressSpaceCastSuffix(Backend);

            using var command = BeginCommand(addressSpaceOperation);
            command.AppendAddressSpace(
                toGeneric ? sourceType.AddressSpace : value.TargetAddressSpace);
            command.AppendSuffix(addressSpaceOperationSuffix);
            command.AppendArgument(targetAdressRegister);
            command.AppendArgument(address);
        }
Esempio n. 17
0
        /// <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);
        }
Esempio n. 18
0
        /// <summary cref="IValueVisitor.Visit(AddressSpaceCast)"/>
        public void Visit(AddressSpaceCast value)
        {
            var sourceType           = value.SourceType as AddressSpaceType;
            var targetAdressRegister = AllocatePlatformRegister(value, out RegisterDescription _);

            PrimitiveRegister address;

            if (value.IsPointerCast)
            {
                address = LoadPrimitive(value.Value);
            }
            else
            {
                var viewSource = LoadAs <ViewImplementationRegister>(value.Value);
                address = viewSource.Pointer;

                // Reuse the existing length register since we don't modify the result
                var viewTarget = new ViewImplementationRegister(
                    value.Type as ViewType,
                    targetAdressRegister,
                    viewSource.Length);
                Bind(value, viewTarget);
            }

            var toGeneric                   = value.TargetAddressSpace == MemoryAddressSpace.Generic;
            var addressSpaceOperation       = PTXInstructions.GetAddressSpaceCast(toGeneric);
            var addressSpaceOperationSuffix = PTXInstructions.GetAddressSpaceCastSuffix(ABI);

            using (var command = BeginCommand(addressSpaceOperation))
            {
                command.AppendAddressSpace(
                    toGeneric ? sourceType.AddressSpace : value.TargetAddressSpace);
                command.AppendSuffix(addressSpaceOperationSuffix);
                command.AppendArgument(targetAdressRegister);
                command.AppendArgument(address);
            }
        }
Esempio n. 19
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(IfPredicate)"/>
        public void GenerateCode(IfPredicate predicate)
        {
            var condition  = LoadPrimitive(predicate.Condition);
            var trueValue  = Load(predicate.TrueValue);
            var falseValue = Load(predicate.FalseValue);

            var targetRegister = Allocate(predicate);

            if (predicate.BasicValueType == BasicValueType.Int1)
            {
                // We need a specific sequence of instructions for predicate registers
                var conditionRegister = EnsureHardwareRegister(condition);
                using (var statement1 = BeginMove(
                           new PredicateConfiguration(conditionRegister, true)))
                {
                    statement1.AppendSuffix(BasicValueType.Int1);
                    statement1.AppendArgument(targetRegister as PrimitiveRegister);
                    statement1.AppendArgument(trueValue as PrimitiveRegister);
                }

                using var statement2 = BeginMove(
                          new PredicateConfiguration(conditionRegister, false));
                statement2.AppendSuffix(BasicValueType.Int1);
                statement2.AppendArgument(targetRegister as PrimitiveRegister);
                statement2.AppendArgument(falseValue as PrimitiveRegister);
            }
            else
            {
                EmitComplexCommand(
                    PTXInstructions.GetSelectValueOperation(predicate.BasicValueType),
                    new PredicateEmitter(condition),
                    targetRegister,
                    trueValue,
                    falseValue);
            }
        }
Esempio n. 20
0
        /// <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);
            }
        }
Esempio n. 21
0
 /// <summary>
 /// Appends the given vector length suffix.
 /// </summary>
 /// <param name="vectorLength">The vector length.</param>
 public void AppendVectorSuffix(int vectorLength) =>
 AppendSuffix(PTXInstructions.GetVectorOperationSuffix(vectorLength));
Esempio n. 22
0
        /// <summary cref="IValueVisitor.Visit(SwitchBranch)"/>
        public void Visit(SwitchBranch branch)
        {
            var idx = LoadPrimitive(branch.Condition);

            using (var lowerBoundsScope = new PredicateScope(this))
            {
                // Emit less than
                var lessThanCommand = PTXInstructions.GetCompareOperation(
                    CompareKind.LessThan,
                    ArithmeticBasicValueType.Int32);
                using (var command = BeginCommand(
                           lessThanCommand))
                {
                    command.AppendArgument(lowerBoundsScope.PredicateRegister);
                    command.AppendArgument(idx);
                    command.AppendConstant(0);
                }

                using (var upperBoundsScope = new PredicateScope(this))
                {
                    using (var command = BeginCommand(
                               PTXInstructions.BranchIndexRangeComparison))
                    {
                        command.AppendArgument(upperBoundsScope.PredicateRegister);
                        command.AppendArgument(idx);
                        command.AppendConstant(branch.NumCasesWithoutDefault);
                        command.AppendArgument(lowerBoundsScope.PredicateRegister);
                    }
                    using (var command = BeginCommand(
                               PTXInstructions.BranchOperation,
                               new PredicateConfiguration(upperBoundsScope.PredicateRegister, true)))
                    {
                        var defaultTarget = blockLookup[branch.DefaultBlock];
                        command.AppendLabel(defaultTarget);
                    }
                }
            }

            var targetLabel = DeclareLabel();

            MarkLabel(targetLabel);
            Builder.Append('\t');
            Builder.Append(PTXInstructions.BranchTargetsDeclaration);
            Builder.Append(' ');
            for (int i = 0, e = branch.NumCasesWithoutDefault; i < e; ++i)
            {
                var caseTarget = branch.GetCaseTarget(i);
                var caseLabel  = blockLookup[caseTarget];
                Builder.Append(caseLabel);
                if (i + 1 < e)
                {
                    Builder.Append(", ");
                }
            }
            Builder.AppendLine(";");

            using (var command = BeginCommand(
                       PTXInstructions.BranchIndexOperation))
            {
                command.AppendArgument(idx);
                command.AppendLabel(targetLabel);
            }
        }
Esempio n. 23
0
        /// <summary cref="IValueVisitor.Visit(MemoryBarrier)"/>
        public void Visit(MemoryBarrier barrier)
        {
            var command = PTXInstructions.GetMemoryBarrier(barrier.Kind);

            Command(command);
        }
Esempio n. 24
0
 /// <summary>
 /// Gets the actual select command.
 /// </summary>
 public string AdjustCommand(string command, PrimitiveRegister[] registers) =>
 PTXInstructions.GetSelectValueOperation(registers[0].BasicValueType);
Esempio n. 25
0
        /// <summary cref="IBackendCodeGenerator.GenerateCode(MemoryBarrier)"/>
        public void GenerateCode(MemoryBarrier barrier)
        {
            var command = PTXInstructions.GetMemoryBarrier(barrier.Kind);

            Command(command);
        }