Пример #1
0
        public void Integer_modulo()
        {
            const string source  = @"
; #0 int32
; #1 int32
; #2 int32
BB_0:
    Load 1234 -> #0
    Load 56 -> #1
    Modulo #0 % #1 -> #2
    Return #2
";
            var          method  = MethodAssembler.Assemble(source, "Test::Method");
            var          lowered = LoweringX64.Lower(method);

            // The dividend must be in RAX and the result in RDX
            const string expected = @"
; #0 int32 [?]
; #1 int32 [?]
; #2 int32 [?]
; #3 int32 [rax]
; #4 int32 [rdx]
; #5 int32 [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    LoadInt 0 0 56 -> 1
    Move 0 0 0 -> 3
    IntegerModulo 3 1 0 -> 4
    Move 4 0 0 -> 2
    Move 2 0 0 -> 5
    Return 5 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #2
0
        public void Single_basic_block_with_same_variable_assigned_thrice()
        {
            // int32 a = 0;
            // a = 1;
            // a = 2;
            // return a;
            const string source   = @"
; #0   int32
; #1   int32
; #2   int32
BB_0:
    Load 0 -> #0
    Load 1 -> #1
    CopyValue #1 -> #0
    Load 2 -> #2
    CopyValue #2 -> #0
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32
; #1   int32
; #2   int32
BB_0:
    Load 0 -> #0
    Load 1 -> #1
    Load 2 -> #2
    Return #2
";

            AssertDisassembly(result, expected);
        }
Пример #3
0
        public void Single_basic_block_with_reassignment_of_parameter()
        {
            // int32 TwiceParamSquared(int32 a)
            // {
            //     a = a * a;
            //     a = a + a;
            //     return a;
            // }
            const string source   = @"
; #0   int32 param
BB_0:
    Multiply #0 * #0 -> #0
    Add #0 + #0 -> #0
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32 param
; #1   int32
; #2   int32
BB_0:
    Multiply #0 * #0 -> #1
    Add #1 + #1 -> #2
    Return #2
";

            AssertDisassembly(result, expected);
        }
Пример #4
0
        public void Boolean_set_from_comparison(string highOp, string expectedLowOp)
        {
            var source  = $@"
; #0 int32
; #1 int32
; #2 bool
BB_0:
    Load 1234 -> #0
    Load 5678 -> #1
    {highOp} #0 ?? #1 -> #2
    Return #2
";
            var method  = MethodAssembler.Assemble(source, "Test::Method");
            var lowered = LoweringX64.Lower(method);

            var expected = $@"
; #0 int32 [?]
; #1 int32 [?]
; #2 bool [?]
; #3 bool [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    LoadInt 0 0 5678 -> 1
    Compare 0 1 0 -> 0
    {expectedLowOp} 0 0 0 -> 2
    Move 2 0 0 -> 3
    Return 3 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #5
0
        public void Boolean_binary_ops(string highOp, string expectedLowOp)
        {
            var source  = $@"
; #0 bool
; #1 bool
; #2 bool
BB_0:
    Load true -> #0
    Load false -> #1
    {highOp} #0 ?? #1 -> #2
    Return #2
";
            var method  = MethodAssembler.Assemble(source, "Test::Method");
            var lowered = LoweringX64.Lower(method);

            var expected = $@"
; #0 bool [?]
; #1 bool [?]
; #2 bool [?]
; #3 bool [rax]
LB_0:
    LoadInt 0 0 1 -> 0
    LoadInt 0 0 0 -> 1
    {expectedLowOp} 0 1 0 -> 2
    Move 2 0 0 -> 3
    Return 3 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #6
0
        public void Boolean_negation()
        {
            const string source  = @"
; #0 bool
; #1 bool
BB_0:
    Load false -> #0
    BitwiseNot #0 -> #1
    Return #1
";
            var          method  = MethodAssembler.Assemble(source, "Test::Method");
            var          lowered = LoweringX64.Lower(method);

            const string expected = @"
; #0 bool [?]
; #1 bool [?]
; #2 bool [rax]
LB_0:
    LoadInt 0 0 0 -> 0
    Test 0 0 0 -> 0
    SetIfEqual 0 0 0 -> 1
    Move 1 0 0 -> 2
    Return 2 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #7
0
        public void Integer_shift(string highOp, string expectedLowOp)
        {
            var source  = $@"
; #0 int32
; #1 int32
; #2 int32
BB_0:
    Load 1234 -> #0
    Load 5678 -> #1
    {highOp} #0 ?? #1 -> #2
    Return #2
";
            var method  = MethodAssembler.Assemble(source, "Test::Method");
            var lowered = LoweringX64.Lower(method);

            var expected = $@"
; #0 int32 [?]
; #1 int32 [?]
; #2 int32 [?]
; #3 int32 [rcx]
; #4 int32 [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    LoadInt 0 0 5678 -> 1
    Move 1 0 0 -> 3
    {expectedLowOp} 0 3 0 -> 2
    Move 2 0 0 -> 4
    Return 4 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #8
0
        public void Successive_basic_blocks()
        {
            const string source   = @"
; #0   int32 param
BB_0:
    Multiply #0 * #0 -> #0

BB_1:
    Add #0 + #0 -> #0
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32 param
; #1   int32
; #2   int32
BB_0:
    Multiply #0 * #0 -> #1

BB_1:
    Add #1 + #1 -> #2
    Return #2
";

            AssertDisassembly(result, expected);
        }
Пример #9
0
        public void Integer_unary_arithmetic(string highOp, string expectedLowOp)
        {
            var source  = $@"
; #0 int32
; #1 int32
BB_0:
    Load 1234 -> #0
    {highOp} #0 -> #1
    Return #1
";
            var method  = MethodAssembler.Assemble(source, "Test::Method");
            var lowered = LoweringX64.Lower(method);

            var expected = $@"
; #0 int32 [?]
; #1 int32 [?]
; #2 int32 [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    {expectedLowOp} 0 0 0 -> 1
    Move 1 0 0 -> 2
    Return 2 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #10
0
        public void Integer_compare_and_branch()
        {
            const string source  = @"
; #0 int32
; #1 int32
; #2 bool
; #3 int32
; #4 int32
BB_0:
    Load 1234 -> #0
    Load 5678 -> #1
    Equal #0 == #1 -> #2
    BranchIf #2 ==> BB_1
    ==> BB_2
BB_1:
    Load 1 -> #3
    Return #3
BB_2:
    Load 2 -> #4
    Return #4
";
            var          method  = MethodAssembler.Assemble(source, "Test::Method");
            var          lowered = LoweringX64.Lower(method);

            const string expected = @"
; #0 int32 [?]
; #1 int32 [?]
; #2 bool [?]
; #3 int32 [?]
; #4 int32 [?]
; #5 int32 [rax]
; #6 int32 [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    LoadInt 0 0 5678 -> 1
    Compare 0 1 0 -> 0
    SetIfEqual 0 0 0 -> 2
    Test 2 0 0 -> 0
    JumpIfNotEqual 0 0 0 -> 1
    Jump 0 0 0 -> 2
LB_1:
    LoadInt 0 0 1 -> 3
    Move 3 0 0 -> 5
    Return 5 0 0 -> 0
LB_2:
    LoadInt 0 0 2 -> 4
    Move 4 0 0 -> 6
    Return 6 0 0 -> 0
";

            AssertDump(lowered, expected);

            Assert.That(lowered.Blocks[0].Predecessors, Is.Empty);
            Assert.That(lowered.Blocks[0].Successors, Is.EqualTo(new int[] { 1, 2 }));
            Assert.That(lowered.Blocks[1].Predecessors, Is.EqualTo(new int[] { 0 }));
            Assert.That(lowered.Blocks[1].Successors, Is.Empty);
            Assert.That(lowered.Blocks[2].Predecessors, Is.EqualTo(new int[] { 0 }));
            Assert.That(lowered.Blocks[2].Successors, Is.Empty);
        }
Пример #11
0
        public void Single_basic_block_with_call()
        {
            // int32 Caller(int32 a, bool c)
            // {
            //     int32 b = a;
            //     if (c) { b = b * b; }
            //     return Callee(a, b, b + b);
            // }
            const string source   = @"
; #0   int32 param
; #1   bool param
; #2   int32
; #3   int32
; #4   int32
; #5   int32
BB_0:
    CopyValue #0 -> #2
    BranchIf #1 ==> BB_1
    ==> BB_2

BB_1:
    Multiply #2 * #2 -> #3
    CopyValue #3 -> #2

BB_2:
    Add #2 + #2 -> #4
    Call Test::Callee(#0, #2, #4) -> #5
    Return #5
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // Value #5 is expected to be unused (created in Phi construction)
            const string expected = @"
; #0   int32 param
; #1   bool param
; #2   int32
; #3   int32
; #4   int32
; #5   int32
; #6   int32
BB_0:
    BranchIf #1 ==> BB_1
    ==> BB_2

BB_1:
    Multiply #0 * #0 -> #2

BB_2:
    PHI (#0, #2) -> #3
    Add #3 + #3 -> #4
    Call Test::Callee(#0, #3, #4) -> #6
    Return #6
";

            AssertDisassembly(result, expected);
        }
Пример #12
0
        protected static void EmitAndAssertDisassembly(string source, string expected)
        {
            var sourceMethod      = MethodAssembler.Assemble(source, "Test::Method");
            var disassemblyWriter = new StringWriter();
            var codeGen           = new WindowsX64CodeGenerator(Stream.Null, disassemblyWriter);

            codeGen.EmitMethod(sourceMethod, 0, false, null);

            Assert.That(disassemblyWriter.ToString().Replace("\r\n", "\n").Trim(),
                        Is.EqualTo(expected.Replace("\r\n", "\n").Trim()));
        }
Пример #13
0
        public void Branch_that_merges_back_and_produces_phi()
        {
            // int32 f(int32 value, bool square)
            // {
            //     int32 result = value;
            //     if (square) { result = result * result; }
            //     return result;
            // }
            const string source   = @"
; #0   int32 param
; #1   bool param
; #2   int32
; #3   int32
BB_0:
    CopyValue #0 -> #2
    BranchIf #1 ==> BB_1
    ==> BB_2

BB_1:
    Multiply #2 * #2 -> #3
    CopyValue #3 -> #2

BB_2:
    Return #2
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32 param
; #1   bool param
; #2   int32
; #3   int32
BB_0:
    BranchIf #1 ==> BB_1
    ==> BB_2

BB_1:
    Multiply #0 * #0 -> #2

BB_2:
    PHI (#0, #2) -> #3
    Return #3
";

            AssertDisassembly(result, expected);
        }
Пример #14
0
        public void Trivial_phi_is_optimized_away_in_complete_cfg()
        {
            // int32 F(bool p, int32 v)
            // {
            //     int32 result = v;
            //     if (p) { result = v; }
            //     return result;
            // }
            const string source   = @"
; #0   bool param
; #1   int32 param
; #2   int32
BB_0:
    CopyValue #1 -> #2
    BranchIf #0 ==> BB_1
    ==> BB_2

BB_1:
    CopyValue #1 -> #2

BB_2:
    Return #2
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // PHI(#1, #1) is optimized away.
            // Note that an unused value (#2) is created but it should hurt no-one, and can be removed in optimization.
            const string expected = @"
; #0   bool param
; #1   int32 param
; #2   int32
BB_0:
    BranchIf #0 ==> BB_1
    ==> BB_2

BB_1:

BB_2:
    Return #1
";

            AssertDisassembly(result, expected);
        }
Пример #15
0
        public void Boolean_compare_and_branch()
        {
            const string source  = @"
; #0 bool
; #1 int32
; #2 int32
BB_0:
    Load true -> #0
    BranchIf #0 ==> BB_1
    ==> BB_2
BB_1:
    Load 1 -> #1
    Return #1
BB_2:
    Load 2 -> #2
    Return #2
";
            var          method  = MethodAssembler.Assemble(source, "Test::Method");
            var          lowered = LoweringX64.Lower(method);

            const string expected = @"
; #0 bool [?]
; #1 int32 [?]
; #2 int32 [?]
; #3 int32 [rax]
; #4 int32 [rax]
LB_0:
    LoadInt 0 0 1 -> 0
    Test 0 0 0 -> 0
    JumpIfNotEqual 0 0 0 -> 1
    Jump 0 0 0 -> 2
LB_1:
    LoadInt 0 0 1 -> 1
    Move 1 0 0 -> 3
    Return 3 0 0 -> 0
LB_2:
    LoadInt 0 0 2 -> 2
    Move 2 0 0 -> 4
    Return 4 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #16
0
        public void Void_returns_use_shared_value()
        {
            // void F(bool p)
            // {
            //     if (p) { return; }
            // }
            const string source   = @"
; #0   bool param
; #1   void
; #2   void
BB_0:
    BranchIf #0 ==> BB_1
    ==> BB_2

BB_1:
    Return #1

BB_2:
    Return #2
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // The same (uninitialized) void value is used for both returns
            const string expected = @"
; #0   bool param
; #1   void
BB_0:
    BranchIf #0 ==> BB_1
    ==> BB_2

BB_1:
    Return #1

BB_2:
    Return #1
";

            AssertDisassembly(result, expected);
        }
Пример #17
0
        public void Constant_integer_load_and_return()
        {
            const string source  = @"
; #0 int32
BB_0:
    Load 1234 -> #0
    Return #0
";
            var          method  = MethodAssembler.Assemble(source, "Test::Method");
            var          lowered = LoweringX64.Lower(method);

            const string expected = @"
; #0 int32 [?]
; #1 int32 [rax]
LB_0:
    LoadInt 0 0 1234 -> 0
    Move 0 0 0 -> 1
    Return 1 0 0 -> 0
";

            AssertDump(lowered, expected);
        }
Пример #18
0
        public void Single_basic_block_with_already_ssa_arithmetic_on_parameters()
        {
            // int32 f(int32 a, int32 b)
            // {
            //     int32 c = a + b;
            //     return c - a;
            // }
            const string source   = @"
; #0   int32 param
; #1   int32 param
; #2   int32
; #3   int32
BB_0:
    Add #0 + #1 -> #2
    Subtract #2 - #0 -> #3
    Return #3
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // The source is already in SSA form, so no diff is expected
            AssertDisassembly(result, source);
        }
Пример #19
0
        public void Branch_that_does_not_merge_back()
        {
            const string source   = @"
; #0   int32 param
; #1   bool param
; #2   int32
BB_0:
    BranchIf #1 ==> BB_1
    ==> BB_2

BB_1:
    Multiply #0 * #0 -> #2
    Return #2

BB_2:
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // No change expected
            AssertDisassembly(result, source);
        }
Пример #20
0
        public void Debug_log_contains_method_and_register_dump()
        {
            const string source = @"
; #0   int32 param
BB_0:
    Return #0";

            using (var dumpWriter = new StringWriter())
            {
                var codeGen = new WindowsX64CodeGenerator(Stream.Null, null);
                codeGen.EmitMethod(MethodAssembler.Assemble(source, "Test::Method"), 0, false, dumpWriter);

                var dumpString = dumpWriter.ToString();

                // Dumped LIR
                Assert.That(dumpString, Contains.Substring("Return 2 0 0 -> 0"));

                // Locals
                // #0 has no forced position, the others have
                Assert.That(dumpString, Contains.Substring("; #0 int32 [?]"));
                Assert.That(dumpString, Contains.Substring("; #1 int32 [rcx]"));
                Assert.That(dumpString, Contains.Substring("; #2 int32 [rax]"));
            }
        }
Пример #21
0
        public void Double_branch_that_merges_back_and_produces_phis_in_two_blocks()
        {
            // int32 f(int32 value, bool square, bool twice)
            // {
            //     int32 result = value;
            //     if (square) {
            //         result = result * result;
            //         if (twice) { result = result * result; }
            //     }
            //     return result;
            // }
            const string source   = @"
; #0   int32 param
; #1   bool param
; #2   bool param
; #3   int32
; #4   int32
; #5   int32
BB_0:
    CopyValue #0 -> #3
    BranchIf #1 ==> BB_1
    ==> BB_4

BB_1:
    Multiply #3 * #3 -> #4
    CopyValue #4 -> #3
    BranchIf #2 ==> BB_2
    ==> BB_3

BB_2:
    Multiply #3 * #3 -> #5
    CopyValue #5 -> #3

BB_3:

BB_4:
    Return #3
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32 param
; #1   bool param
; #2   bool param
; #3   int32
; #4   int32
; #5   int32
; #6   int32
BB_0:
    BranchIf #1 ==> BB_1
    ==> BB_4

BB_1:
    Multiply #0 * #0 -> #3
    BranchIf #2 ==> BB_2
    ==> BB_3

BB_2:
    Multiply #3 * #3 -> #4

BB_3:
    PHI (#3, #4) -> #6

BB_4:
    PHI (#0, #6) -> #5
    Return #5
";

            AssertDisassembly(result, expected);
        }
Пример #22
0
 public MethodServices()
 {
     MethodAssembler = new MethodAssembler();
 }
Пример #23
0
        public void Operands_in_non_trivial_phi_are_not_removed()
        {
            // int32 F(int32 a, int32 b)
            // {
            //     int32 result = a;
            //     if (b % 2 == 0) { result = b; }
            //     else if (b % 3 == 0) { result = b; }
            //     return result;
            // }
            const string source   = @"
; #0   int32 param
; #1   int32 param
; #2   int32
; #3   int32
; #4   int32
; #5   int32
; #6   bool
; #7   int32
; #8   int32
; #9   int32
; #10  bool
BB_0:
    CopyValue #0 -> #2
    Load 2 -> #3
    Modulo #1 % #3 -> #4
    Load 0 -> #5
    Equal #4 == #5 -> #6
    BranchIf #6 ==> BB_1
    ==> BB_2

BB_1:
    CopyValue #1 -> #2
    ==> BB_4

BB_2:
    Load 3 -> #7
    Modulo #1 % #7 -> #8
    Load 0 -> #9
    Equal #8 == #9 -> #10
    BranchIf #10 ==> BB_3
    ==> BB_4

BB_3:
    CopyValue #1 -> #2

BB_4:
    Return #2
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            // The duplicate operand in PHI (#0, #1, #1) is not optimized away, as it encodes information
            // which value comes from which branch.
            const string expected = @"
; #0   int32 param
; #1   int32 param
; #2   int32
; #3   int32
; #4   int32
; #5   bool
; #6   int32
; #7   int32
; #8   int32
; #9   bool
; #10  int32
BB_0:
    Load 2 -> #2
    Modulo #1 % #2 -> #3
    Load 0 -> #4
    Equal #3 == #4 -> #5
    BranchIf #5 ==> BB_1
    ==> BB_2

BB_1:
    ==> BB_4

BB_2:
    Load 3 -> #6
    Modulo #1 % #6 -> #7
    Load 0 -> #8
    Equal #7 == #8 -> #9
    BranchIf #9 ==> BB_3
    ==> BB_4

BB_3:

BB_4:
    PHI (#0, #1, #1) -> #10
    Return #10
";

            AssertDisassembly(result, expected);
        }
Пример #24
0
        public void While_loop_where_iteration_variable_has_more_complex_phi()
        {
            // int32 CountToTen()
            // {
            //     int32 result = 0;
            //     while (result < 10)
            //     {
            //         if (result % 2 == 0) { result = result + 1; }
            //         else { result = result + 2; }
            //     }
            //     return result;
            // }
            const string source   = @"
; #0   int32
; #1   int32
; #2   bool
; #3   int32
; #4   int32
; #5   int32
; #6   bool
; #7   int32
; #8   int32
; #9   int32
; #10  int32
BB_0:
    Load 0 -> #0

BB_1:
    Load 10 -> #1
    Less #0 < #1 -> #2
    BranchIf #2 ==> BB_2
    ==> BB_6

BB_2:
    Load 2 -> #3
    Modulo #0 % #3 -> #4
    Load 0 -> #5
    Equal #4 == #5 -> #6
    BranchIf #6 ==> BB_3
    ==> BB_4

BB_3:
    Load 1 -> #7
    Add #0 + #7 -> #8
    CopyValue #8 -> #0
    ==> BB_5

BB_4:
    Load 2 -> #9
    Add #0 + #9 -> #10
    CopyValue #10 -> #0

BB_5:
    ==> BB_1

BB_6:
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32
; #1   int32
; #2   int32
; #3   bool
; #4   int32
; #5   int32
; #6   int32
; #7   bool
; #8   int32
; #9   int32
; #10  int32
; #11  int32
; #12  int32
BB_0:
    Load 0 -> #0

BB_1:
    PHI (#0, #12) -> #2
    Load 10 -> #1
    Less #2 < #1 -> #3
    BranchIf #3 ==> BB_2
    ==> BB_6

BB_2:
    Load 2 -> #4
    Modulo #2 % #4 -> #5
    Load 0 -> #6
    Equal #5 == #6 -> #7
    BranchIf #7 ==> BB_3
    ==> BB_4

BB_3:
    Load 1 -> #8
    Add #2 + #8 -> #9
    ==> BB_5

BB_4:
    Load 2 -> #10
    Add #2 + #10 -> #11

BB_5:
    PHI (#11, #9) -> #12
    ==> BB_1

BB_6:
    Return #2
";

            AssertDisassembly(result, expected);
        }
Пример #25
0
        public void Simple_while_loop()
        {
            // int32 CountToTen()
            // {
            //     int32 result = 0;
            //     while (result < 10) { result = result + 1; }
            //     return result;
            // }
            const string source   = @"
; #0   int32
; #1   int32
; #2   bool
; #3   int32
; #4   int32
BB_0:
    Load 0 -> #0

BB_1:
    Load 10 -> #1
    Less #0 < #1 -> #2
    BranchIf #2 ==> BB_2
    ==> BB_3

BB_2:
    Load 1 -> #3
    Add #0 + #3 -> #4
    CopyValue #4 -> #0
    ==> BB_1

BB_3:
    Return #0
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   int32
; #1   int32
; #2   int32
; #3   bool
; #4   int32
; #5   int32
BB_0:
    Load 0 -> #0

BB_1:
    PHI (#0, #5) -> #2
    Load 10 -> #1
    Less #2 < #1 -> #3
    BranchIf #3 ==> BB_2
    ==> BB_3

BB_2:
    Load 1 -> #4
    Add #2 + #4 -> #5
    ==> BB_1

BB_3:
    Return #2
";

            AssertDisassembly(result, expected);
        }
Пример #26
0
        public void Branch_that_merges_back_three_way_and_produces_one_phi()
        {
            // int32 f(bool a, bool b)
            // {
            //     int32 result = 0;
            //     if (a & b) { result = 3; }
            //     else if (a) { result = 2; }
            //     return result;
            // }
            const string source   = @"
; #0   bool param
; #1   bool param
; #2   int32
; #3   bool
; #4   int32
; #5   int32
BB_0:
    Load 0 -> #2
    BitwiseAnd #0 & #1 -> #3
    BranchIf #3 ==> BB_1
    ==> BB_2

BB_1:
    Load 3 -> #4
    CopyValue #4 -> #2
    ==> BB_4

BB_2:
    BranchIf #0 ==> BB_3
    ==> BB_4

BB_3:
    Load 2 -> #5
    CopyValue #5 -> #2

BB_4:
    Return #2
";
            var          original = MethodAssembler.Assemble(source, "Test::Method");
            var          result   = new SsaConverter().ConvertToSsa(original);

            const string expected = @"
; #0   bool param
; #1   bool param
; #2   int32
; #3   bool
; #4   int32
; #5   int32
; #6   int32
BB_0:
    Load 0 -> #2
    BitwiseAnd #0 & #1 -> #3
    BranchIf #3 ==> BB_1
    ==> BB_2

BB_1:
    Load 3 -> #4
    ==> BB_4

BB_2:
    BranchIf #0 ==> BB_3
    ==> BB_4

BB_3:
    Load 2 -> #5

BB_4:
    PHI (#2, #5, #4) -> #6
    Return #6
";

            AssertDisassembly(result, expected);
        }