summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
committerpatrick <patrick@openbsd.org>2017-01-24 08:32:59 +0000
commit53d771aafdbe5b919f264f53cba3788e2c4cffd2 (patch)
tree7eca39498be0ff1e3a6daf583cd9ca5886bb2636 /gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
parentIn preparation of compiling our kernels with -ffreestanding, explicitly map (diff)
downloadwireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.tar.xz
wireguard-openbsd-53d771aafdbe5b919f264f53cba3788e2c4cffd2.zip
Import LLVM 4.0.0 rc1 including clang and lld to help the current
development effort on OpenBSD/arm64.
Diffstat (limited to 'gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp')
-rw-r--r--gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp66
1 files changed, 50 insertions, 16 deletions
diff --git a/gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
index 90aaba24726..d27e2455978 100644
--- a/gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
+++ b/gnu/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp
@@ -55,7 +55,8 @@ void StatepointLoweringState::startNewStatepoint(SelectionDAGBuilder &Builder) {
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. SmallBitVector::reset initializes all bits to false.
+ // FunctionLoweringInfo. Also need to ensure used bits get cleared.
+ AllocatedStackSlots.clear();
AllocatedStackSlots.resize(Builder.FuncInfo.StatepointStackSlots.size());
}
@@ -70,7 +71,7 @@ SDValue
StatepointLoweringState::allocateStackSlot(EVT ValueType,
SelectionDAGBuilder &Builder) {
NumSlotsAllocatedForStatepoints++;
- auto *MFI = Builder.DAG.getMachineFunction().getFrameInfo();
+ MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();
unsigned SpillSize = ValueType.getSizeInBits() / 8;
assert((SpillSize * 8) == ValueType.getSizeInBits() && "Size not in bytes?");
@@ -82,16 +83,16 @@ StatepointLoweringState::allocateStackSlot(EVT ValueType,
const size_t NumSlots = AllocatedStackSlots.size();
assert(NextSlotToAllocate <= NumSlots && "Broken invariant");
- // The stack slots in StatepointStackSlots beyond the first NumSlots were
- // added in this instance of StatepointLoweringState, and cannot be re-used.
- assert(NumSlots <= Builder.FuncInfo.StatepointStackSlots.size() &&
+ 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) {
+ if (MFI.getObjectSize(FI) == SpillSize) {
AllocatedStackSlots.set(NextSlotToAllocate);
+ // TODO: Is ValueType the right thing to use here?
return Builder.DAG.getFrameIndex(FI, ValueType);
}
}
@@ -101,9 +102,13 @@ StatepointLoweringState::allocateStackSlot(EVT ValueType,
SDValue SpillSlot = Builder.DAG.CreateStackTemporary(ValueType);
const unsigned FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex();
- MFI->markAsStatepointSpillSlotObjectIndex(FI);
+ 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 = std::max<unsigned long>(
StatepointMaxSlotsRequired, Builder.FuncInfo.StatepointStackSlots.size());
@@ -350,9 +355,8 @@ spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
// 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 '>=').
- auto *MFI = Builder.DAG.getMachineFunction().getFrameInfo();
- assert((MFI->getObjectSize(Index) * 8) ==
- Incoming.getValueType().getSizeInBits() &&
+ MachineFrameInfo &MFI = Builder.DAG.getMachineFunction().getFrameInfo();
+ assert((MFI.getObjectSize(Index) * 8) == Incoming.getValueSizeInBits() &&
"Bad spill: stack slot does not match!");
#endif
@@ -370,7 +374,7 @@ spillIncomingStatepointValue(SDValue Incoming, SDValue Chain,
/// 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,
+static void lowerIncomingStatepointValue(SDValue Incoming, bool LiveInOnly,
SmallVectorImpl<SDValue> &Ops,
SelectionDAGBuilder &Builder) {
SDValue Chain = Builder.getRoot();
@@ -389,6 +393,14 @@ static void lowerIncomingStatepointValue(SDValue Incoming,
// relocate the address of the alloca itself?)
Ops.push_back(Builder.DAG.getTargetFrameIndex(FI->getIndex(),
Incoming.getValueType()));
+ } else if (LiveInOnly) {
+ // 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.
+ Ops.push_back(Incoming);
} else {
// Otherwise, locate a spill slot and explicitly spill it so it
// can be found by the runtime later. We currently do not support
@@ -439,19 +451,38 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
"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;
+
+ auto isGCValue =[&](const Value *V) {
+ return is_contained(SI.Ptrs, V) || is_contained(SI.Bases, V);
+ };
+
// 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) {
- reservePreviousStackSlotForValue(V, Builder);
+ if (!LiveInDeopt || isGCValue(V))
+ reservePreviousStackSlotForValue(V, Builder);
}
for (unsigned i = 0; i < SI.Bases.size(); ++i) {
reservePreviousStackSlotForValue(SI.Bases[i], Builder);
@@ -468,7 +499,8 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
// what type of values are contained within.
for (const Value *V : SI.DeoptState) {
SDValue Incoming = Builder.getValue(V);
- lowerIncomingStatepointValue(Incoming, Ops, Builder);
+ const bool LiveInValue = LiveInDeopt && !isGCValue(V);
+ lowerIncomingStatepointValue(Incoming, LiveInValue, Ops, Builder);
}
// Finally, go ahead and lower all the gc arguments. There's no prefixed
@@ -478,10 +510,12 @@ lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops,
// (base[0], ptr[0], base[1], ptr[1], ...)
for (unsigned i = 0; i < SI.Bases.size(); ++i) {
const Value *Base = SI.Bases[i];
- lowerIncomingStatepointValue(Builder.getValue(Base), Ops, Builder);
+ lowerIncomingStatepointValue(Builder.getValue(Base), /*LiveInOnly*/ false,
+ Ops, Builder);
const Value *Ptr = SI.Ptrs[i];
- lowerIncomingStatepointValue(Builder.getValue(Ptr), Ops, Builder);
+ lowerIncomingStatepointValue(Builder.getValue(Ptr), /*LiveInOnly*/ false,
+ Ops, Builder);
}
// If there are any explicit spill slots passed to the statepoint, record
@@ -889,7 +923,7 @@ void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) {
#ifndef NDEBUG
// Consistency check
- // We skip this check for relocates not in the same basic block as thier
+ // 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())