Skip to content

[InstCombine] Wrong value truncation due to incorrect analysis of iv known bits #95547

Closed
@aleks-tmb

Description

@aleks-tmb
define void @src(i32 %0, ptr %p, i1 %cnd) {
entry:
  br i1 %cnd, label %header, label %exit

header:                                           ; preds = %latch, %entry
  %iv = phi i32 [ %iv.next, %latch ], [ 256, %entry ]
  %iv.trunc = trunc i32 %iv to i16
  %div = udiv i16 11, %iv.trunc
  br i1 %cnd, label %loop1, label %loop0

loop0:                                            ; preds = %header
  %load = load i32, ptr %p, align 4
  br label %loop1

loop1:                                            ; preds = %loop0, %header
  %v = phi i32 [ %load, %loop0 ], [ 0, %header ]
  store i32 %v, ptr %p, align 4
  %guard = icmp ugt i32 %iv, 10
  br i1 %guard, label %latch, label %loop2

loop2:                                            ; preds = %loop1
  %div.trunc = trunc i16 %div to i8
  store i8 %div.trunc, ptr %p, align 1
  br label %latch

latch:                                            ; preds = %loop2, %loop1
  %iv.next = add nuw nsw i32 %iv, 1
  %exitcond = icmp ugt i32 %iv, 300
  br i1 %exitcond, label %exit, label %header

exit:                                             ; preds = %latch
  ret void
}

If we run instcombine pass on this example, it will convert trunc i32 %iv to i16 into trunc i32 %iv to i8 to avoid cast:
https://godbolt.org/z/ze4E45ThT

But this transformation is wrong, because on the first iteration %iv is equal to 256, and the 8 bits trunc makes it equal to 0. This give us a division by zero on the next instruction: %div = udiv i16 11, %iv.trunc.

It seems that the problematic patch is #73662

@nikic Could you please take a look?

Metadata

Metadata

Assignees

Labels

llvm:instcombineCovers the InstCombine, InstSimplify and AggressiveInstCombine passesmiscompilation

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions