Skip to content

is_ascii() codegen regression #209216

Description

@nikic
define i1 @is_ascii(ptr %ptr, i64 %len) {
start:
  br label %loop

loop:
  %remaining = phi i64 [ %len, %start ], [ %remaining.next, %loop.latch ]
  %exit.cond = icmp eq i64 %remaining, 0
  br i1 %exit.cond, label %exit, label %loop.latch

loop.latch:
  %remaining.next = add nsw i64 %remaining, -1
  %gep = getelementptr inbounds nuw i8, ptr %ptr, i64 %remaining.next
  %load = load i8, ptr %gep
  %exit.cond.2 = icmp sgt i8 %load, -1
  br i1 %exit.cond.2, label %loop, label %exit

exit:
  ret i1 %exit.cond
}

After #187483 this gets rotated. The result of -O2 is now (https://llvm.godbolt.org/z/8bGvTrjE5):

define noundef i1 @is_ascii(ptr nofree readonly captures(none) %ptr, i64 %len) local_unnamed_addr #0 {
start:
  %exit.cond1 = icmp eq i64 %len, 0
  br i1 %exit.cond1, label %exit, label %loop.latch

loop.latch:
  %remaining2 = phi i64 [ %remaining.next, %loop.latch ], [ %len, %start ]
  %remaining.next = add nsw i64 %remaining2, -1
  %gep = getelementptr inbounds nuw i8, ptr %ptr, i64 %remaining.next
  %load = load i8, ptr %gep, align 1
  %exit.cond.2 = icmp sgt i8 %load, -1
  %exit.cond.2.not = xor i1 %exit.cond.2, true
  %exit.cond = icmp eq i64 %remaining.next, 0
  %or.cond = or i1 %exit.cond.2.not, %exit.cond
  br i1 %or.cond, label %exit, label %loop.latch

exit:
  %exit.cond.lcssa = phi i1 [ true, %start ], [ %exit.cond.2, %loop.latch ]
  ret i1 %exit.cond.lcssa
}

This produces worse codegen (https://llvm.godbolt.org/z/YoWj54h4M). Old:

is_ascii:                               # @is_ascii
.LBB0_1:                                # %loop
        movq    %rsi, %rax
        subq    $1, %rsi
        jb      .LBB0_3
        cmpb    $0, -1(%rdi,%rax)
        jns     .LBB0_1
.LBB0_3:                                # %exit
        testq   %rax, %rax
        sete    %al
        retq

New:

is_ascii:                               # @is_ascii
        test    rsi, rsi
        je      .LBB0_1
        dec     rsi
.LBB0_3:                                # %loop.latch
        mov     rax, rsi
        sub     rsi, 1
        setb    cl
        cmp     byte ptr [rdi + rax], 0
        setns   al
        js      .LBB0_5
        test    cl, cl
        je      .LBB0_3
.LBB0_5:                                # %exit
        ret
.LBB0_1:
        mov     al, 1
        ret

The additional check before the loop is an expected outcome of rotation, but the changes to the loop body are not great.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status
    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions