Пример #1
0
        private static void CreateFieldwiseCopy(
            ValueTag destinationPointer,
            ValueTag sourcePointer,
            NamedInstructionBuilder loadInsertionPoint,
            NamedInstructionBuilder storeInsertionPoint,
            Dictionary <ValueTag, Dictionary <IField, ValueTag> > replacements)
        {
            foreach (var pair in replacements[destinationPointer].Reverse())
            {
                // Copy each field as follows:
                //
                //     field_ptr = get_field_pointer(field)(load_ptr);
                //     val = load(field_type)(field_ptr);
                //     _ = store(field_replacement, val);
                //
                var fieldPtr = loadInsertionPoint.InsertAfter(
                    Instruction.CreateGetFieldPointer(pair.Key, sourcePointer));

                var fieldValue = fieldPtr.InsertAfter(
                    Instruction.CreateLoad(pair.Key.FieldType, fieldPtr));

                var storeInsert = storeInsertionPoint.Tag == loadInsertionPoint.Tag
                    ? fieldValue
                    : storeInsertionPoint;

                storeInsert.InsertAfter(
                    Instruction.CreateStore(
                        pair.Key.FieldType,
                        pair.Value,
                        fieldValue));
            }
        }
Пример #2
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);
            }
        }