[llvm] r193769 - Lower stackmap intrinsics directly to their target opcode in the DAG builder.

Aaron Ballman aaron at aaronballman.com
Fri Nov 1 08:09:24 PDT 2013


On Thu, Oct 31, 2013 at 1:18 PM, Andrew Trick <atrick at apple.com> wrote:
> Author: atrick
> Date: Thu Oct 31 12:18:24 2013
> New Revision: 193769
>
> URL: http://llvm.org/viewvc/llvm-project?rev=193769&view=rev
> Log:
> Lower stackmap intrinsics directly to their target opcode in the DAG builder.
>
> Modified:
>     llvm/trunk/include/llvm/Target/Target.td
>     llvm/trunk/include/llvm/Target/TargetLowering.h
>     llvm/trunk/include/llvm/Target/TargetOpcodes.h
>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
>     llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h
>     llvm/trunk/lib/CodeGen/SelectionDAG/TargetLowering.cpp
>     llvm/trunk/utils/TableGen/CodeGenTarget.cpp
>
> Modified: llvm/trunk/include/llvm/Target/Target.td
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/Target.td?rev=193769&r1=193768&r2=193769&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/Target.td (original)
> +++ llvm/trunk/include/llvm/Target/Target.td Thu Oct 31 12:18:24 2013
> @@ -800,6 +800,19 @@ def LIFETIME_END : Instruction {
>    let AsmString = "LIFETIME_END";
>    let neverHasSideEffects = 1;
>  }
> +def STACKMAP : Instruction {
> +  let OutOperandList = (outs);
> +  let InOperandList = (ins i32imm:$id, i32imm:$nbytes, variable_ops);
> +  let isCall = 1;
> +  let mayLoad = 1;
> +}
> +def PATCHPOINT : Instruction {
> +  let OutOperandList = (outs);
> +  let InOperandList = (ins i32imm:$id, i32imm:$nbytes, unknown:$callee,
> +                       i32imm:$nargs, variable_ops);
> +  let isCall = 1;
> +  let mayLoad = 1;
> +}
>  }
>
>  //===----------------------------------------------------------------------===//
>
> Modified: llvm/trunk/include/llvm/Target/TargetLowering.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetLowering.h?rev=193769&r1=193768&r2=193769&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetLowering.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetLowering.h Thu Oct 31 12:18:24 2013
> @@ -1920,6 +1920,8 @@ public:
>      ArgListEntry() : isSExt(false), isZExt(false), isInReg(false),
>        isSRet(false), isNest(false), isByVal(false), isReturned(false),
>        Alignment(0) { }
> +
> +    void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
>    };
>    typedef std::vector<ArgListEntry> ArgListTy;
>
>
> Modified: llvm/trunk/include/llvm/Target/TargetOpcodes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetOpcodes.h?rev=193769&r1=193768&r2=193769&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Target/TargetOpcodes.h (original)
> +++ llvm/trunk/include/llvm/Target/TargetOpcodes.h Thu Oct 31 12:18:24 2013
> @@ -92,7 +92,19 @@ namespace TargetOpcode {
>
>      /// Lifetime markers.
>      LIFETIME_START = 15,
> -    LIFETIME_END = 16
> +    LIFETIME_END = 16,
> +
> +    /// A Stackmap instruction captures the location of live variables at its
> +    /// position in the instruction stream. It is followed by a shadow of bytes
> +    /// that must lie within the function and not contain another stackmap.
> +    STACKMAP = 17,
> +
> +    /// Patchable call instruction - this instruction represents a call to a
> +    /// constant address, followed by a series of NOPs. It is intended to
> +    /// support optimizations for dynamic languages (such as javascript) that
> +    /// rewrite calls to runtimes with more efficient code sequences.
> +    /// This also implies a stack map.
> +    PATCHPOINT = 18
>    };
>  } // end namespace TargetOpcode
>  } // end namespace llvm
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp?rev=193769&r1=193768&r2=193769&view=diff
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp Thu Oct 31 12:18:24 2013
> @@ -5309,6 +5309,15 @@ SelectionDAGBuilder::visitIntrinsicCall(
>    case Intrinsic::donothing:
>      // ignore
>      return 0;
> +  case Intrinsic::experimental_stackmap: {
> +    visitStackmap(I);
> +    return 0;
> +  }
> +  case Intrinsic::experimental_patchpoint_void:
> +  case Intrinsic::experimental_patchpoint_i64: {
> +    visitPatchpoint(I);
> +    return 0;
> +  }
>    }
>  }
>
> @@ -5373,15 +5382,8 @@ void SelectionDAGBuilder::LowerCallTo(Im
>      SDValue ArgNode = getValue(V);
>      Entry.Node = ArgNode; Entry.Ty = V->getType();
>
> -    unsigned attrInd = i - CS.arg_begin() + 1;
> -    Entry.isSExt     = CS.paramHasAttr(attrInd, Attribute::SExt);
> -    Entry.isZExt     = CS.paramHasAttr(attrInd, Attribute::ZExt);
> -    Entry.isInReg    = CS.paramHasAttr(attrInd, Attribute::InReg);
> -    Entry.isSRet     = CS.paramHasAttr(attrInd, Attribute::StructRet);
> -    Entry.isNest     = CS.paramHasAttr(attrInd, Attribute::Nest);
> -    Entry.isByVal    = CS.paramHasAttr(attrInd, Attribute::ByVal);
> -    Entry.isReturned = CS.paramHasAttr(attrInd, Attribute::Returned);
> -    Entry.Alignment  = CS.getParamAlignment(attrInd);
> +    // Skip the first return-type Attribute to get to params.
> +    Entry.setAttributes(&CS, i - CS.arg_begin() + 1);
>      Args.push_back(Entry);
>    }
>
> @@ -5463,8 +5465,8 @@ void SelectionDAGBuilder::LowerCallTo(Im
>    }
>
>    if (!Result.second.getNode()) {
> -    // As a special case, a null chain means that a tail call has been emitted and
> -    // the DAG root is already updated.
> +    // As a special case, a null chain means that a tail call has been emitted
> +    // and the DAG root is already updated.
>      HasTailCall = true;
>
>      // Since there's no actual continuation from this block, nothing can be
> @@ -6721,6 +6723,189 @@ void SelectionDAGBuilder::visitVACopy(co
>                            DAG.getSrcValue(I.getArgOperand(1))));
>  }
>
> +/// \brief Lower an argument list according to the target calling convention.
> +///
> +/// \return A tuple of <return-value, token-chain>
> +///
> +/// This is a helper for lowering intrinsics that follow a target calling
> +/// convention or require stack pointer adjustment. Only a subset of the
> +/// intrinsic's operands need to participate in the calling convention.
> +std::pair<SDValue, SDValue>
> +SelectionDAGBuilder::LowerCallOperands(const CallInst &CI, unsigned ArgIdx,
> +                                       unsigned NumArgs, SDValue Callee) {
> +  TargetLowering::ArgListTy Args;
> +  Args.reserve(NumArgs);
> +
> +  // Populate the argument list.
> +  // Attributes for args start at offset 1, after the return attribute.
> +  ImmutableCallSite CS(&CI);
> +  for (unsigned ArgI = ArgIdx, ArgE = ArgIdx + NumArgs, AttrI = ArgIdx + 1;
> +       ArgI != ArgE; ++ArgI) {
> +    const Value *V = CI.getOperand(ArgI);
> +
> +    assert(!V->getType()->isEmptyTy() && "Empty type passed to intrinsic.");
> +
> +    TargetLowering::ArgListEntry Entry;
> +    Entry.Node = getValue(V);
> +    Entry.Ty = V->getType();
> +    Entry.setAttributes(&CS, AttrI);
> +    Args.push_back(Entry);
> +  }
> +
> +  TargetLowering::CallLoweringInfo CLI(getRoot(), CI.getType(),
> +    /*retSExt*/ false, /*retZExt*/ false, /*isVarArg*/ false, /*isInReg*/ false,
> +    NumArgs, CI.getCallingConv(), /*isTailCall*/ false, /*doesNotReturn*/ false,
> +    /*isReturnValueUsed*/ CI.use_empty(), Callee, Args, DAG, getCurSDLoc());
> +
> +  const TargetLowering *TLI = TM.getTargetLowering();
> +  return TLI->LowerCallTo(CLI);
> +}
> +
> +/// \brief Lower llvm.experimental.stackmap directly to its target opcode.
> +void SelectionDAGBuilder::visitStackmap(const CallInst &CI) {
> +  // void @llvm.experimental.stackmap(i32 <id>, i32 <numShadowBytes>,
> +  //                                  [live variables...])
> +
> +  assert(CI.getType()->isVoidTy() && "Stackmap cannot return a value.");
> +
> +  SDValue Callee = getValue(CI.getCalledValue());
> +
> +  // Lower into a call sequence with no args and no return value.
> +  std::pair<SDValue, SDValue> Result = LowerCallOperands(CI, 0, 0, Callee);
> +  // Set the root to the target-lowered call chain.
> +  SDValue Chain = Result.second;
> +  DAG.setRoot(Chain);
> +
> +  /// Get a call instruction from the call sequence chain.
> +  /// Tail calls are not allowed.
> +  SDNode *CallEnd = Chain.getNode();
> +  assert(CallEnd->getOpcode() == ISD::CALLSEQ_END &&
> +         "Expected a callseq node.");
> +  SDNode *Call = CallEnd->getOperand(0).getNode();
> +  bool hasGlue = Call->getGluedNode();
> +
> +  assert(Call->getNumOperands() == hasGlue ? 2 : 1 &&
> +         "Unexpected extra stackmap call arguments.");

This assert has an order of evaluation logic error in it, and so it
could never fire.  I fixed this in r193861, but the assert is now
firing on the build bots.  Can you look into the failure?

Thanks!

~Aaron



More information about the llvm-commits mailing list