Skip to content

[M68k] cmp / br pair doesn't prevent reordering in scheduling #106206

Closed
@TechnoElf

Description

@TechnoElf

I have run into an issue while attempting to get some rust code compiled for the m68k target. While the code does compile, it has a completely different behaviour to that described by the source. The relevant section looks something like this:

let mut prev_state = get_input();
loop {
    let state = get_input();
    if state != prev_state {
        do_something();
    }
    prev_state = state;
}

I am pretty sure the issue lies with the backend as the generated IR looks correct. The test case can be reduced to the following IR:

define internal zeroext i1 @get1() unnamed_addr #1 {
start:
  ret i1 0
}

define internal void @main() unnamed_addr #1 {
start:
  %prev_state = alloca [1 x i8], align 1
  br label %bb5

bb5:
  %state = call zeroext i1 @get1() #11
  %8 = load i8, ptr %prev_state, align 1
  %_11 = trunc i8 %8 to i1
  %_10 = icmp ne i1 %state, %_11
  br i1 %_10, label %bb7, label %bb10

bb10:
  %9 = zext i1 %state to i8
  store i8 %9, ptr %prev_state, align 1
  br label %bb5

bb7:
  br label %bb10
}

This is compiled to the following machine code using llc -O0 -march=m68k with llvm compiled from the main branch:

        .text
        .file   "b"
        .p2align        1                               ; -- Begin function get1
        .type   get1,@function
get1:                                   ; @get1
        .cfi_startproc
; %bb.0:                                ; %start
        moveq   #0, %d0
        rts
.Lfunc_end0:
        .size   get1, .Lfunc_end0-get1
        .cfi_endproc
                                        ; -- End function
        .p2align        1                               ; -- Begin function main
        .type   main,@function
main:                                   ; @main
        .cfi_startproc
; %bb.0:                                ; %start
        suba.l  #12, %sp
        .cfi_def_cfa_offset -16
        movem.l %d2, (8,%sp)                    ; 8-byte Folded Spill
        bra     .LBB1_1
.LBB1_1:                                ; %bb5
                                        ; =>This Inner Loop Header: Depth=1
        jsr     get1
        move.b  (7,%sp), %d2
        and.b   #1, %d2
        move.b  %d0, %d1
        sub.b   %d2, %d1
        move.b  %d0, (6,%sp)                    ; 1-byte Folded Spill
        bne     .LBB1_3
        bra     .LBB1_2
.LBB1_2:                                ; %bb10
                                        ;   in Loop: Header=BB1_1 Depth=1
        move.b  (6,%sp), %d0                    ; 1-byte Folded Reload
        move.b  %d0, (7,%sp)
        bra     .LBB1_1
.LBB1_3:                                ; %bb7
                                        ;   in Loop: Header=BB1_1 Depth=1
        bra     .LBB1_2
.Lfunc_end1:
        .size   main, .Lfunc_end1-main
        .cfi_endproc
                                        ; -- End function
        .section        ".note.GNU-stack","",@progbits

The move.b %d0, (6,%sp) overwrites the value in the CC register written by the prior subtraction, preventing the subsequent branch from working correctly. Reversing the order of these two instructions makes the code function as expected.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions