예제 #1
0
파일: Arithmetic.cs 프로젝트: killop/ILGPU
        /// <summary>
        /// Tries to convert the base address into a valid LEA operation.
        /// </summary>
        /// <param name="left">The left operand (the pointer to use).</param>
        /// <param name="baseAddress">The base address offset.</param>
        /// <param name="result">The result value (if any).</param>
        /// <returns>
        /// True, if the given pattern could be converted into a LEA node.
        /// </returns>
        private bool TryConvertIntoLoadElementAddress(
            Value left,
            BinaryArithmeticValue baseAddress,
            out Value result)
        {
            if (
                // Check multiplications
                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, null, out var strideType) ||

                // Check shift-based address computations
                baseAddress.Kind == BinaryArithmeticKind.Shl &&
                // Extract the element stride from the shift pattern
                TryGetBasicValueSize(baseAddress.Right, 1, out 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);
                return(true);
            }
            result = null;
            return(false);
        }
예제 #2
0
 public void Visit(BinaryArithmeticValue value)
 {
     if (Get <BinaryArithmeticValue>().Kind != value.Kind ||
         Get <BinaryArithmeticValue>().Flags != value.Flags)
     {
         Fail();
     }
 }
예제 #3
0
파일: Arithmetic.cs 프로젝트: m4rs-mt/ILGPU
 /// <summary>
 /// Inverts a binary arithmetic value.
 /// </summary>
 /// <param name="location">The current location.</param>
 /// <param name="binary">The binary operation to invert.</param>
 /// <returns>The inverted binary operation.</returns>
 private ValueReference InvertBinaryArithmetic(
     Location location,
     BinaryArithmeticValue binary) =>
 CreateArithmetic(
     binary.Location,
     CreateArithmetic(
         location,
         binary.Left,
         UnaryArithmeticKind.Not),
     CreateArithmetic(
         location,
         binary.Right,
         UnaryArithmeticKind.Not),
     BinaryArithmeticValue.InvertLogical(binary.Kind),
     binary.Flags);
예제 #4
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);
        }
예제 #5
0
        /// <summary cref="IValueVisitor.Visit(BinaryArithmeticValue)"/>
        public void Visit(BinaryArithmeticValue value)
        {
            var left  = Load(value.Left);
            var right = Load(value.Right);

            var target = Allocate(value, value.ArithmeticBasicValueType);

            using (var statement = BeginStatement(target))
            {
                statement.AppendCast(value.ArithmeticBasicValueType);
                var operation = CLInstructions.GetArithmeticOperation(
                    value.Kind,
                    value.BasicValueType.IsFloat(),
                    out bool isFunction);

                if (isFunction)
                {
                    statement.AppendCommand(operation);
                    statement.BeginArguments();
                }
                else
                {
                    statement.OpenParen();
                }

                statement.AppendCast(value.ArithmeticBasicValueType);
                statement.AppendArgument(left);

                if (!isFunction)
                {
                    statement.AppendCommand(operation);
                }

                statement.AppendArgument();
                statement.AppendCast(value.ArithmeticBasicValueType);
                statement.Append(right);

                if (isFunction)
                {
                    statement.EndArguments();
                }
                else
                {
                    statement.CloseParen();
                }
            }
        }
예제 #6
0
 /// <summary cref="IValueVisitor.Visit(BinaryArithmeticValue)"/>
 public void Visit(BinaryArithmeticValue value) =>
 CodeGenerator.GenerateCode(value);
예제 #7
0
        /// <summary>
        /// Creates a unary arithmetic operation.
        /// </summary>
        /// <param name="location">The current location.</param>
        /// <param name="node">The operand.</param>
        /// <param name="kind">The operation kind.</param>
        /// <param name="flags">Operation flags.</param>
        /// <returns>A node that represents the arithmetic operation.</returns>
        public ValueReference CreateArithmetic(
            Location location,
            Value node,
            UnaryArithmeticKind kind,
            ArithmeticFlags flags)
        {
            if (UseConstantPropagation)
            {
                // Check for constants
                if (node is PrimitiveValue value)
                {
                    return(UnaryArithmeticFoldConstants(location, value, kind));
                }

                var isUnsigned = (flags & ArithmeticFlags.Unsigned) ==
                                 ArithmeticFlags.Unsigned;
                switch (kind)
                {
                case UnaryArithmeticKind.Not:
                    switch (node)
                    {
                    // Check nested not operations
                    case UnaryArithmeticValue otherValue when
                        otherValue.Kind == UnaryArithmeticKind.Not:
                        return(otherValue.Value);

                    // Check whether we can invert compare values
                    case CompareValue compareValue:
                        // When the comparison is inverted, and we are comparing
                        // floats, toggle between ordered/unordered float
                        // comparison
                        var compareFlags = compareValue.Flags;
                        if (compareValue.Left.BasicValueType.IsFloat() &&
                            compareValue.Right.BasicValueType.IsFloat())
                        {
                            compareFlags ^= CompareFlags.UnsignedOrUnordered;
                        }

                        return(CreateCompare(
                                   location,
                                   compareValue.Left,
                                   compareValue.Right,
                                   CompareValue.Invert(compareValue.Kind),
                                   compareFlags));

                    // Propagate the not operator through binary operations
                    case BinaryArithmeticValue otherBinary when
                        BinaryArithmeticValue.TryInvertLogical(
                            otherBinary.Kind,
                            out var invertedBinary):
                        return(CreateArithmetic(
                                   otherBinary.Location,
                                   CreateArithmetic(
                                       location,
                                       otherBinary.Left,
                                       UnaryArithmeticKind.Not),
                                   CreateArithmetic(
                                       location,
                                       otherBinary.Right,
                                       UnaryArithmeticKind.Not),
                                   invertedBinary,
                                   otherBinary.Flags));
                    }
                    break;

                case UnaryArithmeticKind.Neg:
                    if (node.BasicValueType == BasicValueType.Int1)
                    {
                        return(CreateArithmetic(
                                   location,
                                   node,
                                   UnaryArithmeticKind.Not));
                    }
                    break;

                case UnaryArithmeticKind.Abs:
                    if (isUnsigned)
                    {
                        return(node);
                    }
                    break;
                }
            }

            return(Append(new UnaryArithmeticValue(
                              GetInitializer(location),
                              node,
                              kind,
                              flags)));
        }