[GVNSink] prevent crashing on mismatched instructions (PR42346)
authorSanjay Patel <spatel@rotateright.com>
Fri, 21 Jun 2019 15:17:24 +0000 (15:17 +0000)
committerSanjay Patel <spatel@rotateright.com>
Fri, 21 Jun 2019 15:17:24 +0000 (15:17 +0000)
Patch based on suggestion by James Molloy (@jmolloy) in:
https://bugs.llvm.org/show_bug.cgi?id=42346

llvm-svn: 364062

llvm/lib/Transforms/Scalar/GVNSink.cpp
llvm/test/Transforms/GVNSink/operand-mismatch.ll [new file with mode: 0644]

index bf5ec47fbbbc4b947b4b83035e9bccc54db30c52..735f68329af5fc7c1297638cb44d07255acb4fab 100644 (file)
@@ -713,6 +713,15 @@ Optional<SinkingInstructionCandidate> GVNSink::analyzeInstructionForSinking(
   // FIXME: If any of these fail, we should partition up the candidates to
   // try and continue making progress.
   Instruction *I0 = NewInsts[0];
+
+  // If all instructions that are going to participate don't have the same
+  // number of operands, we can't do any useful PHI analysis for all operands.
+  auto hasDifferentNumOperands = [&I0](Instruction *I) {
+    return I->getNumOperands() != I0->getNumOperands();
+  };
+  if (any_of(NewInsts, hasDifferentNumOperands))
+    return None;
+
   for (unsigned OpNum = 0, E = I0->getNumOperands(); OpNum != E; ++OpNum) {
     ModelledPHI PHI(NewInsts, OpNum, ActivePreds);
     if (PHI.areAllIncomingValuesSame())
diff --git a/llvm/test/Transforms/GVNSink/operand-mismatch.ll b/llvm/test/Transforms/GVNSink/operand-mismatch.ll
new file mode 100644 (file)
index 0000000..2ca45cb
--- /dev/null
@@ -0,0 +1,34 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -gvn-sink -S < %s | FileCheck %s
+
+; This would assert/crash because the calls have different numbers of operands:
+; https://bugs.llvm.org/show_bug.cgi?id=42346
+
+%vec = type opaque
+%map = type { i32 }
+
+define void @PR42346() {
+; CHECK-LABEL: @PR42346(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[CALL1:%.*]] = call %vec* @bar(%map* undef, %vec* (%map*)* undef)
+; CHECK-NEXT:    br label [[EXIT:%.*]]
+; CHECK:       if:
+; CHECK-NEXT:    [[CALL2:%.*]] = call %vec* @baz(%map* undef)
+; CHECK-NEXT:    br label [[EXIT]]
+; CHECK:       exit:
+; CHECK-NEXT:    ret void
+;
+entry:
+  %call1 = call %vec* @bar(%map* undef, %vec* (%map*)* undef)
+  br label %exit
+
+if:
+  %call2 = call %vec* @baz(%map* undef)
+  br label %exit
+
+exit:
+  ret void
+}
+
+declare %vec* @bar(%map*, %vec* (%map*)*)
+declare %vec* @baz(%map*)