[llvm] r236672 - [IRBuilder] Add a CreateGCStatepointInvoke.

Sanjoy Das sanjoy at playingwithpointers.com
Wed May 6 16:53:09 PDT 2015


Author: sanjoy
Date: Wed May  6 18:53:09 2015
New Revision: 236672

URL: http://llvm.org/viewvc/llvm-project?rev=236672&view=rev
Log:
[IRBuilder] Add a CreateGCStatepointInvoke.

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.

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

Modified: llvm/trunk/include/llvm/IR/IRBuilder.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/IRBuilder.h?rev=236672&r1=236671&r2=236672&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/IRBuilder.h (original)
+++ llvm/trunk/include/llvm/IR/IRBuilder.h Wed May  6 18:53:09 2015
@@ -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.

Modified: llvm/trunk/lib/IR/IRBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/IRBuilder.cpp?rev=236672&r1=236671&r2=236672&view=diff
==============================================================================
--- llvm/trunk/lib/IR/IRBuilder.cpp (original)
+++ llvm/trunk/lib/IR/IRBuilder.cpp Wed May  6 18:53:09 2015
@@ -62,6 +62,19 @@ static CallInst *createCallHelper(Value
   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::CreateMaskedInt
   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::CreateGCStatepo
     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);
-}
-
-CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
-                                            ArrayRef<Use> CallArgs,
-                                            ArrayRef<Value *> DeoptArgs,
-                                            ArrayRef<Value *> GCArgs,
-                                            const Twine &Name) {
+  std::vector<llvm::Value *> Args =
+      getStatepointArgs(*this, ActualCallee, CallArgs, DeoptArgs, GCArgs);
+  return createCallHelper(FnStatepoint, Args, this, 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,

Modified: llvm/trunk/lib/Transforms/Scalar/PlaceSafepoints.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/PlaceSafepoints.cpp?rev=236672&r1=236671&r2=236672&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/PlaceSafepoints.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/PlaceSafepoints.cpp Wed May  6 18:53:09 2015
@@ -893,7 +893,7 @@ static Value *ReplaceWithStatepoint(cons
   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(cons
     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.

Modified: llvm/trunk/test/Transforms/PlaceSafepoints/invokes.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/PlaceSafepoints/invokes.ll?rev=236672&r1=236671&r2=236672&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/PlaceSafepoints/invokes.ll (original)
+++ llvm/trunk/test/Transforms/PlaceSafepoints/invokes.ll Wed May  6 18:53:09 2015
@@ -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:





More information about the llvm-commits mailing list