Skip to content

instcombine generating incorrect range metadata for a ctpop #59888

@regehr

Description

@regehr

instcombine takes this code:

define i32 @f(i32 %0) {
  %2 = lshr i32 2048, %0
  %3 = call i32 @llvm.ctpop.i32(i32 %2)
  %4 = freeze i32 %3
  ret i32 %4
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

and turns it into:

define i32 @f(i32 %0) {
  %2 = lshr i32 2048, %0
  %.fr = freeze i32 %2
  %3 = call i32 @llvm.ctpop.i32(i32 %.fr), !range !0
  ret i32 %3
}

; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare i32 @llvm.ctpop.i32(i32) #0

attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }

!0 = !{i32 0, i32 13}

but the inferred 0..13 range is too tight. to see this, consider that (in the original code) %2 can easily be poison, this happens when %0 is uge 32. then, ctpop(poison) gives poison, and freezing it results in an arbitrary 32-bit value.

cc @nunoplopes

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions