Exemple #1
0
        private static void StoreLocals(BasicBlock block, long outputs, RegisterType baseType, ExecutionMode mode)
        {
            Operand arg0 = Local(OperandType.I64);

            Operation loadArg0 = Operation(Instruction.LoadArgument, arg0, Const(0));

            block.Append(loadArg0);

            for (int bit = 0; bit < 64; bit++)
            {
                long mask = 1L << bit;

                if ((outputs & mask) == 0)
                {
                    continue;
                }

                Operand source = GetRegFromBit(bit, baseType, mode);

                long offset = NativeContext.GetRegisterOffset(source.GetRegister());

                Operand addr = Local(OperandType.I64);

                Operation calcOffsOp = Operation(Instruction.Add, addr, arg0, Const(offset));

                block.Append(calcOffsOp);

                Operation storeOp = Operation(Instruction.Store, null, addr, source);

                block.Append(storeOp);
            }
        }
        public static void Deconstruct(ControlFlowGraph cfg)
        {
            foreach (BasicBlock block in cfg.Blocks)
            {
                LinkedListNode <Node> node = block.Operations.First;

                while (node?.Value is PhiNode phi)
                {
                    LinkedListNode <Node> nextNode = node.Next;

                    Operand local = Local(phi.Destination.Type);

                    for (int index = 0; index < phi.SourcesCount; index++)
                    {
                        BasicBlock predecessor = phi.GetBlock(index);

                        Operand source = phi.GetSource(index);

                        predecessor.Append(new Operation(Instruction.Copy, local, source));

                        phi.SetSource(index, null);
                    }

                    Operation copyOp = new Operation(Instruction.Copy, phi.Destination, local);

                    block.Operations.AddBefore(node, copyOp);

                    phi.Destination = null;

                    block.Operations.Remove(node);

                    node = nextNode;
                }
            }
        }
Exemple #3
0
        private static void StoreLocals(BasicBlock block, long outputs, RegisterType baseType, bool isCompleteFunction)
        {
            if (Optimizations.AssumeStrictAbiCompliance && isCompleteFunction)
            {
                if (baseType == RegisterType.Integer || baseType == RegisterType.Flag)
                {
                    outputs = ClearCallerSavedIntRegs(outputs);
                }
                else /* if (baseType == RegisterType.Vector) */
                {
                    outputs = ClearCallerSavedVecRegs(outputs);
                }
            }

            Operand arg0 = Local(OperandType.I64);

            Operation loadArg0 = new Operation(Instruction.LoadArgument, arg0, Const(0));

            block.Append(loadArg0);

            for (int bit = 0; bit < 64; bit++)
            {
                long mask = 1L << bit;

                if ((outputs & mask) == 0)
                {
                    continue;
                }

                Operand source = GetRegFromBit(bit, baseType);

                long offset = NativeContext.GetRegisterOffset(source.GetRegister());

                Operand addr = Local(OperandType.I64);

                Operation calcOffsOp = new Operation(Instruction.Add, addr, arg0, Const(offset));

                block.Append(calcOffsOp);

                Operation storeOp = new Operation(Instruction.Store, null, addr, source);

                block.Append(storeOp);
            }
        }
Exemple #4
0
        public static void Deconstruct(ControlFlowGraph cfg)
        {
            for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
            {
                Operation operation = block.Operations.First;

                while (operation != default && operation.Instruction == Instruction.Phi)
                {
                    Operation nextNode = operation.ListNext;

                    Operand local = Local(operation.Destination.Type);

                    PhiOperation phi = operation.AsPhi();

                    for (int index = 0; index < phi.SourcesCount; index++)
                    {
                        BasicBlock predecessor = phi.GetBlock(cfg, index);

                        Operand source = phi.GetSource(index);

                        predecessor.Append(Operation(Instruction.Copy, local, source));

                        phi.SetSource(index, default);
                    }

                    Operation copyOp = Operation(Instruction.Copy, operation.Destination, local);

                    block.Operations.AddBefore(operation, copyOp);

                    operation.Destination = default;

                    block.Operations.Remove(operation);

                    operation = nextNode;
                }
            }
        }
