//===- StatepointLowering.cpp - SDAGBuilder's statepoint code -------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file includes support code use by SelectionDAGBuilder when lowering a
// statepoint sequence in SelectionDAG IR.
//
//===----------------------------------------------------------------------===//

#include "StatepointLowering.h"
#include "SelectionDAGBuilder.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/FunctionLoweringInfo.h"
#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/ISDOpcodes.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/RuntimeLibcalls.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/StackMaps.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Statepoint.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/MachineValueType.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <tuple>
#include <utility>

using namespace llvm;

#define DEBUG_TYPE "statepoint-lowering"

STATISTIC(NumSlotsAllocatedForStatepoints,
          "Number of stack slots allocated for statepoints");
STATISTIC(NumOfStatepoints, "Number of statepoint nodes encountered");
STATISTIC(StatepointMaxSlotsRequired,
          "Maximum number of stack slots required for a singe statepoint");

cl::opt<bool> UseRegistersForDeoptValues(
    "use-registers-for-deopt-values", cl::Hidden, cl::init(false),
    cl::desc("Allow using registers for non pointer deopt args"));

cl::opt<bool> UseRegistersForGCPointersInLandingPad(
    "use-registers-for-gc-values-in-landing-pad", cl::Hidden, cl::init(false),
    cl::desc("Allow using registers for gc pointer in landing pad"));

cl::opt<unsigned> MaxRegistersForGCPointers(
    "max-registers-for-gc-values", cl::Hidden, cl::init(0),
    cl::desc("Max number of VRegs allowed to pass GC pointer meta args in"));

cl::opt<bool> AlwaysSpillBase("statepoint-always-spill-base", cl::Hidden,
                              cl::init(true),
                              cl::desc("Force spilling of base GC pointers"));

typedef FunctionLoweringInfo::StatepointRelocationRecord RecordType;

static void pushStackMapConstant(SmallVectorImpl<SDValue>& Ops,
                                 SelectionDAGBuilder &Builder, uint64_t Value) {
  SDLoc L = Builder.getCurSDLoc();
  Ops.push_back(Builder.DAG.getTargetConstant(StackMaps::ConstantOp, L,
                                              MVT::i64));
  Ops.push_back(Builder.DAG.getTargetConstant(Value, L, MVT::i64));
}

void StatepointLoweringState::startNewStatepoint(SelectionDAGBuilder &Builder) {
  // Consistency check
  assert(PendingGCRelocateCalls.empty() &&
         "Trying to visit statepoint before finished processing previous one");
  Locations.clear();
  NextSlotToAllocate = 0;
  // Need to resize this on each safepoint - we need the two to stay in sync and
  // the clear patterns of a SelectionDAGBuilder have no relation to
  // FunctionLoweringInfo.  Also need to ensure used bits get cleared.
  AllocatedStackSlots.clear();
  AllocatedStackSlots.resize(Builder.FuncInfo.StatepointStackSlots.size());
}

void StatepointLoweringState::clear() {
  Locations.clear();
  AllocatedStackSlots.clear();
  assert(PendingGCRelocateCalls.empty() &&
         "cleared before statepoint sequence completed");
}

SDValue
StatepointLoweringState::allocateStackSlot(EVT ValueType,
                                           SelectionDAGBuilder &Builder) {
  NumSlotsAllocatedForStatepoints++;
  MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();

  unsigned SpillSize = ValueType.getStoreSize();
  assert((SpillSize * 8) ==
             (-8u & (7 + ValueType.getSizeInBits())) && // Round up modulo 8.
         "Size not in bytes?");

  // First look for a previously created stack slot which is not in
  // use (accounting for the fact arbitrary slots may already be
  // reserved), or to create a new stack slot and use it.

  const size_t NumSlots = AllocatedStackSlots.size();
  assert(NextSlotToAllocate <= NumSlots && "Broken invariant");

  assert(AllocatedStackSlots.size() ==
         Builder.FuncInfo.StatepointStackSlots.size() &&
         "Broken invariant");

  for (; NextSlotToAllocate < NumSlots; NextSlotToAllocate++) {
    if (!AllocatedStackSlots.test(NextSlotToAllocate)) {
      const int FI = Builder.FuncInfo.StatepointStackSlots[NextSlotToAllocate];
      if (MFI.getObjectSize(FI) == SpillSize) {
        AllocatedStackSlots.set(NextSlotToAllocate);
        // TODO: Is ValueType the right thing to use here?
        return Builder.DAG.getFrameIndex(FI, ValueType);
      }
    }
  }

  // Couldn't find a free slot, so create a new one:

  SDValue SpillSlot = Builder.DAG.CreateStackTemporary(ValueType);
  const unsigned FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
  MFI.markAsStatepointSpillSlotObjectIndex(FI);

  Builder.FuncInfo.StatepointStackSlots.push_back(FI);
  AllocatedStackSlots.resize(AllocatedStackSlots.size()+1, true);
  assert(AllocatedStackSlots.size() ==
         Builder.FuncInfo.StatepointStackSlots.size() &&
         "Broken invariant");

  StatepointMaxSlotsRequired.updateMax(
      Builder.FuncInfo.StatepointStackSlots.size());

  return SpillSlot;
}

/// Utility function for reservePreviousStackSlotForValue. Tries to find
/// stack slot index to which we have spilled value for previous statepoints.
/// LookUpDepth specifies maximum DFS depth this function is allowed to look.
static Optional<int> findPreviousSpillSlot(const Value *Val,
                                           SelectionDAGBuilder &Builder,
                                           int LookUpDepth) {
  // Can not look any further - give up now
  if (LookUpDepth <= 0)
    return None;

  // Spill location is known for gc relocates
  if (const auto *Relocate = dyn_cast<GCRelocateInst>(Val)) {
    const auto &RelocationMap =
        Builder.FuncInfo.StatepointRelocationMaps[Relocate->getStatepoint()];

    auto It = RelocationMap.find(Relocate->getDerivedPtr());
    if (It == RelocationMap.end())
      return None;

    auto &Record = It->second;
    if (Record.type != RecordType::Spill)
      return None;

    return Record.payload.FI;
  }

  // Look through bitcast instructions.
  if (const BitCastInst *Cast = dyn_cast<BitCastInst>(Val))
    return findPreviousSpillSlot(Cast->getOperand(0), Builder, LookUpDepth - 1);

  // Look through phi nodes
  // All incoming values should have same known stack slot, otherwise result
  // is unknown.
  if (const PHINode *Phi = dyn_cast<PHINode>(Val)) {
    Optional<int> MergedResult = None;

    for (auto &IncomingValue : Phi->incoming_values()) {
      Optional<int> SpillSlot =
          findPreviousSpillSlot(IncomingValue, Builder, LookUpDepth - 1);
      if (!SpillSlot.hasValue())
        return None;

      if (MergedResult.hasValue() && *MergedResult != *SpillSlot)
        return None;

      MergedResult = SpillSlot;
    }
    return MergedResult;
  }

  // TODO: We can do better for PHI nodes. In cases like this:
  //   ptr = phi(relocated_pointer, not_relocated_pointer)
  //   statepoint(ptr)
  // We will return that stack slot for ptr is unknown. And later we might
  // assign different stack slots for ptr and relocated_pointer. This limits
  // llvm's ability to remove redundant stores.
  // Unfortunately it's hard to accomplish in current infrastructure.
  // We use this function to eliminate spill store completely, while
  // in example we still need to emit store, but instead of any location
  // we need to use special "preferred" location.

  // TODO: handle simple updates.  If a value is modified and the original
  // value is no longer live, it would be nice to put the modified value in the
  // same slot.  This allows folding of the memory accesses for some
  // instructions types (like an increment).
  //   statepoint (i)
  //   i1 = i+1
  //   statepoint (i1)
  // However we need to be careful for cases like this:
  //   statepoint(i)
  //   i1 = i+1
  //   statepoint(i, i1)
  // Here we want to reserve spill slot for 'i', but not for 'i+1'. If we just
  // put handling of simple modifications in this function like it's done
  // for bitcasts we might end up reserving i's slot for 'i+1' because order in
  // which we visit values is unspecified.

  // Don't know any information about this instruction
  return None;
}

/// Return true if-and-only-if the given SDValue can be lowered as either a
/// constant argument or a stack reference.  The key point is that the value
/// doesn't need to be spilled or tracked as a vreg use.
static bool willLowerDirectly(SDValue Incoming) {
  // We are making an unchecked assumption that the frame size <= 2^16 as that
  // is the largest offset which can be encoded in the stackmap format.
  if (isa<FrameIndexSDNode>(Incoming))
    return true;

  // The largest constant describeable in the StackMap format is 64 bits.
  // Potential Optimization:  Constants values are sign extended by consumer,
  // and thus there are many constants of static type > 64 bits whose value
  // happens to be sext(Con64) and could thus be lowered directly.
  if (Incoming.getValueType().getSizeInBits() > 64)
    return false;

  return (isa<ConstantSDNode>(Incoming) || isa<ConstantFPSDNode>(Incoming) ||
          Incoming.isUndef());
}

/// Try to find existing copies of the incoming values in stack slots used for
/// statepoint spilling.  If we can find a spill slot for the incoming value,
/// mark that slot as allocated, and reuse the same slot for this safepoint.
/// This helps to avoid series of loads and stores that only serve to reshuffle
/// values on the stack between calls.
static void reservePreviousStackSlotForValue(const Value *IncomingValue,
                                             SelectionDAGBuilder &Builder) {
  SDValue Incoming = Builder.getValue(IncomingValue);

  // If we won't spill this, we don't need to check for previously allocated
  // stack slots.
  if (willLowerDirectly(Incoming))
    return;

  SDValue OldLocation = Builder.StatepointLowering.getLocation(Incoming);
  if (OldLocation.getNode())
    // Duplicates in input
    return;

  const int LookUpDepth = 6;
  Optional<int> Index =
      findPreviousSpillSlot(IncomingValue, Builder, LookUpDepth);
  if (!Index.hasValue())
    return;

  const auto &StatepointSlots = Builder.FuncInfo.StatepointStackSlots;

  auto SlotIt = find(StatepointSlots, *Index);
  assert(SlotIt != StatepointSlots.end() &&
         "Value spilled to the unknown stack slot");

  // This is one of our dedicated lowering slots
  const int Offset = std::distance(StatepointSlots.begin(), SlotIt);
  if (Builder.StatepointLowering.isStackSlotAllocated(Offset)) {
    // stack slot already assigned to someone else, can't use it!
    // TODO: currently we reserve space for gc arguments after doing
    // normal allocation for deopt arguments.  We should reserve for
    // _all_ deopt and gc arguments, then start allocating.  This
    // will prevent some moves being inserted when vm state changes,
    // but gc state doesn't between two calls.
    return;
  }
  // Reserve this stack slot
  Builder.StatepointLowering.reserveStackSlot(Offset);

  // Cache this slot so we find it when going through the normal
  // assignment loop.
  SDValue Loc =
      Builder.DAG.getTargetFrameIndex(*Index, Builder.getFrameIndexTy());
  Builder.StatepointLowering.setLocation(Incoming, Loc);
}

/// Extract call from statepoint, lower it and return pointer to the
/// call node. Also update NodeMap so that getValue(statepoint) will
/// reference lowered call result
static std::pair<SDValue, SDNode *> lowerCallFromStatepointLoweringInfo(
    SelectionDAGBuilder::StatepointLoweringInfo &SI,
    SelectionDAGBuilder &Builder, SmallVectorImpl<SDValue> &PendingExports) {
  SDValue ReturnValue, CallEndVal;
  std::tie(ReturnValue, CallEndVal) =
      Builder.lowerInvokable(SI.CLI, SI.EHPadBB);
  SDNode *CallEnd = CallEndVal.getNode();

  // Get a call instruction from the call sequence chain.  Tail calls are not
  // allowed.  The following code is essentially reverse engineering X86's
  // LowerCallTo.
  //
  // We are expecting DAG to have the following form:
  //
  // ch = eh_label (only in case of invoke statepoint)
  //   ch, glue = callseq_start ch
  //   ch, glue = X86::Call ch, glue
  //   ch, glue = callseq_end ch, glue
  //   get_return_value ch, glue
  //
  // get_return_value can either be a sequence of CopyFromReg instructions
  // to grab the return value from the return register(s), or it can be a LOAD
  // to load a value returned by reference via a stack slot.

  bool HasDef = !SI.CLI.RetTy->isVoidTy();
  if (HasDef) {
    if (CallEnd->getOpcode() == ISD::LOAD)
      CallEnd = CallEnd->getOperand(0).getNode();
    else
      while (CallEnd->getOpcode() == ISD::CopyFromReg)
        CallEnd = CallEnd->getOperand(0).getNode();
  }

  assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && "expected!");
  return std::make_pair(ReturnValue, CallEnd->getOperand(0).getNode());
}

static MachineMemOperand* getMachineMemOperand(MachineFunction &MF,
                                               FrameIndexSDNode &FI) {
  auto PtrInfo = MachinePointerInfo::getFixedStack(MF, FI.getIndex());
  auto MMOFlags = MachineMemOperand::MOStore |
    MachineMemOperand::MOLoad | MachineMemOperand::MOVolatile;
  auto &MFI = MF.getFrameInfo();
  return MF.getMachineMemOperand(PtrInfo, MMOFlags,
                                 MFI.getObjectSize(FI.getIndex()),
                                 MFI.getObjectAlign(FI.getIndex()));
}

