Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Illegal IR decl deduplication #15

Open
48cf opened this issue Aug 31, 2023 · 1 comment
Open

Illegal IR decl deduplication #15

48cf opened this issue Aug 31, 2023 · 1 comment
Labels
bug Something isn't working workaround exists

Comments

@48cf
Copy link
Collaborator

48cf commented Aug 31, 2023

The following code causes the optimizer to perform an illegal deduplication:

fn inc(foo: *u32) void {
    foo.* += 1;
}

fn main() noreturn {
    var foo: u32 = 0;

    loop {
        if (foo < 10) {
            inc(foo.&);
        }

        inc(foo.&);
    }
}

Block 1 is the function's entry block, block 5 is the loop's first body block, which does the if comparison and jumps to block 5, which is the if's taken branch, or block 7, which is the continuation of block 3. In block 5 the decl $13 is the addr_of instruction that is used in both calls to the function inc. You can see that the later call does not take the address of the local variable taken again, instead, it uses a decl $13 which it shouldn't have access to. That generates bad code which won't actually load the right value into the register rdi

Block#1:
  $1 = enter_function(16)
  $5 = stack(4)
  $6 = store($5, #0)
  $7 = goto(Block#3)

Block#3:
  $10 = u64 less($5, #10)
  $11 = if($10, Block#5, Block#7)

Block#5:
  $13 (rbx) = u64 addr_of($5)
  $18 (rdi) = u64 copy($13)
  $15 (rax) = u64 call(inc, $18)
  $19 (rax) = u64 copy($15)
  $16 = goto(Block#7)

Block#7:
  $37 (rdi) = u64 copy($13)
  $21 (rax) = u64 call(inc, $37)
  $36 (rax) = u64 copy($21)
  $22 = goto(Block#3)
.text:0000000000100008 main            proc near
.text:0000000000100008
.text:0000000000100008 var_4           = dword ptr -4
.text:0000000000100008
.text:0000000000100008                 push    rbx
.text:0000000000100009                 push    rbp
.text:000000000010000A                 mov     rbp, rsp
.text:000000000010000D                 sub     rsp, 10h
.text:0000000000100011                 mov     [rbp+var_4], 0
.text:0000000000100018
.text:0000000000100018 loc_100018:                             ; CODE XREF: main+2F↓j
.text:0000000000100018                 cmp     qword ptr [rbp+var_4], 0Ah
.text:000000000010001D                 jnb     loc_10002F
.text:0000000000100023                 lea     rbx, [rbp+var_4]
.text:0000000000100027                 mov     rdi, rbx
.text:000000000010002A                 call    inc
.text:000000000010002F
.text:000000000010002F loc_10002F:                             ; CODE XREF: main+15↑j
.text:000000000010002F                 mov     rdi, rbx        ; The value of rbx is invalid here, if the branch wasn't taken
.text:0000000000100032                 call    inc
.text:0000000000100037                 jmp     short loc_100018
.text:0000000000100037 main            endp
@48cf 48cf added bug Something isn't working workaround exists labels Aug 31, 2023
@48cf
Copy link
Collaborator Author

48cf commented Sep 1, 2023

A workaround for this issue can be seen in this commit: a2db8be

N00byEdge added a commit that referenced this issue Sep 1, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working workaround exists
Projects
None yet
Development

No branches or pull requests

1 participant