Index: llvm/include/llvm/CodeGen/ISDOpcodes.h =================================================================== --- llvm/include/llvm/CodeGen/ISDOpcodes.h +++ llvm/include/llvm/CodeGen/ISDOpcodes.h @@ -1282,6 +1282,11 @@ #define BEGIN_REGISTER_VP_SDNODE(VPSDID, ...) VPSDID, #include "llvm/IR/VPIntrinsics.def" + // The `llvm.experimental.stackmap` intrinsic. + // Operands: input chain, glue, , , [live0[, live1...]] + // Outputs: output chain, glue + STACKMAP, + /// BUILTIN_OP_END - This must be the last enum value in this list. /// The target-specific pre-isel opcode values start here. BUILTIN_OP_END Index: llvm/include/llvm/CodeGen/SelectionDAGISel.h =================================================================== --- llvm/include/llvm/CodeGen/SelectionDAGISel.h +++ llvm/include/llvm/CodeGen/SelectionDAGISel.h @@ -321,6 +321,7 @@ void Select_FREEZE(SDNode *N); void Select_ARITH_FENCE(SDNode *N); + void Select_STACKMAP(SDNode *N); private: void DoInstructionSelection(); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1689,6 +1689,9 @@ break; case ISD::SET_ROUNDING: Res = PromoteIntOp_SET_ROUNDING(N); break; + case ISD::STACKMAP: + Res = PromoteIntOp_STACKMAP(N, OpNo); + break; } // If the result is null, the sub-method took care of registering results etc. @@ -2265,6 +2268,13 @@ return SDValue(DAG.UpdateNodeOperands(N, N->getOperand(0), Op), 0); } +SDValue DAGTypeLegalizer::PromoteIntOp_STACKMAP(SDNode *N, unsigned OpNo) { + assert(OpNo > 1); // Because the first two arguments are guaranteed legal. + SmallVector NewOps(N->ops().begin(), N->ops().end()); + NewOps[OpNo] = ZExtPromotedInteger(N->getOperand(OpNo)); + return SDValue(DAG.UpdateNodeOperands(N, NewOps), 0); +} + //===----------------------------------------------------------------------===// // Integer Result Expansion //===----------------------------------------------------------------------===// Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -404,6 +404,7 @@ SDValue PromoteIntOp_VECREDUCE(SDNode *N); SDValue PromoteIntOp_VP_REDUCE(SDNode *N, unsigned OpNo); SDValue PromoteIntOp_SET_ROUNDING(SDNode *N); + SDValue PromoteIntOp_STACKMAP(SDNode *N, unsigned OpNo); void PromoteSetCCOperands(SDValue &LHS,SDValue &RHS, ISD::CondCode Code); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -9376,9 +9376,9 @@ } } -/// Lower llvm.experimental.stackmap directly to its target opcode. +/// Lower llvm.experimental.stackmap. void SelectionDAGBuilder::visitStackmap(const CallInst &CI) { - // void @llvm.experimental.stackmap(i32 , i32 , + // void @llvm.experimental.stackmap(i64 , i32 , // [live variables...]) assert(CI.getType()->isVoidTy() && "Stackmap cannot return a value."); @@ -9403,29 +9403,18 @@ Chain = DAG.getCALLSEQ_START(getRoot(), 0, 0, DL); InFlag = Chain.getValue(1); - // Add the and constants. - SDValue IDVal = getValue(CI.getOperand(PatchPointOpers::IDPos)); - Ops.push_back(DAG.getTargetConstant( - cast(IDVal)->getZExtValue(), DL, MVT::i64)); - SDValue NBytesVal = getValue(CI.getOperand(PatchPointOpers::NBytesPos)); - Ops.push_back(DAG.getTargetConstant( - cast(NBytesVal)->getZExtValue(), DL, - MVT::i32)); - - // Push live variables for the stack map. - addStackMapLiveVars(CI, 2, DL, Ops, *this); - - // We are not pushing any register mask info here on the operands list, - // because the stackmap doesn't clobber anything. + // Add the STACKMAP operands, starting with DAG house-keeping. + std::vector Operands; + Operands.push_back(Chain); + Operands.push_back(InFlag); - // Push the chain and the glue flag. - Ops.push_back(Chain); - Ops.push_back(InFlag); + // Add the , and live variables arguments. + for (unsigned I = 0; I < CI.arg_size(); I++) + Operands.push_back(getValue(CI.getArgOperand(I))); // Create the STACKMAP node. SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - SDNode *SM = DAG.getMachineNode(TargetOpcode::STACKMAP, DL, NodeTys, Ops); - Chain = SDValue(SM, 0); + Chain = DAG.getNode(ISD::STACKMAP, DL, NodeTys, Operands); InFlag = Chain.getValue(1); Chain = DAG.getCALLSEQ_END(Chain, NullPtr, NullPtr, InFlag, DL); Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGDumper.cpp @@ -490,6 +490,9 @@ case ISD::SDID: \ return #NAME; #include "llvm/IR/VPIntrinsics.def" + + case ISD::STACKMAP: + return "stackmap"; } } Index: llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -51,6 +51,7 @@ #include "llvm/CodeGen/SchedulerRegistry.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/StackMaps.h" #include "llvm/CodeGen/StackProtector.h" #include "llvm/CodeGen/SwiftErrorValueTracking.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -2241,6 +2242,60 @@ N->getOperand(0)); } +void SelectionDAGISel::Select_STACKMAP(SDNode *N) { + std::vector Ops; + auto *It = N->op_begin(); + SDLoc DL(N); + + // Stash the chain and glue operands so we can move them to the end. + SDValue Chain = *It++; + SDValue InFlag = *It++; + + // operand. + SDValue ID = It->get(); + assert(ID.getOpcode() == ISD::Constant); + assert(ID.getValueType() == MVT::i64); + SDValue IDConst = CurDAG->getTargetConstant( + cast(ID)->getZExtValue(), DL, ID.getValueType()); + Ops.push_back(IDConst); + It++; + + // operand. + SDValue Shad = It->get(); + assert(Shad.getOpcode() == ISD::Constant); + assert(Shad.getValueType() == MVT::i32); + SDValue ShadConst = CurDAG->getTargetConstant( + cast(Shad)->getZExtValue(), DL, Shad.getValueType()); + Ops.push_back(ShadConst); + It++; + + // Live variable operands. + for (; It != N->op_end(); It++) { + SDNode *OpNode = It->getNode(); + SDValue O; + if (OpNode->getOpcode() == ISD::Constant) { + Ops.push_back( + CurDAG->getTargetConstant(StackMaps::ConstantOp, DL, MVT::i64)); + O = CurDAG->getTargetConstant( + cast(OpNode)->getZExtValue(), DL, It->getValueType()); + } else if (OpNode->getOpcode() == ISD::FrameIndex) { + FrameIndexSDNode *FI = cast(OpNode); + O = CurDAG->getTargetFrameIndex(FI->getIndex(), It->getValueType()); + } else { + // Otherwise it's a register. + // XXX ^^ is this true? + O = *It; // XXX Also does this guarantee register selection? + } + Ops.push_back(O); + } + + Ops.push_back(Chain); + Ops.push_back(InFlag); + + SDVTList NodeTys = CurDAG->getVTList(MVT::Other, MVT::Glue); + CurDAG->SelectNodeTo(N, TargetOpcode::STACKMAP, NodeTys, Ops); +} + /// GetVBR - decode a vbr encoding whose top bit is set. LLVM_ATTRIBUTE_ALWAYS_INLINE static uint64_t GetVBR(uint64_t Val, const unsigned char *MatcherTable, unsigned &Idx) { @@ -2795,6 +2850,9 @@ case ISD::ARITH_FENCE: Select_ARITH_FENCE(NodeToMatch); return; + case ISD::STACKMAP: + Select_STACKMAP(NodeToMatch); + return; } assert(!NodeToMatch->isMachineOpcode() && "Node already selected!"); Index: llvm/test/CodeGen/X86/selectiondag-stackmap-legalize.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/X86/selectiondag-stackmap-legalize.ll @@ -0,0 +1,49 @@ +; RUN: llc -debug-only=legalize-types -print-after=finalize-isel %s -O1 -mtriple=x86_64-unknown-unknown -o /dev/null 2>&1 | FileCheck %s + + +declare void @llvm.experimental.stackmap(i64, i32, ...) + +define dso_local i32 @main(i32 %argc, i8** %argv) { +entry: + %x = icmp eq i32 %argc, 5 + call void (i64, i32, ...) @llvm.experimental.stackmap(i64 0, i32 0, i1 %x, i7 2) + ; CHECK: Legalizing node: t14: ch,glue = stackmap t10, t10:1, Constant:i64<0>, Constant:i32<0>, t7, Constant:i7<2> + ; CHECK-NEXT: Analyzing result type: ch + ; CHECK-NEXT: Legal result type + ; CHECK-NEXT: Analyzing result type: glue + ; CHECK-NEXT: Legal result type + ; CHECK-NEXT: Analyzing operand: t10: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t10: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t11: i64 = Constant<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t12: i32 = Constant<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t7: i1 = setcc t2, Constant:i32<5>, seteq:ch + ; CHECK-NEXT: Promote integer operand: t14: ch,glue = stackmap t10, t10:1, Constant:i64<0>, Constant:i32<0>, t7, Constant:i7<2> + + ; CHECK: Legalizing node: t14: ch,glue = stackmap t10, t10:1, Constant:i64<0>, Constant:i32<0>, t23, Constant:i7<2> + ; CHECK-NEXT: Analyzing result type: ch + ; CHECK-NEXT: Legal result type + ; CHECK-NEXT: Analyzing result type: glue + ; CHECK-NEXT: Legal result type + ; CHECK-NEXT: Analyzing operand: t10: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t10: ch,glue = callseq_start t0, TargetConstant:i64<0>, TargetConstant:i64<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t11: i64 = Constant<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t12: i32 = Constant<0> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t23: i8 = and t21, Constant:i8<1> + ; CHECK-NEXT: Legal operand + ; CHECK-NEXT: Analyzing operand: t13: i7 = Constant<2> + ; CHECK-NEXT: Promote integer operand: t14: ch,glue = stackmap t10, t10:1, Constant:i64<0>, Constant:i32<0>, t23, Constant:i7<2> + + ; CHECK: # Machine code for function main + ; CHECK: bb.0.entry: + ; CHECK: STACKMAP 0, 0, killed %3:gr8, 2, 2, implicit-def dead early-clobber $r11 + ; CHECK: # End machine code for function main + ret i32 0 +}