/// Spill a value incoming to the statepoint. It might be either part of
/// vmstate
/// or gcstate. In both cases unconditionally spill it on the stack unless it
/// is a null constant. Return pair with first element being frame index
/// containing saved value and second element with outgoing chain from the
/// emitted store
static std::tuple<SDValue, SDValue, MachineMemOperand*>
spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
                             SelectionDAGBuilder &Builder) {
  SDValue Loc = Builder.StatepointLowering.getLocation(Incoming);
  MachineMemOperand* MMO = nullptr;

  // Emit new store if we didn't do it for this ptr before
  if (!Loc.getNode()) {
    Loc = Builder.StatepointLowering.allocateStackSlot(Incoming.getValueType(),
                                                       Builder);
    int Index = cast<FrameIndexSDNode>(Loc)->getIndex();
    // We use TargetFrameIndex so that isel will not select it into LEA
    Loc = Builder.DAG.getTargetFrameIndex(Index, Builder.getFrameIndexTy());

    // Right now we always allocate spill slots that are of the same
    // size as the value we're about to spill (the size of spillee can
    // vary since we spill vectors of pointers too).  At some point we
    // can consider allowing spills of smaller values to larger slots
    // (i.e. change the '==' in the assert below to a '>=').
    MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();
    assert((MFI.getObjectSize(Index) * 8) ==
               (-8 & (7 + // Round up modulo 8.
                      (int64_t)Incoming.getValueSizeInBits())) &&
           "Bad spill:  stack slot does not match!");

    // Note: Using the alignment of the spill slot (rather than the abi or
    // preferred alignment) is required for correctness when dealing with spill
    // slots with preferred alignments larger than frame alignment..
    auto &MF = Builder.DAG.getMachineFunction();
    auto PtrInfo = MachinePointerInfo::getFixedStack(MF, Index);
    auto *StoreMMO = MF.getMachineMemOperand(
        PtrInfo, MachineMemOperand::MOStore, MFI.getObjectSize(Index),
        MFI.getObjectAlign(Index));
    Chain = Builder.DAG.getStore(Chain, Builder.getCurSDLoc(), Incoming, Loc,
                                 StoreMMO);

    MMO = getMachineMemOperand(MF, *cast<FrameIndexSDNode>(Loc));

    Builder.StatepointLowering.setLocation(Incoming, Loc);
  }

  assert(Loc.getNode());
  return std::make_tuple(Loc, Chain, MMO);
}

/// Lower a single value incoming to a statepoint node.  This value can be
/// either a deopt value or a gc value, the handling is the same.  We special
/// case constants and allocas, then fall back to spilling if required.
static void
lowerIncomingStatepointValue(SDValue Incoming, bool RequireSpillSlot,
                             SmallVectorImpl<SDValue> &Ops,
                             SmallVectorImpl<MachineMemOperand *> &MemRefs,
                             SelectionDAGBuilder &Builder) {
  
  if (willLowerDirectly(Incoming)) {
    if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Incoming)) {
      // This handles allocas as arguments to the statepoint (this is only
      // really meaningful for a deopt value.  For GC, we'd be trying to
      // relocate the address of the alloca itself?)
      assert(Incoming.getValueType() == Builder.getFrameIndexTy() &&
             "Incoming value is a frame index!");
      Ops.push_back(Builder.DAG.getTargetFrameIndex(FI->getIndex(),
                                                    Builder.getFrameIndexTy()));

      auto &MF = Builder.DAG.getMachineFunction();
      auto *MMO = getMachineMemOperand(MF, *FI);
      MemRefs.push_back(MMO);
      return;
    }

    assert(Incoming.getValueType().getSizeInBits() <= 64);
    
    if (Incoming.isUndef()) {
      // Put an easily recognized constant that's unlikely to be a valid
      // value so that uses of undef by the consumer of the stackmap is
      // easily recognized. This is legal since the compiler is always
      // allowed to chose an arbitrary value for undef.
      pushStackMapConstant(Ops, Builder, 0xFEFEFEFE);
      return;
    }

    // If the original value was a constant, make sure it gets recorded as
    // such in the stackmap.  This is required so that the consumer can
    // parse any internal format to the deopt state.  It also handles null
    // pointers and other constant pointers in GC states.
    if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Incoming)) {
      pushStackMapConstant(Ops, Builder, C->getSExtValue());
      return;
    } else if (ConstantFPSDNode *C = dyn_cast<ConstantFPSDNode>(Incoming)) {
      pushStackMapConstant(Ops, Builder,
                           C->getValueAPF().bitcastToAPInt().getZExtValue());
      return;
    }

    llvm_unreachable("unhandled direct lowering case");
  }



  if (!RequireSpillSlot) {
    // If this value is live in (not live-on-return, or live-through), we can
    // treat it the same way patchpoint treats it's "live in" values.  We'll
    // end up folding some of these into stack references, but they'll be
    // handled by the register allocator.  Note that we do not have the notion
    // of a late use so these values might be placed in registers which are
    // clobbered by the call.  This is fine for live-in. For live-through
    // fix-up pass should be executed to force spilling of such registers.
    Ops.push_back(Incoming);
  } else {
    // Otherwise, locate a spill slot and explicitly spill it so it can be
    // found by the runtime later.  Note: We know all of these spills are
    // independent, but don't bother to exploit that chain wise.  DAGCombine
    // will happily do so as needed, so doing it here would be a small compile
    // time win at most. 
    SDValue Chain = Builder.getRoot();
    auto Res = spillIncomingStatepointValue(Incoming, Chain, Builder);
    Ops.push_back(std::get<0>(Res));
    if (auto *MMO = std::get<2>(Res))
      MemRefs.push_back(MMO);
    Chain = std::get<1>(Res);;
    Builder.DAG.setRoot(Chain);
  }

}

/// Return true if value V represents the GC value. The behavior is conservative
/// in case it is not sure that value is not GC the function returns true.
static bool isGCValue(const Value *V, SelectionDAGBuilder &Builder) {
  auto *Ty = V->getType();
  if (!Ty->isPtrOrPtrVectorTy())
    return false;
  if (auto *GFI = Builder.GFI)
    if (auto IsManaged = GFI->getStrategy().isGCManagedPointer(Ty))
      return *IsManaged;
  return true; // conservative
}

