llvm.org GIT mirror llvm / e10581a
PlaceSafepoints: use IRBuilder helpers Use the IRBuilder helpers for gc.statepoint and gc.result, instead of coding the construction by hand. Note that the gc.statepoint IRBuilder handles only CallInst, not InvokeInst; retain that part of hand-coding. Differential Revision: http://reviews.llvm.org/D7518 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@230591 91177308-0d34-0410-b5e6-96231b3b80d8 Ramkumar Ramachandra 4 years ago
4 changed file(s) with 59 addition(s) and 45 deletion(s). Raw diff Collapse all Expand all
442442 /// start a new statepoint sequence.
443443 CallInst *CreateGCStatepoint(Value *ActualCallee,
444444 ArrayRef CallArgs,
445 ArrayRef DeoptArgs,
446 ArrayRef GCArgs,
447 const Twine &Name = "");
448
449 // Conveninence function for the common case when CallArgs are filled in using
450 // makeArrayRef(CS.arg_begin(), .arg_end()); Use needs to be .get()'ed to get
451 // the Value *.
452 CallInst *CreateGCStatepoint(Value *ActualCallee, ArrayRef CallArgs,
445453 ArrayRef DeoptArgs,
446454 ArrayRef GCArgs,
447455 const Twine &Name = "");
259259 return createCallHelper(FnStatepoint, args, this, Name);
260260 }
261261
262 CallInst *IRBuilderBase::CreateGCStatepoint(Value *ActualCallee,
263 ArrayRef CallArgs,
264 ArrayRef DeoptArgs,
265 ArrayRef GCArgs,
266 const Twine &Name) {
267 std::vector VCallArgs;
268 for (auto &U : CallArgs)
269 VCallArgs.push_back(U.get());
270 return CreateGCStatepoint(ActualCallee, VCallArgs, DeoptArgs, GCArgs, Name);
271 }
272
262273 CallInst *IRBuilderBase::CreateGCResult(Instruction *Statepoint,
263274 Type *ResultType,
264275 const Twine &Name) {
872872 // this logic out to the initialization of the pass. Doesn't appear to
873873 // matter in practice.
874874
875 // Fill in the one generic type'd argument (the function is also vararg)
876 std::vector argTypes;
877 argTypes.push_back(CS.getCalledValue()->getType());
878
879 Function *gc_statepoint_decl = Intrinsic::getDeclaration(
880 M, Intrinsic::experimental_gc_statepoint, argTypes);
881
882875 // Then go ahead and use the builder do actually do the inserts. We insert
883876 // immediately before the previous instruction under the assumption that all
884877 // arguments will be available here. We can't insert afterwards since we may
885878 // be replacing a terminator.
886879 Instruction *insertBefore = CS.getInstruction();
887880 IRBuilder<> Builder(insertBefore);
888 // First, create the statepoint (with all live ptrs as arguments).
889 std::vector args;
890 // target, #call args, unused, call args..., #deopt args, deopt args..., gc args...
891 Value *Target = CS.getCalledValue();
892 args.push_back(Target);
893 int callArgSize = CS.arg_size();
894 args.push_back(
895 ConstantInt::get(Type::getInt32Ty(M->getContext()), callArgSize));
896 // TODO: add a 'Needs GC-rewrite' later flag
897 args.push_back(ConstantInt::get(Type::getInt32Ty(M->getContext()), 0));
898
899 // Copy all the arguments of the original call
900 args.insert(args.end(), CS.arg_begin(), CS.arg_end());
901
902 // # of deopt arguments: this pass currently does not support the
903 // identification of deopt arguments. If this is interesting to you,
904 // please ask on llvm-dev.
905 args.push_back(ConstantInt::get(Type::getInt32Ty(M->getContext()), 0));
906881
907882 // Note: The gc args are not filled in at this time, that's handled by
908883 // RewriteStatepointsForGC (which is currently under review).
912887 AttributeSet return_attributes;
913888 if (CS.isCall()) {
914889 CallInst *toReplace = cast(CS.getInstruction());
915 CallInst *call =
916 Builder.CreateCall(gc_statepoint_decl, args, "safepoint_token");
917 call->setTailCall(toReplace->isTailCall());
918 call->setCallingConv(toReplace->getCallingConv());
890 CallInst *Call = Builder.CreateGCStatepoint(
891 CS.getCalledValue(), makeArrayRef(CS.arg_begin(), CS.arg_end()), None,
892 None, "safepoint_token");
893 Call->setTailCall(toReplace->isTailCall());
894 Call->setCallingConv(toReplace->getCallingConv());
919895
920896 // Before we have to worry about GC semantics, all attributes are legal
921897 AttributeSet new_attrs = toReplace->getAttributes();
922898 // In case if we can handle this set of sttributes - set up function attrs
923899 // directly on statepoint and return attrs later for gc_result intrinsic.
924 call->setAttributes(new_attrs.getFnAttributes());
900 Call->setAttributes(new_attrs.getFnAttributes());
925901 return_attributes = new_attrs.getRetAttributes();
926902 // TODO: handle param attributes
927903
928 token = call;
904 token = Call;
929905
930906 // Put the following gc_result and gc_relocate calls immediately after the
931907 // the old call (which we're about to delete)
937913 Builder.SetCurrentDebugLocation(IP->getDebugLoc());
938914
939915 } else if (CS.isInvoke()) {
916 // TODO: make CreateGCStatepoint return an Instruction that we can cast to a
917 // Call or Invoke, instead of doing this junk here.
918
919 // Fill in the one generic type'd argument (the function is also
920 // vararg)
921 std::vector argTypes;
922 argTypes.push_back(CS.getCalledValue()->getType());
923
924 Function *gc_statepoint_decl = Intrinsic::getDeclaration(
925 M, Intrinsic::experimental_gc_statepoint, argTypes);
926
927 // First, create the statepoint (with all live ptrs as arguments).
928 std::vector args;
929 // target, #call args, unused, ... call parameters, #deopt args, ... deopt
930 // parameters, ... gc parameters
931 Value *Target = CS.getCalledValue();
932 args.push_back(Target);
933 int callArgSize = CS.arg_size();
934 // #call args
935 args.push_back(Builder.getInt32(callArgSize));
936 // unused
937 args.push_back(Builder.getInt32(0));
938 // call parameters
939 args.insert(args.end(), CS.arg_begin(), CS.arg_end());
940 // #deopt args: 0
941 args.push_back(Builder.getInt32(0));
942
940943 InvokeInst *toReplace = cast(CS.getInstruction());
941944
942945 // Insert the new invoke into the old block. We'll remove the old one in a
972975
973976 // Only add the gc_result iff there is actually a used result
974977 if (!CS.getType()->isVoidTy() && !CS.getInstruction()->use_empty()) {
975 Instruction *gc_result = nullptr;
976 std::vector types; // one per 'any' type
977 types.push_back(CS.getType()); // result type
978 Intrinsic::ID Id = Intrinsic::experimental_gc_result;
979 Value *gc_result_func = Intrinsic::getDeclaration(M, Id, types);
980
981 std::vector args;
982 args.push_back(token);
983 gc_result = Builder.CreateCall(
984 gc_result_func, args,
985 CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : "");
986
987 cast(gc_result)->setAttributes(return_attributes);
978 std::string takenName =
979 CS.getInstruction()->hasName() ? CS.getInstruction()->getName() : "";
980 CallInst *gc_result =
981 Builder.CreateGCResult(token, CS.getType(), takenName);
982 gc_result->setAttributes(return_attributes);
988983 return gc_result;
989984 } else {
990985 // No return value for the call.
7373 ; CHECK: gc.statepoint.p0f_isVoidf
7474 ; CHECK: gc.statepoint.p0f_i1i1f
7575 ; CHECK: (i1 (i1)* @i1_return_i1, i32 1, i32 0, i1 false, i32 0)
76 ; CHECK: gc.result.i1
76 ; CHECK: %call12 = call i1 @llvm.experimental.gc.result.i1
7777 entry:
7878 %call1 = tail call i1 (i1)* @i1_return_i1(i1 false)
7979 ret i1 %call1