aboutsummaryrefslogtreecommitdiff
path: root/src/ARMeilleure/CodeGen/Optimizations/BlockPlacement.cs
blob: 5f0e377215bb2d5e3a51ed2dcb6da29d76b97986 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Diagnostics;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

namespace ARMeilleure.CodeGen.Optimizations
{
    static class BlockPlacement
    {
        public static void RunPass(ControlFlowGraph cfg)
        {
            bool update = false;

            BasicBlock block;
            BasicBlock nextBlock;

            BasicBlock lastBlock = cfg.Blocks.Last;

            // Move cold blocks at the end of the list, so that they are emitted away from hot code.
            for (block = cfg.Blocks.First; block != null; block = nextBlock)
            {
                nextBlock = block.ListNext;

                if (block.Frequency == BasicBlockFrequency.Cold)
                {
                    cfg.Blocks.Remove(block);
                    cfg.Blocks.AddLast(block);
                }

                if (block == lastBlock)
                {
                    break;
                }
            }

            for (block = cfg.Blocks.First; block != null; block = nextBlock)
            {
                nextBlock = block.ListNext;

                if (block.SuccessorsCount == 2)
                {
                    Operation branchOp = block.Operations.Last;

                    Debug.Assert(branchOp.Instruction == Instruction.BranchIf);

                    BasicBlock falseSucc = block.GetSuccessor(0);
                    BasicBlock trueSucc = block.GetSuccessor(1);

                    // If true successor is next block in list, invert the condition. We avoid extra branching by
                    // making the true side the fallthrough (i.e, convert it to the false side).
                    if (trueSucc == block.ListNext)
                    {
                        Comparison comp = (Comparison)branchOp.GetSource(2).AsInt32();
                        Comparison compInv = comp.Invert();

                        branchOp.SetSource(2, Const((int)compInv));

                        block.SetSuccessor(0, trueSucc);
                        block.SetSuccessor(1, falseSucc);

                        update = true;
                    }
                }
            }

            if (update)
            {
                cfg.Update();
            }
        }
    }
}