/// Lower deopt state and gc pointer arguments of the statepoint.  The actual
/// lowering is described in lowerIncomingStatepointValue.  This function is
/// responsible for lowering everything in the right position and playing some
/// tricks to avoid redundant stack manipulation where possible.  On
/// completion, 'Ops' will contain ready to use operands for machine code
/// statepoint. The chain nodes will have already been created and the DAG root
/// will be set to the last value spilled (if any were).
static void
lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
                        SmallVectorImpl<MachineMemOperand *> &MemRefs,
                        SmallVectorImpl<SDValue> &GCPtrs,
                        DenseMap<SDValue, int> &LowerAsVReg,
                        SelectionDAGBuilder::StatepointLoweringInfo &SI,
                        SelectionDAGBuilder &Builder) {
  // Lower the deopt and gc arguments for this statepoint.  Layout will be:
  // deopt argument length, deopt arguments.., gc arguments...
#ifndef NDEBUG
  if (auto *GFI = Builder.GFI) {
    // Check that each of the gc pointer and bases we've gotten out of the
    // safepoint is something the strategy thinks might be a pointer (or vector
    // of pointers) into the GC heap.  This is basically just here to help catch
    // errors during statepoint insertion. TODO: This should actually be in the
    // Verifier, but we can't get to the GCStrategy from there (yet).
    GCStrategy &S = GFI->getStrategy();
    for (const Value *V : SI.Bases) {
      auto Opt = S.isGCManagedPointer(V->getType()->getScalarType());
      if (Opt.hasValue()) {
        assert(Opt.getValue() &&
               "non gc managed base pointer found in statepoint");
      }
    }
    for (const Value *V : SI.Ptrs) {
      auto Opt = S.isGCManagedPointer(V->getType()->getScalarType());
      if (Opt.hasValue()) {
        assert(Opt.getValue() &&
               "non gc managed derived pointer found in statepoint");
      }
    }
    assert(SI.Bases.size() == SI.Ptrs.size() && "Pointer without base!");
  } else {
    assert(SI.Bases.empty() && "No gc specified, so cannot relocate pointers!");
    assert(SI.Ptrs.empty() && "No gc specified, so cannot relocate pointers!");
  }
#endif

  // Figure out what lowering strategy we're going to use for each part
  // Note: Is is conservatively correct to lower both "live-in" and "live-out"
  // as "live-through". A "live-through" variable is one which is "live-in",
  // "live-out", and live throughout the lifetime of the call (i.e. we can find
  // it from any PC within the transitive callee of the statepoint).  In
  // particular, if the callee spills callee preserved registers we may not
  // be able to find a value placed in that register during the call.  This is
  // fine for live-out, but not for live-through.  If we were willing to make
  // assumptions about the code generator producing the callee, we could
  // potentially allow live-through values in callee saved registers.
  const bool LiveInDeopt =
    SI.StatepointFlags & (uint64_t)StatepointFlags::DeoptLiveIn;

  // Decide which deriver pointers will go on VRegs
  unsigned MaxVRegPtrs = MaxRegistersForGCPointers.getValue();

  // Pointers used on exceptional path of invoke statepoint.
  // We cannot assing them to VRegs.
  SmallSet<SDValue, 8> LPadPointers;
  if (!UseRegistersForGCPointersInLandingPad)
    if (auto *StInvoke = dyn_cast_or_null<InvokeInst>(SI.StatepointInstr)) {
      LandingPadInst *LPI = StInvoke->getLandingPadInst();
      for (auto *Relocate : SI.GCRelocates)
        if (Relocate->getOperand(0) == LPI) {
          LPadPointers.insert(Builder.getValue(Relocate->getBasePtr()));
          LPadPointers.insert(Builder.getValue(Relocate->getDerivedPtr()));
        }
    }

  LLVM_DEBUG(dbgs() << "Deciding how to lower GC Pointers:\n");

  // List of unique lowered GC Pointer values.
  SmallSetVector<SDValue, 16> LoweredGCPtrs;
  // Map lowered GC Pointer value to the index in above vector
  DenseMap<SDValue, unsigned> GCPtrIndexMap;

  unsigned CurNumVRegs = 0;

  auto canPassGCPtrOnVReg = [&](SDValue SD) {
    if (SD.getValueType().isVector())
      return false;
    if (LPadPointers.count(SD))
      return false;
    return !willLowerDirectly(SD);
  };

  auto processGCPtr = [&](const Value *V) {
    SDValue PtrSD = Builder.getValue(V);
    if (!LoweredGCPtrs.insert(PtrSD))
      return; // skip duplicates
    GCPtrIndexMap[PtrSD] = LoweredGCPtrs.size() - 1;

    assert(!LowerAsVReg.count(PtrSD) && "must not have been seen");
    if (LowerAsVReg.size() == MaxVRegPtrs)
      return;
    assert(V->getType()->isVectorTy() == PtrSD.getValueType().isVector() &&
           "IR and SD types disagree");
    if (!canPassGCPtrOnVReg(PtrSD)) {
      LLVM_DEBUG(dbgs() << "direct/spill "; PtrSD.dump(&Builder.DAG));
      return;
    }
    LLVM_DEBUG(dbgs() << "vreg "; PtrSD.dump(&Builder.DAG));
    LowerAsVReg[PtrSD] = CurNumVRegs++;
  };

  // Process derived pointers first to give them more chance to go on VReg.
  for (const Value *V : SI.Ptrs)
    processGCPtr(V);
  for (const Value *V : SI.Bases)
    processGCPtr(V);

  LLVM_DEBUG(dbgs() << LowerAsVReg.size() << " pointers will go in vregs\n");

  auto requireSpillSlot = [&](const Value *V) {
    if (!Builder.DAG.getTargetLoweringInfo().isTypeLegal(
             Builder.getValue(V).getValueType()))
      return true;
    if (isGCValue(V, Builder))
      return !LowerAsVReg.count(Builder.getValue(V));
    return !(LiveInDeopt || UseRegistersForDeoptValues);
  };

  // Before we actually start lowering (and allocating spill slots for values),
  // reserve any stack slots which we judge to be profitable to reuse for a
  // particular value.  This is purely an optimization over the code below and
  // doesn't change semantics at all.  It is important for performance that we
  // reserve slots for both deopt and gc values before lowering either.
  for (const Value *V : SI.DeoptState) {
    if (requireSpillSlot(V))
      reservePreviousStackSlotForValue(V, Builder);
  }

  for (const Value *V : SI.Ptrs) {
    SDValue SDV = Builder.getValue(V);
    if (!LowerAsVReg.count(SDV))
      reservePreviousStackSlotForValue(V, Builder);
  }

  for (const Value *V : SI.Bases) {
    SDValue SDV = Builder.getValue(V);
    if (!LowerAsVReg.count(SDV))
      reservePreviousStackSlotForValue(V, Builder);
  }

  // First, prefix the list with the number of unique values to be
  // lowered.  Note that this is the number of *Values* not the
  // number of SDValues required to lower them.
  const int NumVMSArgs = SI.DeoptState.size();
  pushStackMapConstant(Ops, Builder, NumVMSArgs);

  // The vm state arguments are lowered in an opaque manner.  We do not know
  // what type of values are contained within.
  LLVM_DEBUG(dbgs() << "Lowering deopt state\n");
  for (const Value *V : SI.DeoptState) {
    SDValue Incoming;
    // If this is a function argument at a static frame index, generate it as
    // the frame index.
    if (const Argument *Arg = dyn_cast<Argument>(V)) {
      int FI = Builder.FuncInfo.getArgumentFrameIndex(Arg);
      if (FI != INT_MAX)
        Incoming = Builder.DAG.getFrameIndex(FI, Builder.getFrameIndexTy());
    }
    if (!Incoming.getNode())
      Incoming = Builder.getValue(V);
    LLVM_DEBUG(dbgs() << "Value " << *V
                      << " requireSpillSlot = " << requireSpillSlot(V) << "\n");
    lowerIncomingStatepointValue(Incoming, requireSpillSlot(V), Ops, MemRefs,
                                 Builder);
  }

  // Finally, go ahead and lower all the gc arguments.
  pushStackMapConstant(Ops, Builder, LoweredGCPtrs.size());
  for (SDValue SDV : LoweredGCPtrs)
    lowerIncomingStatepointValue(SDV, !LowerAsVReg.count(SDV), Ops, MemRefs,
                                 Builder);

  // Copy to out vector. LoweredGCPtrs will be empty after this point.
  GCPtrs = LoweredGCPtrs.takeVector();

  // If there are any explicit spill slots passed to the statepoint, record
  // them, but otherwise do not do anything special.  These are user provided
  // allocas and give control over placement to the consumer.  In this case,
  // it is the contents of the slot which may get updated, not the pointer to
  // the alloca
  SmallVector<SDValue, 4> Allocas;
  for (Value *V : SI.GCArgs) {
    SDValue Incoming = Builder.getValue(V);
    if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Incoming)) {
      // This handles allocas as arguments to the statepoint
      assert(Incoming.getValueType() == Builder.getFrameIndexTy() &&
             "Incoming value is a frame index!");
      Allocas.push_back(Builder.DAG.getTargetFrameIndex(
          FI->getIndex(), Builder.getFrameIndexTy()));

      auto &MF = Builder.DAG.getMachineFunction();
      auto *MMO = getMachineMemOperand(MF, *FI);
      MemRefs.push_back(MMO);
    }
  }
  pushStackMapConstant(Ops, Builder, Allocas.size());
  Ops.append(Allocas.begin(), Allocas.end());

  // Now construct GC base/derived map;
  pushStackMapConstant(Ops, Builder, SI.Ptrs.size());
  SDLoc L = Builder.getCurSDLoc();
  for (unsigned i = 0; i < SI.Ptrs.size(); ++i) {
    SDValue Base = Builder.getValue(SI.Bases[i]);
    assert(GCPtrIndexMap.count(Base) && "base not found in index map");
    Ops.push_back(
        Builder.DAG.getTargetConstant(GCPtrIndexMap[Base], L, MVT::i64));
    SDValue Derived = Builder.getValue(SI.Ptrs[i]);
    assert(GCPtrIndexMap.count(Derived) && "derived not found in index map");
    Ops.push_back(
        Builder.DAG.getTargetConstant(GCPtrIndexMap[Derived], L, MVT::i64));
  }
}

