From 587b47add04b876fa0e73ef0206949b92738bb99 Mon Sep 17 00:00:00 2001
From: Sanjoy Das <sanjoy@playingwithpointers.com>
Date: Wed, 9 Dec 2015 20:33:52 +0000
Subject: [PATCH] Use WeakVH to keep track of calls with operand bundles in
 CloneCodeInfo

`CloneAndPruneIntoFromInst` can DCE instructions after cloning them into
the new function, and so an AssertingVH is too strong.  This change
switches CloneCodeInfo to use a std::vector<WeakVH>.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255148 91177308-0d34-0410-b5e6-96231b3b80d8
---
 include/llvm/Transforms/Utils/Cloning.h |  5 ++--
 lib/Transforms/Utils/InlineFunction.cpp |  4 +++-
 test/Transforms/Inline/deopt-bundles.ll | 31 +++++++++++++++++++++++++
 3 files changed, 37 insertions(+), 3 deletions(-)

diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h
index 5d5689c2c1a..d1a5fdeaddc 100644
--- a/include/llvm/Transforms/Utils/Cloning.h
+++ b/include/llvm/Transforms/Utils/Cloning.h
@@ -75,8 +75,9 @@ struct ClonedCodeInfo {
   bool ContainsDynamicAllocas;
 
   /// All cloned call sites that have operand bundles attached are appended to
-  /// this vector.
-  std::vector<AssertingVH<Instruction>> OperandBundleCallSites;
+  /// this vector.  This vector may contain nulls if some of the originally
+  /// inserted callsites were DCE'ed after they were cloned.
+  std::vector<WeakVH> OperandBundleCallSites;
 
   ClonedCodeInfo() : ContainsCalls(false), ContainsDynamicAllocas(false) {}
 };
diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp
index 52bde6797db..9a0aabc38a5 100644
--- a/lib/Transforms/Utils/InlineFunction.cpp
+++ b/lib/Transforms/Utils/InlineFunction.cpp
@@ -1162,7 +1162,9 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
       SmallVector<OperandBundleDef, 2> OpDefs;
 
       for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
-        Instruction *I = VH;
+        if (!VH) continue;  // instruction was DCE'd after being cloned
+
+        Instruction *I = cast<Instruction>(VH);
 
         OpDefs.clear();
 
diff --git a/test/Transforms/Inline/deopt-bundles.ll b/test/Transforms/Inline/deopt-bundles.ll
index b4176089075..75e8d55acdb 100644
--- a/test/Transforms/Inline/deopt-bundles.ll
+++ b/test/Transforms/Inline/deopt-bundles.ll
@@ -131,6 +131,37 @@ define i32 @caller_6() {
   ret i32 %x
 }
 
+define i32 @callee_7(i1 %val) alwaysinline personality i8 3 {
+; We want something that PruningFunctionCloner is not smart enough to
+; recognize, but can be recognized by recursivelySimplifyInstruction.
+
+ entry:
+  br i1 %val, label %check, label %precheck
+
+ precheck:
+  br label %check
+
+ check:
+  %p = phi i1 [ %val, %entry ], [ true, %precheck ]
+  br i1 %p, label %do.not, label %do
+
+ do.not:
+  ret i32 0
+
+ do:
+  %v = call fastcc i32 @g.fastcc() [ "deopt"(i32 0, i32 1), "foo"(double 0.0) ]
+  ret i32 %v
+}
+
+define i32 @caller_7() {
+; CHECK-LABEL: @caller_7(
+ entry:
+; CHECK-NOT: call fastcc i32 @g.fastcc() #[[FOO_BAR_ATTR_IDX]] [ "deopt"(i32 7, i32 0, i32 1), "foo"(double 0.000000e+00) ]
+; CHECK: ret i32 0
+  %x = call i32 @callee_7(i1 true) [ "deopt"(i32 7) ]
+  ret i32 %x
+}
+
 attributes #0 = { "foo"="bar" }
 
 ; CHECK: attributes #[[FOO_BAR_ATTR_IDX]] = { "foo"="bar" }
-- 
2.34.1