This is an archive of the discontinued LLVM Phabricator instance.

[InstSimplify] Allow isUndefValue(V) to return true if V is poison
AbandonedPublic

Authored by aqjune on Dec 1 2020, 9:49 AM.

Details

Summary

In the past, isUndefValue()/getWithoutUndef() was added to SimplifyQuery to avoid relying on an assumption that undef was folded into some constant in some cases.

For example, ExpandBinOp uses getWithoutUndef() because this can happen:

(1) Given undef & (1 ^ 1), ExpandBinOp first transforms it into (undef & 1) ^ (undef & 1) by distributivity.

(2) A first simplify call answers that the first (undef & 1) is 0 whereas another simplify call answers the second (undef & 1) is undef (this can happen when undefs are hidden under variables)

(3) Since 0 ^ undef = undef, ExpandBinOp returns undef.

However, this is incorrect because undef & (1 ^ 1) is 0 whereas the result is undef.
To avoid this, ExpandBinOp is calling subsequent queries with getWithoutUndef() applied to avoid folding undefs.

With poison, this transformation is now okay: poison & (1 ^ 1) is simply poison.

This patch

(1) renames isUndefValue() to isUndefOrPoison(), and

(2) let isUndefOrPoison() return true if the value is poison.

Considering the miscompilation due to the old ExpandBinOp in the past (https://reviews.llvm.org/D83360#2145746): if poison is used instead, it now becomes correct.

define i1 @src(i32 %x, i32 %y) {
%0:
  %cmp9.not.1 = icmp eq i32 %x, %y
  %cmp15 = icmp slt i32 %x, %y
  %spec.select39 = select i1 %cmp9.not.1, i1 poison, i1 %cmp15
  %spec.select40 = xor i1 %cmp9.not.1, 1
  %spec.select = and i1 %spec.select39, %spec.select40
  ret i1 %spec.select
}
=>
define i1 @tgt(i32 %x, i32 %y) {
%0:
  %cmp9.not.1 = icmp eq i32 %x, %y
  %cmp15 = icmp slt i32 %x, %y
  %spec.select39 = select i1 %cmp9.not.1, i1 poison, i1 %cmp15
  ret i1 %spec.select39
}
Transformation seems to be correct!

Diff Detail

Event Timeline

aqjune created this revision.Dec 1 2020, 9:49 AM
Herald added a project: Restricted Project. · View Herald TranscriptDec 1 2020, 9:49 AM
aqjune requested review of this revision.Dec 1 2020, 9:49 AM
nikic added a comment.Dec 1 2020, 11:24 AM

I don't think this change makes a lot of sense. I expect that in nearly all cases we'll be able to produce a better result by having a separate PoisonValue check beforehand (we'll want to return poison rather than undef or some other value). And if we do that, this change to the isUndefValue() API just makes things more confusing.

reames added a comment.Dec 1 2020, 1:33 PM

I agree that this change makes the API (more) confusing.

aqjune added a comment.Dec 1 2020, 3:23 PM

Well, okay. I'll make another patch for that.

aqjune abandoned this revision.Dec 1 2020, 3:23 PM
aqjune added a comment.Dec 3 2020, 7:52 AM

I'll make the next patch after http://llvm.org/pr48353 is resolved .