[IRBuilder] Add a CreateGCStatepointInvoke.
authorSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 6 May 2015 23:53:09 +0000 (23:53 +0000)
committerSanjoy Das <sanjoy@playingwithpointers.com>
Wed, 6 May 2015 23:53:09 +0000 (23:53 +0000)
Renames the original CreateGCStatepoint to CreateGCStatepointCall, and
moves invoke creating functionality from PlaceSafepoints.cpp to
IRBuilder.cpp.

This changes the labels generated for PlaceSafepoints/invokes.ll so use
a regex there to make the basic block labels more resilient.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236672 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/IR/IRBuilder.h
lib/IR/IRBuilder.cpp
lib/Transforms/Scalar/PlaceSafepoints.cpp
test/Transforms/PlaceSafepoints/invokes.ll

index 515f19c754ea9d0b25bd61260117903d1cfdd5e6..7224496c204b261eddbda22ccb59087228b61073 100644 (file)
@@ -447,19 +447,36 @@ public:
 
   /// \brief Create a call to the experimental.gc.statepoint intrinsic to
   /// start a new statepoint sequence.
-  CallInst *CreateGCStatepoint(Value *ActualCallee,
-                               ArrayRef<Value *> CallArgs,
-                               ArrayRef<Value *> DeoptArgs,
-                               ArrayRef<Value *> GCArgs,
-                               const Twine &Name = "");
+  CallInst *CreateGCStatepointCall(Value *ActualCallee,
+                                   ArrayRef<Value *> CallArgs,
+                                   ArrayRef<Value *> DeoptArgs,
+                                   ArrayRef<Value *> GCArgs,
+                                   const Twine &Name = "");
+
+  // \brief Conveninence function for the common case when CallArgs are filled
+  // in using makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be
+  // .get()'ed to get the Value pointer.
+  CallInst *CreateGCStatepointCall(Value *ActualCallee, ArrayRef<Use> CallArgs,
+                                   ArrayRef<Value *> DeoptArgs,
+                                   ArrayRef<Value *> GCArgs,
+                                   const Twine &Name = "");
+
+  /// brief Create an invoke to the experimental.gc.statepoint intrinsic to
+  /// start a new statepoint sequence.
+  InvokeInst *
+  CreateGCStatepointInvoke(Value *ActualInvokee, BasicBlock *NormalDest,
+                           BasicBlock *UnwindDest, ArrayRef<Value *> InvokeArgs,
+                           ArrayRef<Value *> DeoptArgs,
+                           ArrayRef<Value *> GCArgs, const Twine &Name = "");
 
   // Conveninence function for the common case when CallArgs are filled in using
-  // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get
-  // the Value *.
-  CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef<Use> CallArgs,
-                               ArrayRef<Value *> DeoptArgs,
-                               ArrayRef<Value *> GCArgs,
-                               const Twine &Name = "");
+  // makeArrayRef(CS.arg_begin(), CS.arg_end()); Use needs to be .get()'ed to
+  // get the Value *.
+  InvokeInst *
+  CreateGCStatepointInvoke(Value *ActualInvokee, BasicBlock *NormalDest,
+                           BasicBlock *UnwindDest, ArrayRef<Use> InvokeArgs,
+                           ArrayRef<Value *> DeoptArgs,
+                           ArrayRef<Value *> GCArgs, const Twine &Name = "");
 
   /// \brief Create a call to the experimental.gc.result intrinsic to extract
   /// the result from a call wrapped in a statepoint.
index 001d10fd69e1a11d7fbd01e1a74f474bc477ab68..c526c862bdc156249f0809883c0aabde3a0ec9aa 100644 (file)
@@ -62,6 +62,19 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops,
   return CI;  
 }
 
+static InvokeInst *createInvokeHelper(Value *Invokee, BasicBlock *NormalDest,
+                                      BasicBlock *UnwindDest,
+                                      ArrayRef<Value *> Ops,
+                                      IRBuilderBase *Builder,
+                                      const Twine &Name = "") {
+  InvokeInst *II =
+      InvokeInst::Create(Invokee, NormalDest, UnwindDest, Ops, Name);
+  Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),
+                                                  II);
+  Builder->SetInstDebugLocation(II);
+  return II;
+}
+
 CallInst *IRBuilderBase::
 CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
              bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
@@ -231,11 +244,28 @@ CallInst *IRBuilderBase::CreateMaskedIntrinsic(unsigned Id,
   return createCallHelper(TheFn, Ops, this, Name);
 }
 
-CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
-                                            ArrayRef<Value *> CallArgs,
-                                            ArrayRef<Value *> DeoptArgs,
-                                            ArrayRef<Value *> GCArgs,
-                                            const Twine &Name) {
+static std::vector<Value *> getStatepointArgs(IRBuilderBase &B,
+                                              Value *ActualCallee,
+                                              ArrayRef<Value *> CallArgs,
+                                              ArrayRef<Value *> DeoptArgs,
+                                              ArrayRef<Value *> GCArgs) {
+  std::vector<Value *> Args;
+  Args.push_back(ActualCallee);
+  Args.push_back(B.getInt32(CallArgs.size()));
+  Args.push_back(B.getInt32(0)); // unused
+  Args.insert(Args.end(), CallArgs.begin(), CallArgs.end());
+  Args.push_back(B.getInt32(DeoptArgs.size()));
+  Args.insert(Args.end(), DeoptArgs.begin(), DeoptArgs.end());
+  Args.insert(Args.end(), GCArgs.begin(), GCArgs.end());
+
+  return Args;
+}
+
+CallInst *IRBuilderBase::CreateGCStatepointCall(Value *ActualCallee,
+                                                ArrayRef<Value *> CallArgs,
+                                                ArrayRef<Value *> DeoptArgs,
+                                                ArrayRef<Value *> GCArgs,
+                                                const Twine &Name) {
   // Extract out the type of the callee.
   PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType());
   assert(isa<FunctionType>(FuncPtrType->getElementType()) &&
@@ -248,27 +278,52 @@ CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
     Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint,
                               ArgTypes);
 
-  std::vector<llvm::Value *> args;
-  args.push_back(ActualCallee);
-  args.push_back(getInt32(CallArgs.size()));
-  args.push_back(getInt32(0 /*unused*/));
-  args.insert(args.end(), CallArgs.begin(), CallArgs.end());
-  args.push_back(getInt32(DeoptArgs.size()));
-  args.insert(args.end(), DeoptArgs.begin(), DeoptArgs.end());
-  args.insert(args.end(), GCArgs.begin(), GCArgs.end());
-
-  return createCallHelper(FnStatepoint, args, this, Name);
+  std::vector<llvm::Value *> Args =
+      getStatepointArgs(*this, ActualCallee, CallArgs, DeoptArgs, GCArgs);
+  return createCallHelper(FnStatepoint, Args, this, Name);
 }
 
-CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
-                                            ArrayRef<Use> CallArgs,
-                                            ArrayRef<Value *> DeoptArgs,
-                                            ArrayRef<Value *> GCArgs,
-                                            const Twine &Name) {
+CallInst *IRBuilderBase::CreateGCStatepointCall(Value *ActualCallee,
+                                                ArrayRef<Use> CallArgs,
+                                                ArrayRef<Value *> DeoptArgs,
+                                                ArrayRef<Value *> GCArgs,
+                                                const Twine &Name) {
   std::vector<Value *> VCallArgs;
   for (auto &U : CallArgs)
     VCallArgs.push_back(U.get());
-  return CreateGCStatepoint(ActualCallee, VCallArgs, DeoptArgs, GCArgs, Name);
+  return CreateGCStatepointCall(ActualCallee, VCallArgs, DeoptArgs, GCArgs,
+                                Name);
+}
+
+InvokeInst *IRBuilderBase::CreateGCStatepointInvoke(
+    Value *ActualInvokee, BasicBlock *NormalDest, BasicBlock *UnwindDest,
+    ArrayRef<Value *> InvokeArgs, ArrayRef<Value *> DeoptArgs,
+    ArrayRef<Value *> GCArgs, const Twine &Name) {
+  // Extract out the type of the callee.
+  PointerType *FuncPtrType = cast<PointerType>(ActualInvokee->getType());
+  assert(isa<FunctionType>(FuncPtrType->getElementType()) &&
+         "actual callee must be a callable value");
+
+  Module *M = BB->getParent()->getParent();
+  // Fill in the one generic type'd argument (the function is also vararg)
+  Function *FnStatepoint = Intrinsic::getDeclaration(
+      M, Intrinsic::experimental_gc_statepoint, {FuncPtrType});
+
+  std::vector<llvm::Value *> Args =
+      getStatepointArgs(*this, ActualInvokee, InvokeArgs, DeoptArgs, GCArgs);
+  return createInvokeHelper(FnStatepoint, NormalDest, UnwindDest, Args, this,
+                            Name);
+}
+
+InvokeInst *IRBuilderBase::CreateGCStatepointInvoke(
+    Value *ActualInvokee, BasicBlock *NormalDest, BasicBlock *UnwindDest,
+    ArrayRef<Use> InvokeArgs, ArrayRef<Value *> DeoptArgs,
+    ArrayRef<Value *> GCArgs, const Twine &Name) {
+  std::vector<Value *> VCallArgs;
+  for (auto &U : InvokeArgs)
+    VCallArgs.push_back(U.get());
+  return CreateGCStatepointInvoke(ActualInvokee, NormalDest, UnwindDest,
+                                  VCallArgs, DeoptArgs, GCArgs, Name);
 }
 
 CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,
index 08e41c27c5c6ef834ab762ccd17502daf03ca829..36a1fea4edc99cd901de9f718f632fe946350c25 100644 (file)
@@ -893,7 +893,7 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */
   AttributeSet return_attributes;
   if (CS.isCall()) {
     CallInst *toReplace = cast<CallInst>(CS.getInstruction());
-    CallInst *Call = Builder.CreateGCStatepoint(
+    CallInst *Call = Builder.CreateGCStatepointCall(
         CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()), None,
         None, "safepoint_token");
     Call->setTailCall(toReplace->isTailCall());
@@ -919,42 +919,16 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */
     Builder.SetCurrentDebugLocation(IP->getDebugLoc());
 
   } else if (CS.isInvoke()) {
-    // TODO: make CreateGCStatepoint return an Instruction that we can cast to a
-    // Call or Invoke, instead of doing this junk here.
-
-    // Fill in the one generic type'd argument (the function is also
-    // vararg)
-    std::vector<Type *> argTypes;
-    argTypes.push_back(CS.getCalledValue()->getType());
-
-    Function *gc_statepoint_decl = Intrinsic::getDeclaration(
-        M, Intrinsic::experimental_gc_statepoint, argTypes);
-
-    // First, create the statepoint (with all live ptrs as arguments).
-    std::vector<llvm::Value *> args;
-    // target, #call args, unused, ... call parameters, #deopt args, ... deopt
-    // parameters, ... gc parameters
-    Value *Target = CS.getCalledValue();
-    args.push_back(Target);
-    int callArgSize = CS.arg_size();
-    // #call args
-    args.push_back(Builder.getInt32(callArgSize));
-    // unused
-    args.push_back(Builder.getInt32(0));
-    // call parameters
-    args.insert(args.end(), CS.arg_begin(), CS.arg_end());
-    // #deopt args: 0
-    args.push_back(Builder.getInt32(0));
-
     InvokeInst *toReplace = cast<InvokeInst>(CS.getInstruction());
 
     // Insert the new invoke into the old block.  We'll remove the old one in a
     // moment at which point this will become the new terminator for the
     // original block.
-    InvokeInst *invoke = InvokeInst::Create(
-        gc_statepoint_decl, toReplace->getNormalDest(),
-        toReplace->getUnwindDest(), args, "", toReplace->getParent());
-    invoke->setCallingConv(toReplace->getCallingConv());
+    Builder.SetInsertPoint(toReplace->getParent());
+    InvokeInst *invoke = Builder.CreateGCStatepointInvoke(
+        CS.getCalledValue(), toReplace->getNormalDest(),
+        toReplace->getUnwindDest(), makeArrayRef(CS.arg_begin(), CS.arg_end()),
+        Builder.getInt32(0), None, "safepoint_token");
 
     // Currently we will fail on parameter attributes and on certain
     // function attributes.
index 5fd5bea7e5faae373babb9499129ba321a6c86a6..f91f845b13992c75e2a85c31005fc5188468198e 100644 (file)
@@ -62,6 +62,7 @@ exceptional_return:
 }
 
 define i64 addrspace(1)* @test_phi_node(i1 %cond, i64 addrspace(1)* %obj) gc "statepoint-example" {
+; CHECK-LABEL: @test_phi_node
 ; CHECK-LABEL: entry:
 entry:
   br i1 %cond, label %left, label %right
@@ -74,15 +75,15 @@ right:
   %ret_val_right = invoke i64 addrspace(1)* @"some_call"(i64 addrspace(1)* %obj)
                      to label %merge unwind label %exceptional_return
 
-; CHECK-LABEL: merge1:
+; CHECK: merge[[A:[0-9]]]:
 ; CHECK: gc.result
-; CHECK: br label %merge
+; CHECK: br label %[[with_phi:merge[0-9]*]]
 
-; CHECK-LABEL: merge3:
+; CHECK: merge[[B:[0-9]]]:
 ; CHECK: gc.result
-; CHECK: br label %merge
+; CHECK: br label %[[with_phi]]
 
-; CHECK-LABEL: merge:
+; CHECK: [[with_phi]]:
 ; CHECK: phi
 ; CHECK: ret i64 addrspace(1)* %ret_val
 merge: