This is an archive of the discontinued LLVM Phabricator instance.

Fix a phase-ordering problem in SimplifyCFG.
ClosedPublic

Authored by resistor on Jan 1 2023, 5:20 PM.

Details

Summary

Switch simplification could sometimes fail to notice when an
intermediate case removal caused the switch condition to become
constant. This would cause the switch to be simplified into a
conditional branch rather than a direct branch.

Most of the time this didn't matter, except that occasionally
downstream parts of SimplifyCFG expect tautological branches to
already have been eliminated. The missed handling in switch
simplification would cause an assertion failure in the downstream
code.

Triggering the assertion failure is fairly sensitive to the exact
order of various simplifications.

Fixes https://github.com/llvm/llvm-project/issues/59768

Diff Detail

Event Timeline

resistor created this revision.Jan 1 2023, 5:20 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 1 2023, 5:20 PM
Herald added a subscriber: hiraditya. · View Herald Transcript
resistor requested review of this revision.Jan 1 2023, 5:20 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 1 2023, 5:20 PM
nikic added a reviewer: nikic.Jan 2 2023, 6:02 AM
nikic added a subscriber: nikic.
nikic added inline comments.
llvm/test/Transforms/SimplifyCFG/switch-simplify-crash2.ll
3

Outside PhaseOrdering, tests should not use the full optimization pipeline. Here is a reduction of your test case:

; RUN: opt -S -passes="simplifycfg<forward-switch-cond;no-keep-loops>" < %s | FileCheck %s

define i8 @test() {
entry:
  br label %loop

loop:
  %phi1 = phi i8 [ 0, %entry ], [ %phi2, %loop2 ]
  br label %loop2

loop2:
  %phi2 = phi i8 [ %phi1, %loop ], [ 0, %loop2 ]
  switch i8 %phi2, label %loop [
    i8 0, label %loop2
    i8 1, label %exit
  ]

exit:
  ret i8 0
}

Please also reference the issue.

resistor updated this revision to Diff 485914.Jan 2 2023, 9:00 PM

Reduce test case.

nikic added inline comments.Jan 3 2023, 2:07 AM
llvm/lib/Transforms/Utils/Local.cpp
241

I think this may cause problems if we have the following case: We have a case 1 => foo, case 2 => default, then removing default folds CI to 1, but at this point we have already visited case 1, so TheOnlyDest will remain nullptr, and we'll set it to the default destination below, which would be the wrong one in that case.

resistor updated this revision to Diff 486097.Jan 3 2023, 2:42 PM

Restart case iteration when we fold the switch condition.

resistor marked an inline comment as done.Jan 3 2023, 2:51 PM
nikic accepted this revision.Jan 4 2023, 1:48 AM

LG

llvm/lib/Transforms/Utils/Local.cpp
243–244
This revision is now accepted and ready to land.Jan 4 2023, 1:48 AM
resistor updated this revision to Diff 486415.Jan 4 2023, 3:46 PM

Incorporate suggestion

This revision was landed with ongoing or failed builds.Jan 4 2023, 3:47 PM
This revision was automatically updated to reflect the committed changes.