SDValue SelectionDAGBuilder::LowerAsSTATEPOINT(
    SelectionDAGBuilder::StatepointLoweringInfo &SI) {
  // The basic scheme here is that information about both the original call and
  // the safepoint is encoded in the CallInst.  We create a temporary call and
  // lower it, then reverse engineer the calling sequence.

  NumOfStatepoints++;
  // Clear state
  StatepointLowering.startNewStatepoint(*this);
  assert(SI.Bases.size() == SI.Ptrs.size());

  LLVM_DEBUG(dbgs() << "Lowering statepoint " << *SI.StatepointInstr << "\n");
#ifndef NDEBUG
  for (auto *Reloc : SI.GCRelocates)
    if (Reloc->getParent() == SI.StatepointInstr->getParent())
      StatepointLowering.scheduleRelocCall(*Reloc);
#endif

  // Lower statepoint vmstate and gcstate arguments

  // All lowered meta args.
  SmallVector<SDValue, 10> LoweredMetaArgs;
  // Lowered GC pointers (subset of above).
  SmallVector<SDValue, 16> LoweredGCArgs;
  SmallVector<MachineMemOperand*, 16> MemRefs;
  // Maps derived pointer SDValue to statepoint result of relocated pointer.
  DenseMap<SDValue, int> LowerAsVReg;
  lowerStatepointMetaArgs(LoweredMetaArgs, MemRefs, LoweredGCArgs, LowerAsVReg,
                          SI, *this);

  // Now that we've emitted the spills, we need to update the root so that the
  // call sequence is ordered correctly.
  SI.CLI.setChain(getRoot());

  // Get call node, we will replace it later with statepoint
  SDValue ReturnVal;
  SDNode *CallNode;
  std::tie(ReturnVal, CallNode) =
      lowerCallFromStatepointLoweringInfo(SI, *this, PendingExports);

  // Construct the actual GC_TRANSITION_START, STATEPOINT, and GC_TRANSITION_END
  // nodes with all the appropriate arguments and return values.

  // Call Node: Chain, Target, {Args}, RegMask, [Glue]
  SDValue Chain = CallNode->getOperand(0);

  SDValue Glue;
  bool CallHasIncomingGlue = CallNode->getGluedNode();
  if (CallHasIncomingGlue) {
    // Glue is always last operand
    Glue = CallNode->getOperand(CallNode->getNumOperands() - 1);
  }

  // Build the GC_TRANSITION_START node if necessary.
  //
  // The operands to the GC_TRANSITION_{START,END} nodes are laid out in the
  // order in which they appear in the call to the statepoint intrinsic. If
  // any of the operands is a pointer-typed, that operand is immediately
  // followed by a SRCVALUE for the pointer that may be used during lowering
  // (e.g. to form MachinePointerInfo values for loads/stores).
  const bool IsGCTransition =
      (SI.StatepointFlags & (uint64_t)StatepointFlags::GCTransition) ==
      (uint64_t)StatepointFlags::GCTransition;
  if (IsGCTransition) {
    SmallVector<SDValue, 8> TSOps;

    // Add chain
    TSOps.push_back(Chain);

    // Add GC transition arguments
    for (const Value *V : SI.GCTransitionArgs) {
      TSOps.push_back(getValue(V));
      if (V->getType()->isPointerTy())
        TSOps.push_back(DAG.getSrcValue(V));
    }

    // Add glue if necessary
    if (CallHasIncomingGlue)
      TSOps.push_back(Glue);

    SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);

    SDValue GCTransitionStart =
        DAG.getNode(ISD::GC_TRANSITION_START, getCurSDLoc(), NodeTys, TSOps);

    Chain = GCTransitionStart.getValue(0);
    Glue = GCTransitionStart.getValue(1);
  }

  // TODO: Currently, all of these operands are being marked as read/write in
  // PrologEpilougeInserter.cpp, we should special case the VMState arguments
  // and flags to be read-only.
  SmallVector<SDValue, 40> Ops;

  // Add the <id> and <numBytes> constants.
  Ops.push_back(DAG.getTargetConstant(SI.ID, getCurSDLoc(), MVT::i64));
  Ops.push_back(
      DAG.getTargetConstant(SI.NumPatchBytes, getCurSDLoc(), MVT::i32));

  // Calculate and push starting position of vmstate arguments
  // Get number of arguments incoming directly into call node
  unsigned NumCallRegArgs =
      CallNode->getNumOperands() - (CallHasIncomingGlue ? 4 : 3);
  Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, getCurSDLoc(), MVT::i32));

  // Add call target
  SDValue CallTarget = SDValue(CallNode->getOperand(1).getNode(), 0);
  Ops.push_back(CallTarget);

  // Add call arguments
  // Get position of register mask in the call
  SDNode::op_iterator RegMaskIt;
  if (CallHasIncomingGlue)
    RegMaskIt = CallNode->op_end() - 2;
  else
    RegMaskIt = CallNode->op_end() - 1;
  Ops.insert(Ops.end(), CallNode->op_begin() + 2, RegMaskIt);

  // Add a constant argument for the calling convention
  pushStackMapConstant(Ops, *this, SI.CLI.CallConv);

  // Add a constant argument for the flags
  uint64_t Flags = SI.StatepointFlags;
  assert(((Flags & ~(uint64_t)StatepointFlags::MaskAll) == 0) &&
         "Unknown flag used");
  pushStackMapConstant(Ops, *this, Flags);

  // Insert all vmstate and gcstate arguments
  llvm::append_range(Ops, LoweredMetaArgs);

  // Add register mask from call node
  Ops.push_back(*RegMaskIt);

  // Add chain
  Ops.push_back(Chain);

  // Same for the glue, but we add it only if original call had it
  if (Glue.getNode())
    Ops.push_back(Glue);

  // Compute return values.  Provide a glue output since we consume one as
  // input.  This allows someone else to chain off us as needed.
  SmallVector<EVT, 8> NodeTys;
  for (auto SD : LoweredGCArgs) {
    if (!LowerAsVReg.count(SD))
      continue;
    NodeTys.push_back(SD.getValueType());
  }
  LLVM_DEBUG(dbgs() << "Statepoint has " << NodeTys.size() << " results\n");
  assert(NodeTys.size() == LowerAsVReg.size() && "Inconsistent GC Ptr lowering");
  NodeTys.push_back(MVT::Other);
  NodeTys.push_back(MVT::Glue);

  unsigned NumResults = NodeTys.size();
  MachineSDNode *StatepointMCNode =
    DAG.getMachineNode(TargetOpcode::STATEPOINT, getCurSDLoc(), NodeTys, Ops);
  DAG.setNodeMemRefs(StatepointMCNode, MemRefs);

  // For values lowered to tied-defs, create the virtual registers.  Note that
  // for simplicity, we *always* create a vreg even within a single block.
  DenseMap<SDValue, Register> VirtRegs;
  for (const auto *Relocate : SI.GCRelocates) {
    Value *Derived = Relocate->getDerivedPtr();
    SDValue SD = getValue(Derived);
    if (!LowerAsVReg.count(SD))
      continue;

    // Handle multiple gc.relocates of the same input efficiently.
    if (VirtRegs.count(SD))
      continue;

    SDValue Relocated = SDValue(StatepointMCNode, LowerAsVReg[SD]);

    auto *RetTy = Relocate->getType();
    Register Reg = FuncInfo.CreateRegs(RetTy);
    RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),
                     DAG.getDataLayout(), Reg, RetTy, None);
    SDValue Chain = DAG.getRoot();
    RFV.getCopyToRegs(Relocated, DAG, getCurSDLoc(), Chain, nullptr);
    PendingExports.push_back(Chain);

    VirtRegs[SD] = Reg;
  }

  // Record for later use how each relocation was lowered.  This is needed to
  // allow later gc.relocates to mirror the lowering chosen.
  const Instruction *StatepointInstr = SI.StatepointInstr;
  auto &RelocationMap = FuncInfo.StatepointRelocationMaps[StatepointInstr];
  for (const GCRelocateInst *Relocate : SI.GCRelocates) {
    const Value *V = Relocate->getDerivedPtr();
    SDValue SDV = getValue(V);
    SDValue Loc = StatepointLowering.getLocation(SDV);

    RecordType Record;
    if (LowerAsVReg.count(SDV)) {
      Record.type = RecordType::VReg;
      assert(VirtRegs.count(SDV));
      Record.payload.Reg = VirtRegs[SDV];
    } else if (Loc.getNode()) {
      Record.type = RecordType::Spill;
      Record.payload.FI = cast<FrameIndexSDNode>(Loc)->getIndex();
    } else {
      Record.type = RecordType::NoRelocate;
      // If we didn't relocate a value, we'll essentialy end up inserting an
      // additional use of the original value when lowering the gc.relocate.
      // We need to make sure the value is available at the new use, which
      // might be in another block.
      if (Relocate->getParent() != StatepointInstr->getParent())
        ExportFromCurrentBlock(V);
    }
    RelocationMap[V] = Record;
  }

  

  SDNode *SinkNode = StatepointMCNode;

  // Build the GC_TRANSITION_END node if necessary.
  //
  // See the comment above regarding GC_TRANSITION_START for the layout of
  // the operands to the GC_TRANSITION_END node.
  if (IsGCTransition) {
    SmallVector<SDValue, 8> TEOps;

    // Add chain
    TEOps.push_back(SDValue(StatepointMCNode, NumResults - 2));

    // Add GC transition arguments
    for (const Value *V : SI.GCTransitionArgs) {
      TEOps.push_back(getValue(V));
      if (V->getType()->isPointerTy())
        TEOps.push_back(DAG.getSrcValue(V));
    }

    // Add glue
    TEOps.push_back(SDValue(StatepointMCNode, NumResults - 1));

    SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);

    SDValue GCTransitionStart =
        DAG.getNode(ISD::GC_TRANSITION_END, getCurSDLoc(), NodeTys, TEOps);

    SinkNode = GCTransitionStart.getNode();
  }

  // Replace original call
  // Call: ch,glue = CALL ...
  // Statepoint: [gc relocates],ch,glue = STATEPOINT ...
  unsigned NumSinkValues = SinkNode->getNumValues();
  SDValue StatepointValues[2] = {SDValue(SinkNode, NumSinkValues - 2),
                                 SDValue(SinkNode, NumSinkValues - 1)};
  DAG.ReplaceAllUsesWith(CallNode, StatepointValues);
  // Remove original call node
  DAG.DeleteNode(CallNode);

  // Since we always emit CopyToRegs (even for local relocates), we must
  // update root, so that they are emitted before any local uses.
  (void)getControlRoot();

  // TODO: A better future implementation would be to emit a single variable
  // argument, variable return value STATEPOINT node here and then hookup the
  // return value of each gc.relocate to the respective output of the
  // previously emitted STATEPOINT value.  Unfortunately, this doesn't appear
  // to actually be possible today.

  return ReturnVal;
}

