/// <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); }
public void Visit(BinaryArithmeticValue value) { if (Get <BinaryArithmeticValue>().Kind != value.Kind || Get <BinaryArithmeticValue>().Flags != value.Flags) { Fail(); } }
/// <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);
/// <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(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(); } } }
/// <summary cref="IValueVisitor.Visit(BinaryArithmeticValue)"/> public void Visit(BinaryArithmeticValue value) => CodeGenerator.GenerateCode(value);
/// <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))); }