Skip to content

Const loop not folded #117509

@ZuseZ4

Description

@ZuseZ4

Originally encountered on the Julia Slack, then discussed a bit on the Rust Discord.
The following loop has no side effects and should be simple enough to fold, yet both clang and rustc end up with a phi node.
https://godbolt.org/z/16rG5bjz9

unsigned long foo() {
    unsigned long max = 1000000000;
    unsigned long total = 0;
    
    for (unsigned long i = 0; i < max; i++) {
        total = i;
    }
    return total;
}

under -O3 and -S -emit-llvm gives

define dso_local noundef i64 @foo()() local_unnamed_addr #0 !dbg !10 {
entry:
    #dbg_value(i64 1000000000, !16, !DIExpression(), !20)
    #dbg_value(i64 0, !17, !DIExpression(), !20)
    #dbg_value(i64 0, !18, !DIExpression(), !21)
  br label %vector.body, !dbg !22

vector.body:
  %index = phi i64 [ 0, %entry ], [ %index.next.9, %vector.body ], !dbg !23
  %0 = phi i64 [ 15, %entry ], [ %1, %vector.body ], !dbg !23
  %index.next.9 = add nuw nsw i64 %index, 320, !dbg !23
  %1 = add nuw nsw i64 %0, 320, !dbg !23
  %2 = icmp eq i64 %index.next.9, 1000000000, !dbg !23
  br i1 %2, label %for.cond, label %vector.body, !dbg !23

for.cond:
  %vector.recur.extract = add nuw i64 %0, 304
    #dbg_value(i64 1000000000, !18, !DIExpression(), !21)
    #dbg_value(i64 1000000000, !17, !DIExpression(), !20)
    #dbg_value(i64 1000000001, !18, !DIExpression(), !21)
  ret i64 %vector.recur.extract, !dbg !30
}

attributes #0 = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }

The resulting asm is:

foo():
        mov     rax, -1
.LBB0_1:
        add     rax, 320
        cmp     rax, 999999999
        jne     .LBB0_1
        ret

compared to GCC, which just has a

foo():
        mov     eax, 999999999
        ret

Here the pass that looks suspicious (thanks to @scottmcm) https://rust.godbolt.org/z/dG9far1dW
Tbh. it looks like a fun issue, so if someone gives me a hint on where to fix it, I could start trying to come up with a fix next week.

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