private void FillWith(
            ValueTag array,
            IReadOnlyList <Constant> data,
            IType elementType,
            NamedInstructionBuilder insertionPoint)
        {
            var arrayType = insertionPoint.Graph.GetValueType(array);
            var indexSpec = IndexType.GetIntegerSpecOrNull();

            for (int i = 0; i < data.Count; i++)
            {
                insertionPoint.InsertBefore(
                    Instruction.CreateStoreElementIntrinsic(
                        elementType,
                        arrayType,
                        new[] { IndexType },
                        insertionPoint.InsertBefore(Instruction.CreateConstant(data[i], elementType)),
                        array,
                        new[]
                {
                    insertionPoint.InsertBefore(
                        Instruction.CreateConstant(
                            new IntegerConstant(i, indexSpec),
                            IndexType))
                    .Tag
                }));
            }
        }
        /// <inheritdoc/>
        public override void Expand(NamedInstructionBuilder instance)
        {
            var insn = instance.Instruction;

            AssertIsPrototypeOf(insn);

            var gfp = instance.InsertBefore(
                Instruction.CreateGetFieldPointer(
                    Field, insn.Arguments[0]));

            instance.Instruction = Instruction.CreateLoad(Field.FieldType, gfp);
        }
        private static ValueTag ConvertThisArgument(
            ValueTag thisArgument,
            IType expectedThisType,
            NamedInstructionBuilder insertionPoint)
        {
            var thisType = insertionPoint.Graph.GetValueType(thisArgument);

            if (thisType != expectedThisType)
            {
                return(insertionPoint.InsertBefore(
                           Instruction.CreateReinterpretCast(
                               (PointerType)expectedThisType,
                               thisArgument)));
            }
            else
            {
                return(thisArgument);
            }
        }
Beispiel #4
0
        private static void ReassociateNonAssociative(NamedInstructionBuilder instruction)
        {
            // Look for instructions that compute an expression that looks
            // like so: `(a op1 b) op1 c` and replace it with `a op1 (b op2 c)`,
            // where `op2` is some (associative) operator such that the transformation
            // is semantics-preserving, e.g., op1 == (-) and op2 == (+) for integers.
            //
            // Here's why this transformation is useful: consider the following
            // expression: `(((x - 1) - 1) - 1) - 1`. It is clear that this can be
            // optimized to `x - 4`, but it's not super easy to see how: the reduction-
            // based reassociation doesn't apply to nonassociative operators. However,
            // by rewriting the expression as `x - (1 + 1 + 1 + 1)`, we can apply
            // reduction-based reassocation to the RHS.

            var proto = instruction.Prototype as IntrinsicPrototype;
            IntrinsicPrototype rightPrototype;

            if (proto == null || !IsLeftToRightReassociable(proto, out rightPrototype))
            {
                return;
            }

            NamedInstructionBuilder left;

            if (instruction.Graph.TryGetInstruction(instruction.Instruction.Arguments[0], out left) &&
                left.Prototype == proto)
            {
                var uses = instruction.Graph.GetAnalysisResult <ValueUses>();
                if (uses.GetUseCount(left) == 1)
                {
                    var right = instruction.InsertBefore(
                        rightPrototype.Instantiate(
                            new[]
                    {
                        left.Instruction.Arguments[1],
                        instruction.Instruction.Arguments[1]
                    }));
                    instruction.Instruction = proto.Instantiate(new[] { left.Instruction.Arguments[0], right });
                    instruction.Graph.RemoveInstruction(left);
                }
            }
        }
Beispiel #5
0
        private static void MaterializeReduction(
            IReadOnlyList <ValueTag> args,
            InstructionPrototype prototype,
            NamedInstructionBuilder result)
        {
            if (args.Count == 1)
            {
                result.Instruction = Instruction.CreateCopy(result.ResultType, args[0]);
                return;
            }

            var accumulator = args[0];

            for (int i = 1; i < args.Count - 1; i++)
            {
                accumulator = result.InsertBefore(
                    prototype.Instantiate(new[] { accumulator, args[i] }));
            }
            result.Instruction = prototype.Instantiate(new[] { accumulator, args[args.Count - 1] });
        }