Exemple #5
0
        public static void Remove(BasicBlock[] blocks)
        {
            for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
            {
                BasicBlock block = blocks[blkIndex];

                LinkedListNode <INode> node = block.Operations.First;

                while (node != null)
                {
                    LinkedListNode <INode> nextNode = node.Next;

                    if (node.Value is not PhiNode phi)
                    {
                        node = nextNode;

                        continue;
                    }

                    for (int index = 0; index < phi.SourcesCount; index++)
                    {
                        Operand src = phi.GetSource(index);

                        BasicBlock srcBlock = phi.GetBlock(index);

                        Operation copyOp = new Operation(Instruction.Copy, phi.Dest, src);

                        srcBlock.Append(copyOp);
                    }

                    block.Operations.Remove(node);

                    node = nextNode;
                }
            }
        }
Exemple #6
0
        public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode)
        {
            // Compute local register inputs and outputs used inside blocks.
            RegisterMask[] localInputs  = new RegisterMask[cfg.Blocks.Count];
            RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];

            for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
            {
                for (Operation node = block.Operations.First; node != default; node = node.ListNext)
                {
                    for (int index = 0; index < node.SourcesCount; index++)
                    {
                        Operand source = node.GetSource(index);

                        if (source.Kind == OperandKind.Register)
                        {
                            Register register = source.GetRegister();

                            localInputs[block.Index] |= GetMask(register) & ~localOutputs[block.Index];
                        }
                    }

                    if (node.Destination != default && node.Destination.Kind == OperandKind.Register)
                    {
                        localOutputs[block.Index] |= GetMask(node.Destination.GetRegister());
                    }
                }
            }

            // Compute global register inputs and outputs used across blocks.
            RegisterMask[] globalCmnOutputs = new RegisterMask[cfg.Blocks.Count];

            RegisterMask[] globalInputs  = new RegisterMask[cfg.Blocks.Count];
            RegisterMask[] globalOutputs = new RegisterMask[cfg.Blocks.Count];

            bool modified;
            bool firstPass = true;

            do
            {
                modified = false;

                // Compute register outputs.
                for (int index = cfg.PostOrderBlocks.Length - 1; index >= 0; index--)
                {
                    BasicBlock block = cfg.PostOrderBlocks[index];

                    if (block.Predecessors.Count != 0 && !HasContextLoad(block))
                    {
                        BasicBlock predecessor = block.Predecessors[0];

                        RegisterMask cmnOutputs = localOutputs[predecessor.Index] | globalCmnOutputs[predecessor.Index];
                        RegisterMask outputs    = globalOutputs[predecessor.Index];

                        for (int pIndex = 1; pIndex < block.Predecessors.Count; pIndex++)
                        {
                            predecessor = block.Predecessors[pIndex];

                            cmnOutputs &= localOutputs[predecessor.Index] | globalCmnOutputs[predecessor.Index];
                            outputs    |= globalOutputs[predecessor.Index];
                        }

                        globalInputs[block.Index] |= outputs & ~cmnOutputs;

                        if (!firstPass)
                        {
                            cmnOutputs &= globalCmnOutputs[block.Index];
                        }

                        modified |= Exchange(globalCmnOutputs, block.Index, cmnOutputs);
                        outputs  |= localOutputs[block.Index];
                        modified |= Exchange(globalOutputs, block.Index, globalOutputs[block.Index] | outputs);
                    }
                    else
                    {
                        modified |= Exchange(globalOutputs, block.Index, localOutputs[block.Index]);
                    }
                }

                // Compute register inputs.
                for (int index = 0; index < cfg.PostOrderBlocks.Length; index++)
                {
                    BasicBlock block = cfg.PostOrderBlocks[index];

                    RegisterMask inputs = localInputs[block.Index];

                    for (int i = 0; i < block.SuccessorsCount; i++)
                    {
                        inputs |= globalInputs[block.GetSuccessor(i).Index];
                    }

                    inputs &= ~globalCmnOutputs[block.Index];

                    modified |= Exchange(globalInputs, block.Index, globalInputs[block.Index] | inputs);
                }

                firstPass = false;
            }while (modified);

            // Insert load and store context instructions where needed.
            for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
            {
                bool hasContextLoad = HasContextLoad(block);

                if (hasContextLoad)
                {
                    block.Operations.Remove(block.Operations.First);
                }

                Operand arg = default;

                // The only block without any predecessor should be the entry block.
                // It always needs a context load as it is the first block to run.
                if (block.Predecessors.Count == 0 || hasContextLoad)
                {
                    arg = Local(OperandType.I64);

                    Operation loadArg = block.Operations.AddFirst(Operation(Instruction.LoadArgument, arg, Const(0)));

                    LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector, mode, loadArg, arg);
                    LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer, mode, loadArg, arg);
                }

                bool hasContextStore = HasContextStore(block);

                if (hasContextStore)
                {
                    block.Operations.Remove(block.Operations.Last);
                }

                if (EndsWithReturn(block) || hasContextStore)
                {
                    if (arg == default)
                    {
                        arg = Local(OperandType.I64);

                        block.Append(Operation(Instruction.LoadArgument, arg, Const(0)));
                    }

                    StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer, mode, arg);
                    StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector, mode, arg);
                }
            }
        }
        private void InsertSplitCopiesAtEdges(ControlFlowGraph cfg)
        {
            int blocksCount = cfg.Blocks.Count;

            bool IsSplitEdgeBlock(BasicBlock block)
            {
                return(block.Index >= blocksCount);
            }

            for (LinkedListNode <BasicBlock> node = cfg.Blocks.First; node != null; node = node.Next)
            {
                BasicBlock block = node.Value;

                if (IsSplitEdgeBlock(block))
                {
                    continue;
                }

                bool hasSingleOrNoSuccessor = block.Next == null || block.Branch == null;

                foreach (BasicBlock successor in Successors(block))
                {
                    int succIndex = successor.Index;

                    // If the current node is a split node, then the actual successor node
                    // (the successor before the split) should be right after it.
                    if (IsSplitEdgeBlock(successor))
                    {
                        succIndex = Successors(successor).First().Index;
                    }

                    CopyResolver copyResolver = new CopyResolver();

                    foreach (int iIndex in _blockLiveIn[succIndex])
                    {
                        LiveInterval interval = _parentIntervals[iIndex];

                        if (!interval.IsSplit)
                        {
                            continue;
                        }

                        int lEnd   = _blockRanges[block.Index].End - 1;
                        int rStart = _blockRanges[succIndex].Start;

                        LiveInterval left  = interval.GetSplitChild(lEnd);
                        LiveInterval right = interval.GetSplitChild(rStart);

                        if (left != null && right != null && left != right)
                        {
                            copyResolver.AddSplit(left, right);
                        }
                    }

                    if (!copyResolver.HasCopy)
                    {
                        continue;
                    }

                    Operation[] sequence = copyResolver.Sequence();

                    if (hasSingleOrNoSuccessor)
                    {
                        foreach (Operation operation in sequence)
                        {
                            block.Append(operation);
                        }
                    }
                    else if (successor.Predecessors.Count == 1)
                    {
                        LinkedListNode <Node> prependNode = successor.Operations.AddFirst(sequence[0]);

                        for (int index = 1; index < sequence.Length; index++)
                        {
                            Operation operation = sequence[index];

                            prependNode = successor.Operations.AddAfter(prependNode, operation);
                        }
                    }
                    else
                    {
                        // Split the critical edge.
                        BasicBlock splitBlock = cfg.SplitEdge(block, successor);

                        foreach (Operation operation in sequence)
                        {
                            splitBlock.Append(operation);
                        }
                    }
                }
            }
        }