Skip to content

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

Closed as not planned
@GoldsteinE

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

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