Beispiel #6
0
        private static NamedInstructionBuilder ConstantFold(
            ValueTag first,
            ValueTag second,
            InstructionPrototype prototype,
            NamedInstructionBuilder insertionPoint)
        {
            var      graph = insertionPoint.Graph;
            Constant firstConstant;
            Constant secondConstant;

            if (IsConstant(first, insertionPoint.Graph.ToImmutable(), out firstConstant) &&
                IsConstant(second, insertionPoint.Graph.ToImmutable(), out secondConstant))
            {
                var newConstant = ConstantPropagation.EvaluateDefault(
                    prototype,
                    new[] { firstConstant, secondConstant });
                if (newConstant != null)
                {
                    return(insertionPoint.InsertBefore(
                               Instruction.CreateConstant(newConstant, prototype.ResultType)));
                }
            }
            return(null);
        }
Beispiel #7
0
        private bool TryRewriteStore(
            NamedInstructionBuilder instruction,
            Dictionary <ValueTag, Dictionary <IField, ValueTag> > replacements)
        {
            var storeProto = (StorePrototype)instruction.Prototype;
            var pointer    = storeProto.GetPointer(instruction.Instruction);
            var value      = storeProto.GetValue(instruction.Instruction);

            NamedInstructionBuilder valueInstruction;

            if (instruction.Graph.TryGetInstruction(value, out valueInstruction) &&
                valueInstruction.Prototype is LoadPrototype)
            {
                var loadPointer = valueInstruction.Arguments[0];
                if (replacements.ContainsKey(pointer))
                {
                    if (replacements.ContainsKey(loadPointer))
                    {
                        foreach (var pair in replacements[pointer].Reverse())
                        {
                            // Copy each field as follows:
                            //
                            //     val = load(field_type)(field_replacement_1);
                            //     _ = store(field_replacement_2, val);
                            //
                            var fieldValue = valueInstruction.InsertAfter(
                                Instruction.CreateLoad(pair.Key.FieldType, replacements[loadPointer][pair.Key]));

                            instruction.InsertAfter(
                                Instruction.CreateStore(
                                    pair.Key.FieldType,
                                    pair.Value,
                                    fieldValue));
                        }
                    }
                    else
                    {
                        CreateFieldwiseCopy(pointer, loadPointer, valueInstruction, instruction, replacements);
                    }

                    // Replace the store with a load, in case someone is
                    // using the value it returns.
                    instruction.Instruction = Instruction.CreateLoad(
                        instruction.Instruction.ResultType,
                        pointer);
                    return(true);
                }
                else if (replacements.ContainsKey(loadPointer) && CanAccessFields(storeProto.ResultType))
                {
                    // We're not scalarrepl'ing the store's address, but we are scalarrepl'ing the store's
                    // value. We could just leave this as-is and have the load lowering hash it out,
                    // but we can generate better code by storing values directly into the destination.
                    foreach (var pair in replacements[loadPointer])
                    {
                        var fieldValue = valueInstruction.InsertBefore(
                            Instruction.CreateLoad(pair.Key.FieldType, pair.Value));

                        var fieldPointer = instruction.InsertBefore(
                            Instruction.CreateGetFieldPointer(pair.Key, pointer));

                        instruction.InsertBefore(
                            Instruction.CreateStore(pair.Key.FieldType, fieldPointer, fieldValue));
                    }
                    instruction.Instruction = Instruction.CreateLoad(
                        instruction.Instruction.ResultType,
                        pointer);
                    return(true);
                }
                else
                {
                    return(false);
                }
            }
            else if (replacements.ContainsKey(pointer))
            {
                // If we're *not* dealing with a pointer-to-pointer copy, then things
                // are going to get ugly: we'll need to store the value in a temporary
                // and then perform a fieldwise copy from that temporary.
                var temporary = instruction.Graph.EntryPoint.InsertInstruction(
                    0,
                    Instruction.CreateAlloca(storeProto.ResultType),
                    pointer.Name + ".scalarrepl.temp");

                var tempStore = instruction.InsertAfter(
                    storeProto.Instantiate(temporary, value));

                CreateFieldwiseCopy(pointer, temporary, tempStore, tempStore, replacements);

                // Replace the store with a load, in case someone is
                // using the value it returns.
                instruction.Instruction = Instruction.CreateLoad(
                    instruction.Instruction.ResultType,
                    pointer);
                return(true);
            }
            else
            {
                return(false);
            }
        }