void
SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
                                     const BasicBlock *EHPadBB /*= nullptr*/) {
  assert(I.getCallingConv() != CallingConv::AnyReg &&
         "anyregcc is not supported on statepoints!");

#ifndef NDEBUG
  // Check that the associated GCStrategy expects to encounter statepoints.
  assert(GFI->getStrategy().useStatepoints() &&
         "GCStrategy does not expect to encounter statepoints");
#endif

  SDValue ActualCallee;
  SDValue Callee = getValue(I.getActualCalledOperand());

  if (I.getNumPatchBytes() > 0) {
    // If we've been asked to emit a nop sequence instead of a call instruction
    // for this statepoint then don't lower the call target, but use a constant
    // `undef` instead.  Not lowering the call target lets statepoint clients
    // get away without providing a physical address for the symbolic call
    // target at link time.
    ActualCallee = DAG.getUNDEF(Callee.getValueType());
  } else {
    ActualCallee = Callee;
  }

  StatepointLoweringInfo SI(DAG);
  populateCallLoweringInfo(SI.CLI, &I, GCStatepointInst::CallArgsBeginPos,
                           I.getNumCallArgs(), ActualCallee,
                           I.getActualReturnType(), false /* IsPatchPoint */);

  // There may be duplication in the gc.relocate list; such as two copies of
  // each relocation on normal and exceptional path for an invoke.  We only
  // need to spill once and record one copy in the stackmap, but we need to
  // reload once per gc.relocate.  (Dedupping gc.relocates is trickier and best
  // handled as a CSE problem elsewhere.)
  // TODO: There a couple of major stackmap size optimizations we could do
  // here if we wished.
  // 1) If we've encountered a derived pair {B, D}, we don't need to actually
  // record {B,B} if it's seen later.
  // 2) Due to rematerialization, actual derived pointers are somewhat rare;
  // given that, we could change the format to record base pointer relocations
  // separately with half the space. This would require a format rev and a
  // fairly major rework of the STATEPOINT node though.
  SmallSet<SDValue, 8> Seen;
  for (const GCRelocateInst *Relocate : I.getGCRelocates()) {
    SI.GCRelocates.push_back(Relocate);

    SDValue DerivedSD = getValue(Relocate->getDerivedPtr());
    if (Seen.insert(DerivedSD).second) {
      SI.Bases.push_back(Relocate->getBasePtr());
      SI.Ptrs.push_back(Relocate->getDerivedPtr());
    }
  }

  // If we find a deopt value which isn't explicitly added, we need to
  // ensure it gets lowered such that gc cycles occurring before the
  // deoptimization event during the lifetime of the call don't invalidate
  // the pointer we're deopting with.  Note that we assume that all
  // pointers passed to deopt are base pointers; relaxing that assumption
  // would require relatively large changes to how we represent relocations.
  for (Value *V : I.deopt_operands()) {
    if (!isGCValue(V, *this))
      continue;
    if (Seen.insert(getValue(V)).second) {
      SI.Bases.push_back(V);
      SI.Ptrs.push_back(V);
    }
  }

  SI.GCArgs = ArrayRef<const Use>(I.gc_args_begin(), I.gc_args_end());
  SI.StatepointInstr = &I;
  SI.ID = I.getID();

  SI.DeoptState = ArrayRef<const Use>(I.deopt_begin(), I.deopt_end());
  SI.GCTransitionArgs = ArrayRef<const Use>(I.gc_transition_args_begin(),
                                            I.gc_transition_args_end());

  SI.StatepointFlags = I.getFlags();
  SI.NumPatchBytes = I.getNumPatchBytes();
  SI.EHPadBB = EHPadBB;

  SDValue ReturnValue = LowerAsSTATEPOINT(SI);

  // Export the result value if needed
  const std::pair<bool, bool> GCResultLocality = I.getGCResultLocality();
  Type *RetTy = I.getActualReturnType();

  if (RetTy->isVoidTy() ||
      (!GCResultLocality.first && !GCResultLocality.second)) {
    // The return value is not needed, just generate a poison value. 
    setValue(&I, DAG.getIntPtrConstant(-1, getCurSDLoc()));
    return;
  }

  if (GCResultLocality.first) {
    // Result value will be used in a same basic block. Don't export it or
    // perform any explicit register copies. The gc_result will simply grab
    // this value. 
    setValue(&I, ReturnValue);
  }

  if (!GCResultLocality.second)
    return;
  // Result value will be used in a different basic block so we need to export
  // it now.  Default exporting mechanism will not work here because statepoint
  // call has a different type than the actual call. It means that by default
  // llvm will create export register of the wrong type (always i32 in our
  // case). So instead we need to create export register with correct type
  // manually.
  // TODO: To eliminate this problem we can remove gc.result intrinsics
  //       completely and make statepoint call to return a tuple.
  unsigned Reg = FuncInfo.CreateRegs(RetTy);
  RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),
                   DAG.getDataLayout(), Reg, RetTy,
                   I.getCallingConv());
  SDValue Chain = DAG.getEntryNode();
  
  RFV.getCopyToRegs(ReturnValue, DAG, getCurSDLoc(), Chain, nullptr);
  PendingExports.push_back(Chain);
  FuncInfo.ValueMap[&I] = Reg;
}

