Skip to content

SimplifyCFGPass incorrectly hoists load before loop that can have zero iterations #92274

Closed as not planned

Description

@GoldsteinE

C++ reproducer:

int ub(int &foo, int count) {
  delete &foo;
  int x = {};
  for (int i = 0; i < count; i++)
    x += foo;
  return x;
}

This code compiles to

define dso_local noundef i32 @ub(int&, int)(ptr noundef nonnull align 4 dereferenceable(4) %foo, i32 noundef %count) local_unnamed_addr {
entry:
  tail call void @operator delete(void*)(ptr noundef nonnull %foo) #3
  %cmp4 = icmp sgt i32 %count, 0
  %0 = load i32, ptr %foo, align 4
  ; ^ unconditional UB: load from a dead pointer
  %1 = mul i32 %0, %count
  %x.0.lcssa = select i1 %cmp4, i32 %1, i32 0
  ret i32 %x.0.lcssa
}

turning conditional UB (on count != 0) into an unconditional one.

This is flagged as incorrect by alive2: https://alive2.llvm.org/ce/z/c3KXo9

Originaly discovered by @feedab1e

Activity

  1. GoldsteinE commented on May 15, 2024

    @GoldsteinE
    Author

    Looking at godbolt’s “Opt Pipeline”, it looks like this SimplifyCFGPass causes the problem:

     define dso_local noundef i32 @ub(int&, int)(ptr noundef nonnull align 4 dereferenceable(4) %foo, i32 noundef %count) local_unnamed_addr {
     entry:
         #dbg_value(ptr %foo, !17, !DIExpression(), !22)
         #dbg_value(i32 %count, !18, !DIExpression(), !22)
       tail call void @operator delete(void*)(ptr noundef nonnull %foo)
         #dbg_value(i32 0, !19, !DIExpression(), !22)
         #dbg_value(i32 0, !20, !DIExpression(), !24)
       %cmp4 = icmp sgt i32 %count, 0
    -  br i1 %cmp4, label %for.body.lr.ph, label %for.cond.cleanup
    -
    -for.body.lr.ph:                                   ; preds = %entry
       %0 = load i32, ptr %foo, align 4
    -    #dbg_value(i32 poison, !20, !DIExpression(), !24)
    -    #dbg_value(i32 poison, !19, !DIExpression(), !22)
       %1 = mul i32 %0, %count
    -  br label %for.cond.cleanup
    -
    -for.cond.cleanup:                                 ; preds = %for.body.lr.ph, %entry
    -  %x.0.lcssa = phi i32 [ 0, %entry ], [ %1, %for.body.lr.ph ]
    +  %x.0.lcssa = select i1 %cmp4, i32 %1, i32 0
       ret i32 %x.0.lcssa
     }
    
  2. efriedma-quic commented on May 15, 2024

    @efriedma-quic
    Contributor

    Duplicate of #37011 .

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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