This is an archive of the discontinued LLVM Phabricator instance.

[InstCombine] Switch foldOpIntoPhi() to use InstSimplify
ClosedPublic

Authored by nikic on Sep 30 2022, 5:46 AM.

Details

Summary

foldOpIntoPhi() currently only folds operations into the phi if all but one operands constant-fold. The two exceptions to this are freeze and select, where we allow more general simplification.

This patch makes foldOpIntoPhi() generally simplification based and removes all the instruction-specific logic. We just try to simplify the instruction for each operand, and for the (potentially) one non-simplified operand, we move it into the new block with adjusted operands.

This fixes https://github.com/llvm/llvm-project/issues/57448, which was my original motivation for the change.

There is some barely measurable compile-time impact (http://llvm-compile-time-tracker.com/compare.php?from=5c5ac3490cb96bd187234226d26933ec0d92ed17&to=08ad1abbcaecf0986357498397d657506de38d13&stat=instructions), but it is in the 0.05% range, so I think this is fine.

Diff Detail

Event Timeline

nikic created this revision.Sep 30 2022, 5:46 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 30 2022, 5:46 AM
Herald added a subscriber: hiraditya. · View Herald Transcript
nikic requested review of this revision.Sep 30 2022, 5:46 AM
Herald added a project: Restricted Project. · View Herald TranscriptSep 30 2022, 5:46 AM
nikic edited the summary of this revision. (Show Details)Sep 30 2022, 5:56 AM
spatel accepted this revision.Sep 30 2022, 10:37 AM

LGTM.

I haven't followed the nuances of inttoptr/ptrtoint folding, but I assume those diffs are valid. See inline for one question.

llvm/test/Transforms/InstCombine/recurrence.ll
7

This is an improvement, but it's not clear to me from the diffs or debug spew why it happened. Did you step through to look at that?

This revision is now accepted and ready to land.Sep 30 2022, 10:37 AM

I haven't followed the nuances of inttoptr/ptrtoint folding, but I assume those diffs are valid.

It's technically not correct, but we currently still consider inttoptr(ptrtoint) as no-op casts. There is a disable-i2p-p2i-opt flag to centrally disable this behavior.

llvm/test/Transforms/InstCombine/recurrence.ll
7

This fold gets performed by foldOpIntoPhi() now, while it was previously done by https://github.com/llvm/llvm-project/blob/586784a2e4acc70a5aedfab64723f992f83deaaa/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp#L3221-L3225. (That fold isn't redundant though, because we will only call foldOpIntoPhi() with a constant operand, at least currently.)

TimNN added a subscriber: TimNN.Oct 4 2022, 2:17 AM
nikic added a comment.Oct 5 2022, 4:08 AM

Reduced the infinite loop on buildbots to this test case:

define i64 @test(i1 %c, ptr %arg.ptr, ptr %arg.ptr2) {
entry:
  br i1 %c, label %if, label %else

if:
  %arg.ptr2.val = load i64, ptr %arg.ptr2, align 8
  br label %join

else:
  %arg.int.ptr = ptrtoint ptr %arg.ptr to i64
  br label %join

join:
  %int.ptr = phi i64 [ %arg.ptr2.val, %if ], [ %arg.int.ptr, %else ]
  %ptr = inttoptr i64 %int.ptr to ptr
  %v = load i64, ptr %ptr, align 8
  ret i64 %v
}

The conflicting transform appears to be this: https://github.com/llvm/llvm-project/blob/78305720f387ba5c86810a02155bd6c58d22c97c/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp#L105

This revision was landed with ongoing or failed builds.Oct 5 2022, 5:00 AM
This revision was automatically updated to reflect the committed changes.

I found that most recent version e94619b955104841cc2a4a6febe4025ee140194e miscompiles (?): https://godbolt.org/z/fffnjGa4q .
Will likely revert soon cc @asbirlea

nikic added a comment.Oct 6 2022, 11:43 AM

Reviewing the code here again, a problem could be use of an incorrect context instruction for simplification (should use predecessor terminator, not original instruction). I'll look into it tomorrow, but feel free to revert in the meantime.

nikic added a comment.Oct 7 2022, 1:57 AM

Reduced test case:

define void @test(ptr %ptr.base, i64 %n) {
entry:
  %ptr.end = getelementptr inbounds i8, ptr %ptr.base, i64 %n
  br label %loop

loop:
  %ptr = phi ptr [ %ptr.next, %latch ], [ %ptr.base, %entry ]
  %phi = phi i1 [ %cmp, %latch ], [ true, %entry ]
  %v = load i8, ptr %ptr, align 1
  %cmp = icmp eq i8 %v, 95
  br i1 %cmp, label %latch, label %if

if:
  %sel = select i1 %phi, i8 117, i8 100
  call void @use(i8 %sel)
  br label %latch

latch:
  %ptr.next = getelementptr inbounds i8, ptr %ptr, i64 1
  %cmp.i.not = icmp eq ptr %ptr.next, %ptr.end
  br i1 %cmp.i.not, label %exit, label %loop

exit:
  ret void
}

declare void @use(i8)

This is indeed a problem with the context instruction.

fhahn added a subscriber: fhahn.Oct 17 2022, 4:51 AM

It looks like the mis-compile in https://github.com/llvm/llvm-project/issues/58401 is caused by the change. I'll revert the commit for now.