void SelectionDAGBuilder::LowerCallSiteWithDeoptBundleImpl(
    const CallBase *Call, SDValue Callee, const BasicBlock *EHPadBB,
    bool VarArgDisallowed, bool ForceVoidReturnTy) {
  StatepointLoweringInfo SI(DAG);
  unsigned ArgBeginIndex = Call->arg_begin() - Call->op_begin();
  populateCallLoweringInfo(
      SI.CLI, Call, ArgBeginIndex, Call->getNumArgOperands(), Callee,
      ForceVoidReturnTy ? Type::getVoidTy(*DAG.getContext()) : Call->getType(),
      false);
  if (!VarArgDisallowed)
    SI.CLI.IsVarArg = Call->getFunctionType()->isVarArg();

  auto DeoptBundle = *Call->getOperandBundle(LLVMContext::OB_deopt);

  unsigned DefaultID = StatepointDirectives::DeoptBundleStatepointID;

  auto SD = parseStatepointDirectivesFromAttrs(Call->getAttributes());
  SI.ID = SD.StatepointID.getValueOr(DefaultID);
  SI.NumPatchBytes = SD.NumPatchBytes.getValueOr(0);

  SI.DeoptState =
      ArrayRef<const Use>(DeoptBundle.Inputs.begin(), DeoptBundle.Inputs.end());
  SI.StatepointFlags = static_cast<uint64_t>(StatepointFlags::None);
  SI.EHPadBB = EHPadBB;

  // NB! The GC arguments are deliberately left empty.

  if (SDValue ReturnVal = LowerAsSTATEPOINT(SI)) {
    ReturnVal = lowerRangeToAssertZExt(DAG, *Call, ReturnVal);
    setValue(Call, ReturnVal);
  }
}

