Example #1
0
        /// <summary>
        /// Resolves an unary arithmetic operation.
        /// </summary>
        /// <param name="kind">The arithmetic kind.</param>
        /// <param name="isFloat">True, if this is a floating-point operation.</param>
        /// <param name="isFunction">True, if the resolved operation is a function call.</param>
        /// <returns>The resolved arithmetic operation.</returns>
        public static string GetArithmeticOperation(
            UnaryArithmeticKind kind,
            bool isFloat,
            out bool isFunction)
        {
            string operation;

            (operation, isFunction) = UnaryArithmeticOperations[(kind, isFloat)];
Example #2
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>
 /// <returns>A node that represents the arithmetic operation.</returns>
 public ValueReference CreateArithmetic(
     Location location,
     Value node,
     UnaryArithmeticKind kind) =>
 CreateArithmetic(
     location,
     node,
     kind,
     ArithmeticFlags.None);
Example #3
0
        /// <summary>
        /// Creates a unary arithmetic operation.
        /// </summary>
        /// <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(
            Value node,
            UnaryArithmeticKind kind,
            ArithmeticFlags flags)
        {
            Debug.Assert(node != null, "Invalid node");

            if (UseConstantPropagation)
            {
                // Check for constants
                if (node is PrimitiveValue value)
                {
                    return(UnaryArithmeticFoldConstants(value, kind));
                }

                var isUnsigned = (flags & ArithmeticFlags.Unsigned) == ArithmeticFlags.Unsigned;
                switch (kind)
                {
                case UnaryArithmeticKind.Not:
                    if (node is UnaryArithmeticValue otherValue &&
                        otherValue.Kind == UnaryArithmeticKind.Not)
                    {
                        return(otherValue.Value);
                    }
                    if (node is CompareValue compareValue)
                    {
                        return(CreateCompare(
                                   compareValue.Left,
                                   compareValue.Right,
                                   CompareValue.Invert(compareValue.Kind),
                                   compareValue.Flags));
                    }
                    break;

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

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

            return(Append(new UnaryArithmeticValue(
                              Context,
                              BasicBlock,
                              node,
                              kind,
                              flags)));
        }
Example #4
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="block">The current basic block.</param>
        /// <param name="builder">The current builder.</param>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        private static void MakeArithmetic(
            Block block,
            IRBuilder builder,
            UnaryArithmeticKind kind)
        {
            var value      = block.PopCompareOrArithmeticValue(ConvertFlags.None);
            var arithmetic = builder.CreateArithmetic(value, kind);

            block.Push(arithmetic);
        }
Example #5
0
 /// <summary>
 /// Resolves an unary arithmetic operation.
 /// </summary>
 /// <param name="kind">The arithmetic kind.</param>
 /// <param name="isFloat">True, if this is a floating-point operation.</param>
 /// <param name="isFunction">True, if the resolved operation is a function call.</param>
 /// <returns>The resolved arithmetic operation.</returns>
 public static string GetArithmeticOperation(
     UnaryArithmeticKind kind,
     bool isFloat,
     out bool isFunction)
 {
     if (!UnaryArithmeticOperations.TryGetValue((kind, isFloat), out var operation))
     {
         throw new NotSupportedIntrinsicException(kind.ToString());
     }
     isFunction = operation.Item2;
     return(operation.Item1);
 }
Example #6
0
        /// <summary>
        /// Realizes an arithmetic operation.
        /// </summary>
        /// <param name="kind">The kind of the arithmetic operation.</param>
        private void MakeArithmetic(UnaryArithmeticKind kind)
        {
            var value = Block.PopCompareOrArithmeticValue(
                Location,
                ConvertFlags.None);
            var arithmetic = Builder.CreateArithmetic(
                Location,
                value,
                kind);

            Block.Push(arithmetic);
        }
Example #7
0
 /// <summary>
 /// Resolves an unary arithmetic operation.
 /// </summary>
 /// <param name="kind">The arithmetic kind.</param>
 /// <param name="basicValueType">The arithmetic basic value type.</param>
 /// <param name="isFunction">
 /// True, if the resolved operation is a function call.
 /// </param>
 /// <returns>The resolved arithmetic operation.</returns>
 public static string GetArithmeticOperation(
     UnaryArithmeticKind kind,
     ArithmeticBasicValueType basicValueType,
     out bool isFunction)
 {
     if (!UnaryCategoryLookup.TryGetValue(basicValueType, out var category) ||
         !UnaryArithmeticOperations.TryGetValue((kind, category), out var operation))
     {
         throw new NotSupportedIntrinsicException(kind.ToString());
     }
     isFunction = operation.Item2;
     return(operation.Item1);
 }
Example #8
0
        public static string GetArithmeticOperation(
            UnaryArithmeticKind kind,
            ArithmeticBasicValueType type,
            bool fastMath)
        {
            var key = (kind, type);

            if (fastMath &&
                UnaryArithmeticOperationsFastMath.TryGetValue(key, out string operation))
            {
                return(operation);
            }
            return(UnaryArithmeticOperations[key]);
        }
Example #9
0
 /// <summary>
 /// Constructs a new unary arithmetic operation.
 /// </summary>
 /// <param name="context">The parent IR context.</param>
 /// <param name="basicBlock">The parent basic block.</param>
 /// <param name="value">The operand.</param>
 /// <param name="kind">The operation kind.</param>
 /// <param name="flags">The operation flags.</param>
 internal UnaryArithmeticValue(
     IRContext context,
     BasicBlock basicBlock,
     ValueReference value,
     UnaryArithmeticKind kind,
     ArithmeticFlags flags)
     : base(
         basicBlock,
         ImmutableArray.Create(value),
         flags,
         ComputeType(context, value, kind))
 {
     Kind = kind;
 }
Example #10
0
        /// <summary>
        /// Resolves an unary arithmetic operation.
        /// </summary>
        /// <param name="kind">The arithmetic kind.</param>
        /// <param name="type">The operation type.</param>
        /// <param name="fastMath">True, to use a fast-math operation.</param>
        /// <returns>The resolved arithmetic operation.</returns>
        public static string GetArithmeticOperation(
            UnaryArithmeticKind kind,
            ArithmeticBasicValueType type,
            bool fastMath)
        {
            var key = (kind, type);

            if (fastMath &&
                UnaryArithmeticOperationsFastMath.TryGetValue(key, out string operation) ||
                UnaryArithmeticOperations.TryGetValue(key, out operation))
            {
                return(operation);
            }
            throw new NotSupportedIntrinsicException(kind.ToString());
        }
Example #11
0
        private static TypeNode ComputeType(
            IRContext context,
            ValueReference operand,
            UnaryArithmeticKind kind)
        {
            var type = operand.Type;

            switch (kind)
            {
            case UnaryArithmeticKind.IsInfF:
            case UnaryArithmeticKind.IsNaNF:
                type = context.GetPrimitiveType(BasicValueType.Int1);
                break;
            }
            return(type);
        }
Example #12
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)
        {
            // Check for constants
            if (node is PrimitiveValue value)
            {
                return(UnaryArithmeticFoldConstants(location, value, kind));
            }

            return
                (UnaryArithmeticSimplify(
                     location,
                     node,
                     kind,
                     flags)
                 ?? Append(new UnaryArithmeticValue(
                               GetInitializer(location),
                               node,
                               kind,
                               flags)));
        }
Example #13
0
 /// <summary>
 /// Creates a unary arithmetic operation.
 /// </summary>
 /// <param name="node">The operand.</param>
 /// <param name="kind">The operation kind.</param>
 /// <returns>A node that represents the arithmetic operation.</returns>
 public ValueReference CreateArithmetic(
     Value node,
     UnaryArithmeticKind kind) =>
 CreateArithmetic(node, kind, ArithmeticFlags.None);
Example #14
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:
                    if (node is UnaryArithmeticValue otherValue &&
                        otherValue.Kind == UnaryArithmeticKind.Not)
                    {
                        return(otherValue.Value);
                    }

                    if (node is 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));
                    }
                    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)));
        }
Example #15
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)));
        }