Skip to content

Commit ad2363f

Browse files
committedOct 17, 2014
[Stackmaps] Enable invoking the patchpoint intrinsic.
Patch by Kevin Modzelewski Reviewers: atrick, ributzka Reviewed By: ributzka Subscribers: llvm-commits, reames Differential Revision: http://reviews.llvm.org/D5634 llvm-svn: 220055
1 parent c48cb86 commit ad2363f

File tree

6 files changed

+141
-57
lines changed

6 files changed

+141
-57
lines changed
 

‎llvm/include/llvm/IR/Intrinsics.td

+4-2
Original file line numberDiff line numberDiff line change
@@ -483,11 +483,13 @@ def int_experimental_stackmap : Intrinsic<[],
483483
def int_experimental_patchpoint_void : Intrinsic<[],
484484
[llvm_i64_ty, llvm_i32_ty,
485485
llvm_ptr_ty, llvm_i32_ty,
486-
llvm_vararg_ty]>;
486+
llvm_vararg_ty],
487+
[Throws]>;
487488
def int_experimental_patchpoint_i64 : Intrinsic<[llvm_i64_ty],
488489
[llvm_i64_ty, llvm_i32_ty,
489490
llvm_ptr_ty, llvm_i32_ty,
490-
llvm_vararg_ty]>;
491+
llvm_vararg_ty],
492+
[Throws]>;
491493

492494
//===-------------------------- Other Intrinsics --------------------------===//
493495
//

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

