[PATCH] D62560: Fix a crash when the default of a switch is removed

Andy Kaylor via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue May 28 17:17:26 PDT 2019


andrew.w.kaylor created this revision.
andrew.w.kaylor added reviewers: karka, rtereshin.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

This patch fixes a problem that occurs in LowerSwitch when a switch statement has a PHI node as its condition, and the PHI node only has two incoming blocks, and one of those incoming blocks is through an unreachable default in the switch statement. When this condition occurs, LowerSwitch holds a pointer to the condition value, but removes the switch block as a predecessor of the PHI block, causing the PHI node to be replaced. LowerSwitch then tries to use its stale pointer to the original condition value, causing a crash.


Repository:
  rL LLVM

https://reviews.llvm.org/D62560

Files:
  lib/Transforms/Utils/LowerSwitch.cpp
  test/Transforms/LowerSwitch/condition-phi-unreachable-default.ll


Index: test/Transforms/LowerSwitch/condition-phi-unreachable-default.ll
===================================================================
--- /dev/null
+++ test/Transforms/LowerSwitch/condition-phi-unreachable-default.ll
@@ -0,0 +1,29 @@
+; RUN: opt < %s -lowerswitch -disable-output
+
+; This test verify -lowerswitch does not crash when an removing an
+; unreachable default branch causes a PHI node used as the switch
+; condition to be erased.
+
+define void @f() local_unnamed_addr {
+entry:
+  br label %sw.epilog
+
+sw.epilog:                                        ; preds = %sw.epilog.outer, %for.body
+  %i = phi i32 [ undef, %for.body ], [ 0, %entry ]
+  br i1 undef, label %for.body, label %for.end
+
+for.body:                                         ; preds = %sw.epilog
+  switch i32 %i, label %sw.epilog [
+    i32 0, label %sw.epilog.outer.backedge.loopexit
+    i32 1, label %sw.epilog.outer.backedge
+  ]
+
+sw.epilog.outer.backedge.loopexit:                ; preds = %for.body
+  unreachable
+
+sw.epilog.outer.backedge:                         ; preds = %for.body
+  unreachable
+
+for.end:                                          ; preds = %sw.epilog
+  ret void
+}
Index: lib/Transforms/Utils/LowerSwitch.cpp
===================================================================
--- lib/Transforms/Utils/LowerSwitch.cpp
+++ lib/Transforms/Utils/LowerSwitch.cpp
@@ -584,6 +584,11 @@
         PopSucc->removePredecessor(OrigBlock);
       return;
     }
+
+    // If the condition was a PHI node with the switch block as a predecessor
+    // removing predecessors may have caused the condition to be erased.
+    // Getting the condition value again here protects against that.
+    Val = SI->getCondition();
   }
 
   // Create a new, empty default block so that the new hierarchy of


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D62560.201792.patch
Type: text/x-patch
Size: 1808 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190529/31c3805b/attachment.bin>


More information about the llvm-commits mailing list