Skip to content

[InstCombine] Missing poison check when reusing existing value in def-use chain #161493

@dtcxzyw

Description

@dtcxzyw

Reproducer: https://alive2.llvm.org/ce/z/H_tcBV

define i16 @src(i4 %x, i12 %y) {
  %x.fr = freeze i4 %x
  %zext.x = zext i4 %x.fr to i16
  %slx = shl nuw nsw i16 %zext.x, 12
  %zext.y = zext i12 %y to i16
  %xy = or disjoint i16 %slx, %zext.y
  call void @use(i16 %xy)
  %sly = shl nuw i16 %zext.y, 4
  %yx = or disjoint i16 %sly, %zext.x
  ret i16 %yx
}

define i16 @tgt(i4 %x, i12 %y) {
  %x.fr = freeze i4 %x
  %zext.x = zext i4 %x.fr to i16
  %slx = shl nuw nsw i16 %zext.x, 12
  %zext.y = zext i12 %y to i16
  %xy = or disjoint i16 %slx, %zext.y
  call void @use(i16 %xy)
  ;%sly = shl nuw i16 %zext.y, 4
  ;%yx = or disjoint i16 %sly, %zext.x
  %yx = call i16 @llvm.fshl.i16(i16 %xy, i16 %xy, i16 4)
  ret i16 %yx
}

declare void @use(i16)
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i4 %x = #x8 (8, -8)
i12 %y = #x000 (0)

Source:
i4 %x.fr = #x8 (8, -8)
i16 %zext.x = #x0008 (8)
i16 %slx = poison
i16 %zext.y = #x0000 (0)
i16 %xy = poison
Function @use returned
i16 %sly = #x0000 (0)
i16 %yx = #x0008 (8)

SOURCE MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >	size: 0	align: 1	alloc type: 0	alive: false	address: #x0
Block 1 >	size: 0	align: 1	alloc type: 0	alive: true	address: #x1

Target:
i4 %x.fr = #x8 (8, -8)
i16 %zext.x = #x0008 (8)
i16 %slx = poison
i16 %zext.y = #x0000 (0)
i16 %xy = poison
Function @use returned
i16 %yx = poison

TARGET MEMORY STATE
===================
NON-LOCAL BLOCKS:
Block 0 >	size: 0	align: 1	alloc type: 0	alive: false	address: #x0
Block 1 >	size: 0	align: 1	alloc type: 0	alive: true	address: #x1
Source value: #x0008 (8)
Target value: poison

It is caused by #68502.

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions