diff options
| author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-05-06 23:53:09 +0000 |
|---|---|---|
| committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2015-05-06 23:53:09 +0000 |
| commit | abe1c685ac4df7a3cf11e43d922d696d49728a18 (patch) | |
| tree | 88426b67d9e2f05397e4337b0ccf7bf28773d21f /llvm | |
| parent | 32b3760cf3483f64475acf7d24f31ac3f1b66176 (diff) | |
| download | bcm5719-llvm-abe1c685ac4df7a3cf11e43d922d696d49728a18.tar.gz bcm5719-llvm-abe1c685ac4df7a3cf11e43d922d696d49728a18.zip | |
[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.
llvm-svn: 236672
Diffstat (limited to 'llvm')
| -rw-r--r-- | llvm/include/llvm/IR/IRBuilder.h | 39 | ||||
| -rw-r--r-- | llvm/lib/IR/IRBuilder.cpp | 97 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp | 38 | ||||
| -rw-r--r-- | llvm/test/Transforms/PlaceSafepoints/invokes.ll | 11 |
4 files changed, 116 insertions, 69 deletions
diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h index 515f19c754e..7224496c204 100644 --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/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<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. diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 001d10fd69e..c526c862bdc 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -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, diff --git a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp b/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp index 08e41c27c5c..36a1fea4edc 100644 --- a/llvm/lib/Transforms/Scalar/PlaceSafepoints.cpp +++ b/llvm/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<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. diff --git a/llvm/test/Transforms/PlaceSafepoints/invokes.ll b/llvm/test/Transforms/PlaceSafepoints/invokes.ll index 5fd5bea7e5f..f91f845b139 100644 --- a/llvm/test/Transforms/PlaceSafepoints/invokes.ll +++ b/llvm/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: |