+55-45
Original file line numberDiff line numberDiff line change
@@ -2008,8 +2008,17 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) {
20082008
if (isa<InlineAsm>(Callee))
20092009
visitInlineAsm(&I);
20102010
else if (Fn && Fn->isIntrinsic()) {
2011-
assert(Fn->getIntrinsicID() == Intrinsic::donothing);
2012-
// Ignore invokes to @llvm.donothing: jump directly to the next BB.
2011+
switch (Fn->getIntrinsicID()) {
2012+
default:
2013+
llvm_unreachable("Cannot invoke this intrinsic");
2014+
case Intrinsic::donothing:
2015+
// Ignore invokes to @llvm.donothing: jump directly to the next BB.
2016+
break;
2017+
case Intrinsic::experimental_patchpoint_void:
2018+
case Intrinsic::experimental_patchpoint_i64:
2019+
visitPatchpoint(&I, LandingPad);
2020+
break;
2021+
}
20132022
} else
20142023
LowerCallTo(&I, getValue(Callee), false, LandingPad);
20152024

@@ -5429,7 +5438,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
54295438
}
54305439
case Intrinsic::experimental_patchpoint_void:
54315440
case Intrinsic::experimental_patchpoint_i64: {
5432-
visitPatchpoint(I);
5441+
visitPatchpoint(&I);
54335442
return nullptr;
54345443
}
54355444
}
@@ -6786,18 +6795,18 @@ void SelectionDAGBuilder::visitVACopy(const CallInst &I) {
67866795
/// convention or require stack pointer adjustment. Only a subset of the
67876796
/// intrinsic's operands need to participate in the calling convention.
67886797
std::pair<SDValue, SDValue>
6789-
SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx,
6798+
SelectionDAGBuilder::lowerCallOperands(ImmutableCallSite CS, unsigned ArgIdx,
67906799
unsigned NumArgs, SDValue Callee,
6791-
bool useVoidTy) {
6800+
bool UseVoidTy,
6801+
MachineBasicBlock *LandingPad) {
67926802
TargetLowering::ArgListTy Args;
67936803
Args.reserve(NumArgs);
67946804

67956805
// Populate the argument list.
67966806
// Attributes for args start at offset 1, after the return attribute.
6797-
ImmutableCallSite CS(&CI);
67986807
for (unsigned ArgI = ArgIdx, ArgE = ArgIdx + NumArgs, AttrI = ArgIdx + 1;
67996808
ArgI != ArgE; ++ArgI) {
6800-
const Value *V = CI.getOperand(ArgI);
6809+
const Value *V = CS->getOperand(ArgI);
68016810

68026811
assert(!V->getType()->isEmptyTy() && "Empty type passed to intrinsic.");
68036812

@@ -6808,13 +6817,13 @@ SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx,
68086817
Args.push_back(Entry);
68096818
}
68106819

6811-
Type *retTy = useVoidTy ? Type::getVoidTy(*DAG.getContext()) : CI.getType();
6820+
Type *retTy = UseVoidTy ? Type::getVoidTy(*DAG.getContext()) : CS->getType();
68126821
TargetLowering::CallLoweringInfo CLI(DAG);
68136822
CLI.setDebugLoc(getCurSDLoc()).setChain(getRoot())
6814-
.setCallee(CI.getCallingConv(), retTy, Callee, std::move(Args), NumArgs)
6815-
.setDiscardResult(!CI.use_empty());
6823+
.setCallee(CS.getCallingConv(), retTy, Callee, std::move(Args), NumArgs)
6824+
.setDiscardResult(CS->use_empty());
68166825

6817-
return lowerInvokable(CLI, nullptr);
6826+
return lowerInvokable(CLI, LandingPad);
68186827
}
68196828

68206829
/// \brief Add a stack map intrinsic call's live variable operands to a stackmap
@@ -6834,11 +6843,11 @@ SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx,
68346843
/// assumption made by the llvm.gcroot intrinsic). If the alloca's location were
68356844
/// only available in a register, then the runtime would need to trap when
68366845
/// execution reaches the StackMap in order to read the alloca's location.
6837-
static void addStackMapLiveVars(const CallInst &CI, unsigned StartIdx,
6846+
static void addStackMapLiveVars(ImmutableCallSite CS, unsigned StartIdx,
68386847
SmallVectorImpl<SDValue> &Ops,
68396848
SelectionDAGBuilder &Builder) {
6840-
for (unsigned i = StartIdx, e = CI.getNumArgOperands(); i != e; ++i) {
6841-
SDValue OpVal = Builder.getValue(CI.getArgOperand(i));
6849+
for (unsigned i = StartIdx, e = CS.arg_size(); i != e; ++i) {
6850+
SDValue OpVal = Builder.getValue(CS.getArgument(i));
68426851
if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(OpVal)) {
68436852
Ops.push_back(
68446853
Builder.DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64));
@@ -6889,7 +6898,7 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
68896898
cast<ConstantSDNode>(NBytesVal)->getZExtValue(), MVT::i32));
68906899

68916900
// Push live variables for the stack map.
6892-
addStackMapLiveVars(CI, 2, Ops, *this);
6901+
addStackMapLiveVars(&CI, 2, Ops, *this);
68936902

68946903
// We are not pushing any register mask info here on the operands list,
68956904
// because the stackmap doesn't clobber anything.
@@ -6916,54 +6925,55 @@ void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
69166925
}
69176926

69186927
/// \brief Lower llvm.experimental.patchpoint directly to its target opcode.
6919-
void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) {
6928+
void SelectionDAGBuilder::visitPatchpoint(ImmutableCallSite CS,
6929+
MachineBasicBlock *LandingPad) {
69206930
// void|i64 @llvm.experimental.patchpoint.void|i64(i64 <id>,
69216931
// i32 <numBytes>,
69226932
// i8* <target>,
69236933
// i32 <numArgs>,
69246934
// [Args...],
69256935
// [live variables...])
69266936

6927-
CallingConv::ID CC = CI.getCallingConv();
6928-
bool isAnyRegCC = CC == CallingConv::AnyReg;
6929-
bool hasDef = !CI.getType()->isVoidTy();
6930-
SDValue Callee = getValue(CI.getOperand(2)); // <target>
6937+
CallingConv::ID CC = CS.getCallingConv();
6938+
bool IsAnyRegCC = CC == CallingConv::AnyReg;
6939+
bool HasDef = !CS->getType()->isVoidTy();
6940+
SDValue Callee = getValue(CS->getOperand(2)); // <target>
69316941

69326942
// Get the real number of arguments participating in the call <numArgs>
6933-
SDValue NArgVal = getValue(CI.getArgOperand(PatchPointOpers::NArgPos));
6943+
SDValue NArgVal = getValue(CS.getArgument(PatchPointOpers::NArgPos));
69346944
unsigned NumArgs = cast<ConstantSDNode>(NArgVal)->getZExtValue();
69356945

69366946
// Skip the four meta args: <id>, <numNopBytes>, <target>, <numArgs>
69376947
// Intrinsics include all meta-operands up to but not including CC.
69386948
unsigned NumMetaOpers = PatchPointOpers::CCPos;
6939-
assert(CI.getNumArgOperands() >= NumMetaOpers + NumArgs &&
6949+
assert(CS.arg_size() >= NumMetaOpers + NumArgs &&
69406950
"Not enough arguments provided to the patchpoint intrinsic");
69416951

69426952
// For AnyRegCC the arguments are lowered later on manually.
6943-
unsigned NumCallArgs = isAnyRegCC ? 0 : NumArgs;
6953+
unsigned NumCallArgs = IsAnyRegCC ? 0 : NumArgs;
69446954
std::pair<SDValue, SDValue> Result =
6945-
LowerCallOperands(CI, NumMetaOpers, NumCallArgs, Callee, isAnyRegCC);
6955+
lowerCallOperands(CS, NumMetaOpers, NumCallArgs, Callee, IsAnyRegCC,
6956+
LandingPad);
69466957

6947-
SDValue Chain = Result.second;
6948-
SDNode *CallEnd = Chain.getNode();
6949-
if (hasDef && (CallEnd->getOpcode() == ISD::CopyFromReg))
6958+
SDNode *CallEnd = Result.second.getNode();
6959+
if (HasDef && (CallEnd->getOpcode() == ISD::CopyFromReg))
69506960
CallEnd = CallEnd->getOperand(0).getNode();
69516961

69526962
/// Get a call instruction from the call sequence chain.
69536963
/// Tail calls are not allowed.
69546964
assert(CallEnd->getOpcode() == ISD::CALLSEQ_END &&
69556965
"Expected a callseq node.");
69566966
SDNode *Call = CallEnd->getOperand(0).getNode();
6957-
bool hasGlue = Call->getGluedNode();
6967+
bool HasGlue = Call->getGluedNode();
69586968

69596969
// Replace the target specific call node with the patchable intrinsic.
69606970
SmallVector<SDValue, 8> Ops;
69616971

69626972
// Add the <id> and <numBytes> constants.
6963-
SDValue IDVal = getValue(CI.getOperand(PatchPointOpers::IDPos));
6973+
SDValue IDVal = getValue(CS->getOperand(PatchPointOpers::IDPos));
69646974
Ops.push_back(DAG.getTargetConstant(
69656975
cast<ConstantSDNode>(IDVal)->getZExtValue(), MVT::i64));
6966-
SDValue NBytesVal = getValue(CI.getOperand(PatchPointOpers::NBytesPos));
6976+
SDValue NBytesVal = getValue(CS->getOperand(PatchPointOpers::NBytesPos));
69676977
Ops.push_back(DAG.getTargetConstant(
69686978
cast<ConstantSDNode>(NBytesVal)->getZExtValue(), MVT::i32));
69696979

@@ -6976,29 +6986,29 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) {
69766986
// Adjust <numArgs> to account for any arguments that have been passed on the
69776987
// stack instead.
69786988
// Call Node: Chain, Target, {Args}, RegMask, [Glue]
6979-
unsigned NumCallRegArgs = Call->getNumOperands() - (hasGlue ? 4 : 3);
6980-
NumCallRegArgs = isAnyRegCC ? NumArgs : NumCallRegArgs;
6989+
unsigned NumCallRegArgs = Call->getNumOperands() - (HasGlue ? 4 : 3);
6990+
NumCallRegArgs = IsAnyRegCC ? NumArgs : NumCallRegArgs;
69816991
Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, MVT::i32));
69826992

69836993
// Add the calling convention
69846994
Ops.push_back(DAG.getTargetConstant((unsigned)CC, MVT::i32));
69856995

69866996
// Add the arguments we omitted previously. The register allocator should
69876997
// place these in any free register.
6988-
if (isAnyRegCC)
6998+
if (IsAnyRegCC)
69896999
for (unsigned i = NumMetaOpers, e = NumMetaOpers + NumArgs; i != e; ++i)
6990-
Ops.push_back(getValue(CI.getArgOperand(i)));
7000+
Ops.push_back(getValue(CS.getArgument(i)));
69917001

69927002
// Push the arguments from the call instruction up to the register mask.
6993-
SDNode::op_iterator e = hasGlue ? Call->op_end()-2 : Call->op_end()-1;
7003+
SDNode::op_iterator e = HasGlue ? Call->op_end()-2 : Call->op_end()-1;
69947004
for (SDNode::op_iterator i = Call->op_begin()+2; i != e; ++i)
69957005
Ops.push_back(*i);
69967006

69977007
// Push live variables for the stack map.
6998-
addStackMapLiveVars(CI, NumMetaOpers + NumArgs, Ops, *this);
7008+
addStackMapLiveVars(CS, NumMetaOpers + NumArgs, Ops, *this);
69997009

70007010
// Push the register mask info.
7001-
if (hasGlue)
7011+
if (HasGlue)
70027012
Ops.push_back(*(Call->op_end()-2));
70037013
else
70047014
Ops.push_back(*(Call->op_end()-1));
@@ -7008,15 +7018,15 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) {
70087018
Ops.push_back(*(Call->op_begin()));
70097019

70107020
// Push the glue flag (last operand).
7011-
if (hasGlue)
7021+
if (HasGlue)
70127022
Ops.push_back(*(Call->op_end()-1));
70137023

70147024
SDVTList NodeTys;
7015-
if (isAnyRegCC && hasDef) {
7025+
if (IsAnyRegCC && HasDef) {
70167026
// Create the return types based on the intrinsic definition
70177027
const TargetLowering &TLI = DAG.getTargetLoweringInfo();
70187028
SmallVector<EVT, 3> ValueVTs;
7019-
ComputeValueVTs(TLI, CI.getType(), ValueVTs);
7029+
ComputeValueVTs(TLI, CS->getType(), ValueVTs);
70207030
assert(ValueVTs.size() == 1 && "Expected only one return value type.");
70217031

70227032
// There is always a chain and a glue type at the end
@@ -7031,18 +7041,18 @@ void SelectionDAGBuilder::visitPatchpoint(const CallInst &CI) {
70317041
getCurSDLoc(), NodeTys, Ops);
70327042

70337043
// Update the NodeMap.
7034-
if (hasDef) {
7035-
if (isAnyRegCC)
7036-
setValue(&CI, SDValue(MN, 0));
7044+
if (HasDef) {
7045+
if (IsAnyRegCC)
7046+
setValue(CS.getInstruction(), SDValue(MN, 0));
70377047
else
7038-
setValue(&CI, Result.first);
7048+
setValue(CS.getInstruction(), Result.first);
70397049
}
70407050

70417051
// Fixup the consumers of the intrinsic. The chain and glue may be used in the
70427052
// call sequence. Furthermore the location of the chain and glue can change
70437053
// when the AnyReg calling convention is used and the intrinsic returns a
70447054
// value.
7045-
if (isAnyRegCC && hasDef) {
7055+
if (IsAnyRegCC && HasDef) {
70467056
SDValue From[] = {SDValue(Call, 0), SDValue(Call, 1)};
70477057
SDValue To[] = {SDValue(MN, 1), SDValue(MN, 2)};
70487058
DAG.ReplaceAllUsesOfValuesWith(From, To, 2);

‎llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h

+9-6
Original file line numberDiff line numberDiff line change
@@ -634,11 +634,13 @@ class SelectionDAGBuilder {
634634
void LowerCallTo(ImmutableCallSite CS, SDValue Callee, bool IsTailCall,
635635
MachineBasicBlock *LandingPad = nullptr);
636636

637-
std::pair<SDValue, SDValue> LowerCallOperands(const CallInst &CI,
638-
unsigned ArgIdx,
639-
unsigned NumArgs,
640-
SDValue Callee,
641-
bool useVoidTy = false);
637+
std::pair<SDValue, SDValue> lowerCallOperands(
638+
ImmutableCallSite CS,
639+
unsigned ArgIdx,
640+
unsigned NumArgs,
641+
SDValue Callee,
642+
bool UseVoidTy = false,
643+
MachineBasicBlock *LandingPad = nullptr);
642644

643645
/// UpdateSplitBlock - When an MBB was split during scheduling, update the
644646
/// references that need to refer to the last resulting block.
@@ -778,7 +780,8 @@ class SelectionDAGBuilder {
778780
void visitVAEnd(const CallInst &I);
779781
void visitVACopy(const CallInst &I);
780782
void visitStackmap(const CallInst &I);
781-
void visitPatchpoint(const CallInst &I);
783+
void visitPatchpoint(ImmutableCallSite CS,
784+
MachineBasicBlock *LandingPad = nullptr);
782785

783786
void visitUserOp1(const Instruction &I) {
784787
llvm_unreachable("UserOp1 should not exist at instruction selection time!");

‎llvm/lib/IR/Verifier.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -2212,11 +2212,15 @@ void Verifier::visitInstruction(Instruction &I) {
22122212
if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
22132213
// Check to make sure that the "address of" an intrinsic function is never
22142214
// taken.
2215-
Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 : 0),
2215+
Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 :
2216+
isa<InvokeInst>(I) ? e-3 : 0),
22162217
"Cannot take the address of an intrinsic!", &I);
22172218
Assert1(!F->isIntrinsic() || isa<CallInst>(I) ||
2218-
F->getIntrinsicID() == Intrinsic::donothing,
2219-
"Cannot invoke an intrinsinc other than donothing", &I);
2219+
F->getIntrinsicID() == Intrinsic::donothing ||
2220+
F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
2221+
F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64,
2222+
"Cannot invoke an intrinsinc other than"
2223+
" donothing or patchpoint", &I);
22202224
Assert1(F->getParent() == M, "Referencing function in another module!",
22212225
&I);
22222226
} else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) {
+65
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
; RUN: llc -mtriple=x86_64-unknown-linux -mcpu=corei7 < %s | FileCheck %s
2+
3+
; Test invoking of patchpoints
4+
;
5+
define i64 @patchpoint_invoke(i64 %p1, i64 %p2) {
6+
entry:
7+
; CHECK-LABEL: patchpoint_invoke:
8+
; CHECK-NEXT: .cfi_startproc
9+
; CHECK: [[FUNC_BEGIN:.L.*]]:
10+
; CHECK: .cfi_lsda 3, [[EXCEPTION_LABEL:.L[^ ]*]]
11+
; CHECK: pushq %rbp
12+
13+
; Unfortunately, hardcode the name of the label that begins the patchpoint:
14+
; CHECK: .Ltmp0:
15+
; CHECK: movabsq $-559038736, %r11
16+
; CHECK-NEXT: callq *%r11
17+
; CHECK-NEXT: xchgw %ax, %ax
18+
; CHECK-NEXT: [[PP_END:.L.*]]:
19+
; CHECK: ret
20+
%resolveCall = inttoptr i64 -559038736 to i8*
21+
%result = invoke i64 (i64, i32, i8*, i32, ...)* @llvm.experimental.patchpoint.i64(i64 2, i32 15, i8* %resolveCall, i32 1, i64 %p1, i64 %p2)
22+
to label %success unwind label %threw
23+
24+
success:
25+
ret i64 %result
26+
27+
threw:
28+
%0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
29+
catch i8* null
30+
ret i64 0
31+
}
32+
33+
; Verify that the exception table was emitted:
34+
; CHECK: [[EXCEPTION_LABEL]]:
35+
; CHECK-NEXT: .byte 255
36+
; CHECK-NEXT: .byte 3
37+
; CHECK-NEXT: .byte 21
38+
; CHECK-NEXT: .byte 3
39+
; CHECK-NEXT: .byte 13
40+
; Verify that the unwind data covers the entire patchpoint region:
41+
; CHECK-NEXT: [[RANGE_OFFSET:.L[^ ]*]] = .Ltmp0-[[FUNC_BEGIN]]
42+
; CHECK-NEXT: .long [[RANGE_OFFSET]]
43+
; CHECK-NEXT: [[RANGE_LENGTH:.L[^ ]*]] = [[PP_END]]-.Ltmp0
44+
; CHECK-NEXT: .long [[RANGE_LENGTH]]
45+
46+
47+
; Verify that the stackmap section got emitted:
48+
; CHECK-LABEL: __LLVM_StackMaps:
49+
; Header
50+
; CHECK-NEXT: .byte 1
51+
; CHECK-NEXT: .byte 0
52+
; CHECK-NEXT: .short 0
53+
; Num Functions
54+
; CHECK-NEXT: .long 1
55+
; Num LargeConstants
56+
; CHECK-NEXT: .long 0
57+
; Num Callsites
58+
; CHECK-NEXT: .long 1
59+
; CHECK-NEXT: .quad patchpoint_invoke
60+
61+
62+
declare void @llvm.experimental.stackmap(i64, i32, ...)
63+
declare void @llvm.experimental.patchpoint.void(i64, i32, i8*, i32, ...)
64+
declare i64 @llvm.experimental.patchpoint.i64(i64, i32, i8*, i32, ...)
65+
declare i32 @__gxx_personality_v0(...)

‎llvm/test/Verifier/invoke.ll

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ contb:
4646

4747
define i8 @f2() {
4848
entry:
49-
; CHECK: Cannot invoke an intrinsinc other than donothing
49+
; CHECK: Cannot invoke an intrinsinc other than donothing or patchpoint
5050
invoke void @llvm.trap()
5151
to label %cont unwind label %lpad
5252

0 commit comments

Comments
 (0)
Please sign in to comment.