From 8a86e2564d5e6225f4dc5d1c4be96937022fdd7a Mon Sep 17 00:00:00 2001 From: Sanjoy Das Date: Wed, 6 May 2015 23:53:09 +0000 Subject: [PATCH] [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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236672 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/IRBuilder.h | 39 ++++++--- lib/IR/IRBuilder.cpp | 97 +++++++++++++++++----- lib/Transforms/Scalar/PlaceSafepoints.cpp | 38 ++------- test/Transforms/PlaceSafepoints/invokes.ll | 11 +-- 4 files changed, 116 insertions(+), 69 deletions(-) diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 515f19c754e..7224496c204 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -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 CallArgs, - ArrayRef DeoptArgs, - ArrayRef GCArgs, - const Twine &Name = ""); + CallInst *CreateGCStatepointCall(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef 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 CallArgs, + ArrayRef DeoptArgs, + ArrayRef 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 InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef 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 CallArgs, - ArrayRef DeoptArgs, - ArrayRef 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 InvokeArgs, + ArrayRef DeoptArgs, + ArrayRef 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. diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 001d10fd69e..c526c862bdc 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -62,6 +62,19 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef Ops, return CI; } +static InvokeInst *createInvokeHelper(Value *Invokee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, + ArrayRef 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 CallArgs, - ArrayRef DeoptArgs, - ArrayRef GCArgs, - const Twine &Name) { +static std::vector getStatepointArgs(IRBuilderBase &B, + Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs) { + std::vector 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 CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name) { // Extract out the type of the callee. PointerType *FuncPtrType = cast(ActualCallee->getType()); assert(isa(FuncPtrType->getElementType()) && @@ -248,27 +278,52 @@ CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee, Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, ArgTypes); - std::vector 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 Args = + getStatepointArgs(*this, ActualCallee, CallArgs, DeoptArgs, GCArgs); + return createCallHelper(FnStatepoint, Args, this, Name); } -CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee, - ArrayRef CallArgs, - ArrayRef DeoptArgs, - ArrayRef GCArgs, - const Twine &Name) { +CallInst *IRBuilderBase::CreateGCStatepointCall(Value *ActualCallee, + ArrayRef CallArgs, + ArrayRef DeoptArgs, + ArrayRef GCArgs, + const Twine &Name) { std::vector 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 InvokeArgs, ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name) { + // Extract out the type of the callee. + PointerType *FuncPtrType = cast(ActualInvokee->getType()); + assert(isa(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 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 InvokeArgs, ArrayRef DeoptArgs, + ArrayRef GCArgs, const Twine &Name) { + std::vector VCallArgs; + for (auto &U : InvokeArgs) + VCallArgs.push_back(U.get()); + return CreateGCStatepointInvoke(ActualInvokee, NormalDest, UnwindDest, + VCallArgs, DeoptArgs, GCArgs, Name); } CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint, diff --git a/lib/Transforms/Scalar/PlaceSafepoints.cpp b/lib/Transforms/Scalar/PlaceSafepoints.cpp index 08e41c27c5c..36a1fea4edc 100644 --- a/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/lib/Transforms/Scalar/PlaceSafepoints.cpp @@ -893,7 +893,7 @@ static Value *ReplaceWithStatepoint(const CallSite &CS, /* to replace */ AttributeSet return_attributes; if (CS.isCall()) { CallInst *toReplace = cast(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 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 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(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. diff --git a/test/Transforms/PlaceSafepoints/invokes.ll b/test/Transforms/PlaceSafepoints/invokes.ll index 5fd5bea7e5f..f91f845b139 100644 --- a/test/Transforms/PlaceSafepoints/invokes.ll +++ b/test/Transforms/PlaceSafepoints/invokes.ll @@ -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: -- 2.34.1