void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle(
    const CallBase *Call, SDValue Callee, const BasicBlock *EHPadBB) {
  LowerCallSiteWithDeoptBundleImpl(Call, Callee, EHPadBB,
                                   /* VarArgDisallowed = */ false,
                                   /* ForceVoidReturnTy  = */ false);
}

void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
  // The result value of the gc_result is simply the result of the actual
  // call.  We've already emitted this, so just grab the value.
  const GCStatepointInst *SI = CI.getStatepoint();

  if (SI->getParent() == CI.getParent()) {
    setValue(&CI, getValue(SI));
    return;
  }
  // Statepoint is in different basic block so we should have stored call
  // result in a virtual register.
  // We can not use default getValue() functionality to copy value from this
  // register because statepoint and actual call return types can be
  // different, and getValue() will use CopyFromReg of the wrong type,
  // which is always i32 in our case.
  Type *RetTy = SI->getActualReturnType();
  SDValue CopyFromReg = getCopyFromRegs(SI, RetTy);
  
  assert(CopyFromReg.getNode());
  setValue(&CI, CopyFromReg);
}

void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
#ifndef NDEBUG
  // Consistency check
  // We skip this check for relocates not in the same basic block as their
  // statepoint. It would be too expensive to preserve validation info through
  // different basic blocks.
  if (Relocate.getStatepoint()->getParent() == Relocate.getParent())
    StatepointLowering.relocCallVisited(Relocate);

  auto *Ty = Relocate.getType()->getScalarType();
  if (auto IsManaged = GFI->getStrategy().isGCManagedPointer(Ty))
    assert(*IsManaged && "Non gc managed pointer relocated!");
#endif

  const Value *DerivedPtr = Relocate.getDerivedPtr();
  auto &RelocationMap =
    FuncInfo.StatepointRelocationMaps[Relocate.getStatepoint()];
  auto SlotIt = RelocationMap.find(DerivedPtr);
  assert(SlotIt != RelocationMap.end() && "Relocating not lowered gc value");
  const RecordType &Record = SlotIt->second;

  // If relocation was done via virtual register..
  if (Record.type == RecordType::VReg) {
    Register InReg = Record.payload.Reg;
    RegsForValue RFV(*DAG.getContext(), DAG.getTargetLoweringInfo(),
                     DAG.getDataLayout(), InReg, Relocate.getType(),
                     None); // This is not an ABI copy.
    // We generate copy to/from regs even for local uses, hence we must
    // chain with current root to ensure proper ordering of copies w.r.t.
    // statepoint.
    SDValue Chain = DAG.getRoot();
    SDValue Relocation = RFV.getCopyFromRegs(DAG, FuncInfo, getCurSDLoc(),
                                             Chain, nullptr, nullptr);
    setValue(&Relocate, Relocation);
    return;
  }

  if (Record.type == RecordType::Spill) {
    unsigned Index = Record.payload.FI;
    SDValue SpillSlot = DAG.getTargetFrameIndex(Index, getFrameIndexTy());

    // All the reloads are independent and are reading memory only modified by
    // statepoints (i.e. no other aliasing stores); informing SelectionDAG of
    // this this let's CSE kick in for free and allows reordering of
    // instructions if possible.  The lowering for statepoint sets the root,
    // so this is ordering all reloads with the either
    // a) the statepoint node itself, or
    // b) the entry of the current block for an invoke statepoint.
    const SDValue Chain = DAG.getRoot(); // != Builder.getRoot()

    auto &MF = DAG.getMachineFunction();
    auto &MFI = MF.getFrameInfo();
    auto PtrInfo = MachinePointerInfo::getFixedStack(MF, Index);
    auto *LoadMMO = MF.getMachineMemOperand(PtrInfo, MachineMemOperand::MOLoad,
                                            MFI.getObjectSize(Index),
                                            MFI.getObjectAlign(Index));

    auto LoadVT = DAG.getTargetLoweringInfo().getValueType(DAG.getDataLayout(),
                                                           Relocate.getType());

    SDValue SpillLoad =
        DAG.getLoad(LoadVT, getCurSDLoc(), Chain, SpillSlot, LoadMMO);
    PendingLoads.push_back(SpillLoad.getValue(1));

    assert(SpillLoad.getNode());
    setValue(&Relocate, SpillLoad);
    return;
  }

  assert(Record.type == RecordType::NoRelocate);
  SDValue SD = getValue(DerivedPtr);

  if (SD.isUndef() && SD.getValueType().getSizeInBits() <= 64) {
    // Lowering relocate(undef) as arbitrary constant. Current constant value
    // is chosen such that it's unlikely to be a valid pointer.
    setValue(&Relocate, DAG.getTargetConstant(0xFEFEFEFE, SDLoc(SD), MVT::i64));
    return;
  }

  // We didn't need to spill these special cases (constants and allocas).
  // See the handling in spillIncomingValueForStatepoint for detail.
  setValue(&Relocate, SD);
}

void SelectionDAGBuilder::LowerDeoptimizeCall(const CallInst *CI) {
  const auto &TLI = DAG.getTargetLoweringInfo();
  SDValue Callee = DAG.getExternalSymbol(TLI.getLibcallName(RTLIB::DEOPTIMIZE),
                                         TLI.getPointerTy(DAG.getDataLayout()));

  // We don't lower calls to __llvm_deoptimize as varargs, but as a regular
  // call.  We also do not lower the return value to any virtual register, and
  // change the immediately following return to a trap instruction.
  LowerCallSiteWithDeoptBundleImpl(CI, Callee, /* EHPadBB = */ nullptr,
                                   /* VarArgDisallowed = */ true,
                                   /* ForceVoidReturnTy = */ true);
}

void SelectionDAGBuilder::LowerDeoptimizingReturn() {
  // We do not lower the return value from llvm.deoptimize to any virtual
  // register, and change the immediately following return to a trap
  // instruction.
  if (DAG.getTarget().Options.TrapUnreachable)
    DAG.setRoot(
        DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, DAG.getRoot()));
}
