def test_reverse_sequence_3(ctx, func, bld):
    """
    Test correctness and completeness with three chained basic blocks.

    The pecularity of this testcase is that basic blocks are not created in the
    "execution order". This was known to trigger invalid instructions
    scheduling in the merged basic block.
    """
    bb_end = bld.create_basic_block()
    bb_next = bld.create_basic_block()

    a_val = bld.build_rload(ctx.reg_a)
    bld.build_jump(bb_next)

    bld.position_at_end(bb_next)
    b_val = bld.build_add(a_val, a_val.type.create(1))
    bld.build_jump(bb_end)

    bld.position_at_end(bb_end)
    bld.build_rstore(ctx.reg_b, b_val)
    bld.build_ret()

    run_before_and_after_optimization(
        func, MergeBasicBlockSequences,
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)},
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 1),
         ctx.reg_b: LiveValue(ctx.reg_a.type, 2)},
    )
    assert len(func) == 1
Esempio n. 2
0
def test_load_and_store(ctx, func, bld):
    """Test for chained register load and store."""
    value_before = bld.build_rload(ctx.reg_a)
    value_after = bld.build_add(value_before, ctx.reg_a.type.create(1))
    bld.build_rstore(ctx.reg_a, value_after)
    bld.build_ret()

    run_before_and_after_optimization(
        func, RegistersToSSA, {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)},
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 2)})
Esempio n. 3
0
def test_basic(ctx, func, bld):
    """Test that ALLOCA + STORE + LOAD in a raw works properly."""
    var_addr = bld.build_alloca(ctx.reg_a.type)
    bld.build_store(var_addr, ctx.reg_a.type.create(0))
    bld.build_rstore(ctx.reg_b, bld.build_load(var_addr))
    bld.build_ret()

    regs = {ctx.reg_a: LiveValue(ctx.reg_a.type, 0)}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 0),
        ctx.reg_b: LiveValue(ctx.reg_a.type, 0),
    }
Esempio n. 4
0
def test_inline_loads(ctx, func, bld):
    """Test that the ToExpr pass does not move LOAD/RLOAD operations."""
    a_val = bld.build_rload(ctx.reg_a)
    bld.build_rstore(ctx.reg_a, a_val.type.create(0))
    bld.build_rstore(ctx.reg_b, a_val)

    # The optimization should not move the RLOAD instruction, even though it is
    # used only once: while reaching its use, the corresponding register value
    # has changed.
    run_before_and_after_optimization(
        func, ToExpr, {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)}, {
            ctx.reg_a: LiveValue(ctx.reg_a.type, 0),
            ctx.reg_b: LiveValue(ctx.reg_a.type, 1)
        })
Esempio n. 5
0
def test_store_undef(ctx, func, bld):
    undef_value = bld.build_rload(ctx.reg_a)
    bld.build_rstore(ctx.reg_b, undef_value)
    bld.build_ret()

    regs = {}
    interpreter.run(func, regs)
    print(regs)
    assert regs == {ctx.reg_b: LiveValue(ctx.reg_a.type)}
Esempio n. 6
0
def test_load_undef(ctx, func, bld):
    zero = ctx.reg_a.type.create(0)
    bld.build_rload(ctx.reg_a)
    bld.build_rstore(ctx.reg_a, zero)
    bld.build_ret()

    regs = {}
    interpreter.run(func, regs)
    assert regs == {ctx.reg_a: LiveValue.from_value(zero)}
def test_sequence_2(ctx, func, bld):
    """Test correctness and completeness with two chained basic blocks."""
    bb_next = bld.create_basic_block()

    a_val = bld.build_rload(ctx.reg_a)
    bld.build_jump(bb_next)

    bld.position_at_end(bb_next)
    bld.build_rstore(ctx.reg_b, bld.build_add(a_val, a_val.type.create(1)))
    bld.build_ret()

    run_before_and_after_optimization(
        func, MergeBasicBlockSequences,
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)},
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 1),
         ctx.reg_b: LiveValue(ctx.reg_a.type, 2)},
    )
    assert len(func) == 1
def test_nop(ctx, func, bld):
    """Test correctness with a single basic block."""
    material.build_simple_rstore(ctx, func, 1)

    run_before_and_after_optimization(
        func, MergeBasicBlockSequences,
        {},
        {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)}
    )
    assert len(func) == 1
Esempio n. 9
0
def test_asymetric_phi(ctx, func):
    zero = LiveValue(ctx.reg_a.type, 0)
    one = LiveValue(ctx.reg_a.type, 1)
    two = LiveValue(ctx.reg_a.type, 2)

    regs = {ctx.reg_a: zero, ctx.reg_b: one}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: zero,
        ctx.reg_b: one,
        ctx.reg_c: one,
    }

    regs = {ctx.reg_a: two, ctx.reg_b: one}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: two,
        ctx.reg_b: one,
        ctx.reg_c: two,
    }
Esempio n. 10
0
def test_simple_loop(ctx, func):
    regs = {ctx.reg_a: LiveValue(ctx.reg_a.type, 0)}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 0),
        ctx.reg_b: LiveValue(ctx.reg_b.type, 1),
    }

    regs = {ctx.reg_a: LiveValue(ctx.reg_a.type, 1)}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 1),
        ctx.reg_b: LiveValue(ctx.reg_b.type, 2),
    }

    regs = {ctx.reg_a: LiveValue(ctx.reg_a.type, 2)}
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 2),
        ctx.reg_b: LiveValue(ctx.reg_b.type, 4),
    }
Esempio n. 11
0
def test_same_alloca_twice(ctx, func, bld):
    """
    Test that one ALLOCA executed multiple times yields different pointers.
    """
    bb_loop_start = bld.create_basic_block()
    bb_loop_store_1 = bld.create_basic_block()
    bb_loop_store_2 = bld.create_basic_block()
    bb_loop_end = bld.create_basic_block()
    bb_end = bld.create_basic_block()
    i_reg = ctx.reg_a
    reg_1 = ctx.reg_b
    reg_2 = ctx.reg_c

    bld.build_rstore(i_reg, i_reg.type.create(2))
    bld.build_jump(bb_loop_start)

    bld.position_at_end(bb_loop_start)
    var_addr = bld.build_alloca(ctx.double_type)
    var_int = bld.build_bitcast(reg_1.type, var_addr)
    bld.build_rstore(
        i_reg, bld.build_sub(bld.build_rload(i_reg), i_reg.type.create(1)))
    bld.build_branch(
        bld.build_eq(bld.build_rload(i_reg), i_reg.type.create(0)),
        bb_loop_store_1, bb_loop_store_2)

    bld.position_at_end(bb_loop_store_1)
    bld.build_rstore(reg_1, var_int)
    bld.build_jump(bb_loop_end)

    bld.position_at_end(bb_loop_store_2)
    bld.build_rstore(reg_2, var_int)
    bld.build_jump(bb_loop_end)

    bld.position_at_end(bb_loop_end)
    bld.build_branch(
        bld.build_ugt(bld.build_rload(i_reg), i_reg.type.create(0)),
        bb_loop_start, bb_end)

    bld.position_at_end(bb_end)
    bld.build_ret()

    regs = {}
    interpreter.run(func, regs)
    assert set(regs) == {ctx.reg_a, ctx.reg_b, ctx.reg_c}
    assert regs[ctx.reg_a] == LiveValue(ctx.reg_a.type, 0)
    assert regs[ctx.reg_b] != regs[ctx.reg_c]
Esempio n. 12
0
def test_simple_phi(ctx, func):
    base_regs = {
        ctx.reg_b: LiveValue(ctx.reg_b.type, 1),
        ctx.reg_c: LiveValue(ctx.reg_c.type, 2),
    }
    regs = dict(base_regs)
    regs[ctx.reg_a] = LiveValue(ctx.reg_b.type, 1)
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 1),
        ctx.reg_b: base_regs[ctx.reg_b],
        ctx.reg_c: base_regs[ctx.reg_c],
        ctx.reg_d: base_regs[ctx.reg_b],
    }

    regs = dict(base_regs)
    regs[ctx.reg_a] = LiveValue(ctx.reg_b.type, 0)
    interpreter.run(func, regs)
    assert regs == {
        ctx.reg_a: LiveValue(ctx.reg_a.type, 0),
        ctx.reg_b: base_regs[ctx.reg_b],
        ctx.reg_c: base_regs[ctx.reg_c],
        ctx.reg_d: base_regs[ctx.reg_c],
    }
Esempio n. 13
0
def test_simple_rstore(ctx, func, i):
    regs = {}
    interpreter.run(func, regs)
    assert regs == {ctx.reg_a: LiveValue(ctx.reg_a.type, i)}