llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.43k stars 12.16k forks source link

Wrong constant fold for ICmp by InstCombine #98441

Open bongjunj opened 4 months ago

bongjunj commented 4 months ago

https://github.com/llvm/llvm-project/blob/ce92b2f594809c39c37bf3ef3d881f2b33bd6730/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L7345-L7346

https://github.com/llvm/llvm-project/blob/ce92b2f594809c39c37bf3ef3d881f2b33bd6730/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L1310-L1325

NewPhi->addIncoming(V, Pred); in the loop for (auto [V, Pred] : zip(Ops, Phi->blocks())) is executed.

Alive2 report: https://alive2.llvm.org/ce/z/5IfYQ9

----------------------------------------
define <2 x i1> @fun0(i1 %val0) {
entry:
  br i1 %val0, label %if.true, label %if.false

if.false:
  br label %merge

if.true:
  br label %merge

merge:
  %val1 = phi <2 x i32> [ { 4294967295, poison }, %if.true ], [ { poison, 0 }, %if.false ]
  br label %exit

exit:
  %val2 = icmp eq <2 x i32> %val1, { undef, 4294967295 }
  ret <2 x i1> %val2
}
=>
define <2 x i1> @fun0(i1 %val0) {
entry:
  br i1 %val0, label %if.true, label %if.false

if.false:
  br label %merge

if.true:
  br label %merge

merge:
  br label %exit

exit:
  ret <2 x i1> { poison, 0 }
}
Transformation doesn't verify!

ERROR: Target is more poisonous than source

Example:
i1 %val0 = #x1 (1)

Source:
  >> Jump to %if.true
  >> Jump to %merge
<2 x i32> %val1 = < #xffffffff (4294967295, -1), poison >
  >> Jump to %exit
<2 x i1> %val2 = < #x0 (0)  [based on undef value], poison >

Target:
  >> Jump to %if.true
  >> Jump to %merge
  >> Jump to %exit
Source value: < #x0 (0), poison >
Target value: < poison, #x0 (0) >

Summary:
  0 correct transformations
  1 incorrect transformations
  0 failed-to-prove transformations
  0 Alive2 errors
mskamp commented 1 month ago

The root cause seems to be a missing handling of partially undef vectors when simplifying PHI nodes. This results in combining <i1 undef, i1 poison> and <i1 poison, i1 false> to <i1 poison, i1 false>. A corresponding select instruction is, however, combined to <i1 undef, i1 false>, which Alive considers correct: https://alive2.llvm.org/ce/z/k2CEUV