This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Don't combine CmpInst that used for verify the legality of the lshr
AbandonedPublic

Authored by TiehuZhang on Oct 14 2021, 7:10 AM.

Details

Summary

When the value of lshr's shift operand is unknown (e.g., the operand is passed through a function parameter), the cmp instruction used to determine the validity of the shift operand cannot be eliminated. Otherwise, undefined behavior may occur.

Diff Detail

Event Timeline

TiehuZhang created this revision.Oct 14 2021, 7:10 AM
TiehuZhang requested review of this revision.Oct 14 2021, 7:10 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 14 2021, 7:10 AM
lebedev.ri requested changes to this revision.Oct 14 2021, 7:13 AM
lebedev.ri added a subscriber: lebedev.ri.

Sorry, but i can not parse the description,

The current transformation is *not* a miscompile:
https://godbolt.org/z/WeTeasK53
https://alive2.llvm.org/ce/z/LVDqSX

This revision now requires changes to proceed.Oct 14 2021, 7:13 AM

@lebedev.ri I think the problem is when %0 is negative, the original code gives a definite result while the transformed IR is UB.

TiehuZhang edited the summary of this revision. (Show Details)Oct 14 2021, 7:09 PM
TiehuZhang added a comment.EditedOct 14 2021, 7:20 PM

Sorry, but i can not parse the description,

The current transformation is *not* a miscompile:
https://godbolt.org/z/WeTeasK53
https://alive2.llvm.org/ce/z/LVDqSX

I'm sorry I didn't make my point clear. The purpose of my current modification is to circumvent a false optimization. In, the case, %0 may be negative. If we eliminate %cmp = icmp slt i32 %0, 0, undefined behavior may occur, as lshr performed a negative shift. @lebedev.ri

original version

%cmp = icmp slt i32 %0, 0
%shr = lshr i32 7, %0
%cmp1 = icmp sgt i32 %0, %shr
%or.cond = or i1 %cmp, %cmp1
br i1 %or.cond, label %cond.end, label %cond.false

miscompile

%shr = lshr i32 7, %0
%1 = icmp ult i32 %shr, %0
br i1 %1, label %cond.end, label %cond.false
craig.topper added a subscriber: craig.topper.EditedOct 14 2021, 7:21 PM

If an input to an or instruction is poison, the output of the or is poison regardless of whether the other operand is true when the poison result occurs.

If an incorrect optimization is occurring it must be where the or is created.

TiehuZhang added a comment.EditedOct 14 2021, 8:10 PM

If an input to an or instruction is poison, the output of the or is poison regardless of whether the other operand is true when the poison result occurs.

If an incorrect optimization is occurring it must be where the or is created.

Thanks for your review! @craig.topper. Do you mean that we should prevent this pattern from being generated, rather than remedying it after the pattern is generated? Actually, the issue I met started from D95959. That optimization does not seem to apply to all scenarios, such as those where the shift operand is negative. In the case I present, this optimization results in a miscalculation of the KnownBit, which in turn results in a false transformation.

If an input to an or instruction is poison, the output of the or is poison regardless of whether the other operand is true when the poison result occurs.

If an incorrect optimization is occurring it must be where the or is created.

Thanks for your review! @craig.topper. Do you mean that we should prevent this pattern from being generated, rather than remedying it after the pattern is generated? Actually, the issue I met started from D95959. That optimization does not seem to apply to all scenarios, such as those where the shift operand is negative. In the case I present, this optimization results in a miscalculation of the KnownBit, which in turn results in a false transformation.

The transform is correct based on the semantics of llvm's or instruction. The or instruction in llvm does not have short circuit evaluation. It can't block the spread of poison. The IR that has the semantics you want is

define i32 @cmp_lshr_cmp(i32 %0) {
entry:
  %cmp = icmp slt i32 %0, 0
  %shr = lshr i32 7, %0
  %cmp1 = icmp sgt i32 %0, %shr
  %or.cond = select i1 %cmp, i1 true, i1 %cmp1
  br i1 %or.cond, label %cond.end, label %cond.false

cond.false:                                       ; preds = %entry
  ret i32 1

cond.end:                                         ; preds = %entry, %cond.false
  ret i32 0
}

Using a select instruction instead of an or prevents the %cmp1 value from being used if %cmp is true. There was previously an incorrect transform that would turn such a select into an or, but it was disabled in https://reviews.llvm.org/D101191

If an input to an or instruction is poison, the output of the or is poison regardless of whether the other operand is true when the poison result occurs.

If an incorrect optimization is occurring it must be where the or is created.

Thanks for your review! @craig.topper. Do you mean that we should prevent this pattern from being generated, rather than remedying it after the pattern is generated? Actually, the issue I met started from D95959. That optimization does not seem to apply to all scenarios, such as those where the shift operand is negative. In the case I present, this optimization results in a miscalculation of the KnownBit, which in turn results in a false transformation.

The transform is correct based on the semantics of llvm's or instruction. The or instruction in llvm does not have short circuit evaluation. It can't block the spread of poison. The IR that has the semantics you want is

define i32 @cmp_lshr_cmp(i32 %0) {
entry:
  %cmp = icmp slt i32 %0, 0
  %shr = lshr i32 7, %0
  %cmp1 = icmp sgt i32 %0, %shr
  %or.cond = select i1 %cmp, i1 true, i1 %cmp1
  br i1 %or.cond, label %cond.end, label %cond.false

cond.false:                                       ; preds = %entry
  ret i32 1

cond.end:                                         ; preds = %entry, %cond.false
  ret i32 0
}

Using a select instruction instead of an or prevents the %cmp1 value from being used if %cmp is true. There was previously an incorrect transform that would turn such a select into an or, but it was disabled in https://reviews.llvm.org/D101191

OK, I get it. I'll try to find out why the or is still generated. Thanks very much @craig.topper

lebedev.ri resigned from this revision.Jan 12 2023, 4:49 PM

This review seems to be stuck/dead, consider abandoning if no longer relevant.

This revision now requires review to proceed.Jan 12 2023, 4:49 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 12 2023, 4:49 PM
Herald added a subscriber: StephenFan. · View Herald Transcript
TiehuZhang abandoned this revision.Jan 12 2023, 5:10 PM