forked from OSchip/llvm-project
Re-land part of r354244 "[DAGCombiner] Eliminate dead stores to stack."
This part introduces the lifetime node. llvm-svn: 354578
This commit is contained in:
parent
e9461a716d
commit
a0321c23e8
|
@ -1016,6 +1016,12 @@ public:
|
|||
ArrayRef<SDValue> Ops, EVT MemVT,
|
||||
MachineMemOperand *MMO);
|
||||
|
||||
/// Creates a LifetimeSDNode that starts (`IsStart==true`) or ends
|
||||
/// (`IsStart==false`) the lifetime of the portion of `FrameIndex` between
|
||||
/// offsets `Offset` and `Offset + Size`.
|
||||
SDValue getLifetimeNode(bool IsStart, const SDLoc &dl, SDValue Chain,
|
||||
int FrameIndex, int64_t Size, int64_t Offset = -1);
|
||||
|
||||
/// Create a MERGE_VALUES node from the given operands.
|
||||
SDValue getMergeValues(ArrayRef<SDValue> Ops, const SDLoc &dl);
|
||||
|
||||
|
|
|
@ -1692,6 +1692,37 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// This SDNode is used for LIFETIME_START/LIFETIME_END values, which indicate
|
||||
/// the offet and size that are started/ended in the underlying FrameIndex.
|
||||
class LifetimeSDNode : public SDNode {
|
||||
int64_t Size;
|
||||
int64_t Offset; // -1 if offset is unknown.
|
||||
public:
|
||||
LifetimeSDNode(unsigned Opcode, unsigned Order, const DebugLoc &dl,
|
||||
SDVTList VTs, int64_t Size, int64_t Offset)
|
||||
: SDNode(Opcode, Order, dl, VTs), Size(Size), Offset(Offset) {}
|
||||
|
||||
int64_t getFrameIndex() const {
|
||||
return cast<FrameIndexSDNode>(getOperand(1))->getIndex();
|
||||
}
|
||||
|
||||
bool hasOffset() const { return Offset >= 0; }
|
||||
int64_t getOffset() const {
|
||||
assert(hasOffset() && "offset is unknown");
|
||||
return Offset;
|
||||
}
|
||||
int64_t getSize() const {
|
||||
assert(hasOffset() && "offset is unknown");
|
||||
return Size;
|
||||
}
|
||||
|
||||
// Methods to support isa and dyn_cast
|
||||
static bool classof(const SDNode *N) {
|
||||
return N->getOpcode() == ISD::LIFETIME_START ||
|
||||
N->getOpcode() == ISD::LIFETIME_END;
|
||||
}
|
||||
};
|
||||
|
||||
class JumpTableSDNode : public SDNode {
|
||||
friend class SelectionDAG;
|
||||
|
||||
|
|
|
@ -6506,6 +6506,36 @@ SDValue SelectionDAG::getMemIntrinsicNode(unsigned Opcode, const SDLoc &dl,
|
|||
return SDValue(N, 0);
|
||||
}
|
||||
|
||||
SDValue SelectionDAG::getLifetimeNode(bool IsStart, const SDLoc &dl,
|
||||
SDValue Chain, int FrameIndex,
|
||||
int64_t Size, int64_t Offset) {
|
||||
const unsigned Opcode = IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END;
|
||||
const auto VTs = getVTList(MVT::Other);
|
||||
SDValue Ops[2] = {
|
||||
Chain,
|
||||
getFrameIndex(FrameIndex,
|
||||
getTargetLoweringInfo().getFrameIndexTy(getDataLayout()),
|
||||
true)};
|
||||
|
||||
FoldingSetNodeID ID;
|
||||
AddNodeIDNode(ID, Opcode, VTs, Ops);
|
||||
ID.AddInteger(FrameIndex);
|
||||
ID.AddInteger(Size);
|
||||
ID.AddInteger(Offset);
|
||||
void *IP = nullptr;
|
||||
if (SDNode *E = FindNodeOrInsertPos(ID, dl, IP))
|
||||
return SDValue(E, 0);
|
||||
|
||||
LifetimeSDNode *N = newSDNode<LifetimeSDNode>(
|
||||
Opcode, dl.getIROrder(), dl.getDebugLoc(), VTs, Size, Offset);
|
||||
createOperands(N, Ops);
|
||||
CSEMap.InsertNode(N, IP);
|
||||
InsertNode(N);
|
||||
SDValue V(N, 0);
|
||||
NewSDValueDbgMsg(V, "Creating new node: ", this);
|
||||
return V;
|
||||
}
|
||||
|
||||
/// InferPointerInfo - If the specified ptr/offset is a frame index, infer a
|
||||
/// MachinePointerInfo record from it. This is particularly useful because the
|
||||
/// code generator has many cases where it doesn't bother passing in a
|
||||
|
|
|
@ -6373,8 +6373,11 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||
if (TM.getOptLevel() == CodeGenOpt::None)
|
||||
return nullptr;
|
||||
|
||||
const int64_t ObjectSize =
|
||||
cast<ConstantInt>(I.getArgOperand(0))->getSExtValue();
|
||||
Value *const ObjectPtr = I.getArgOperand(1);
|
||||
SmallVector<Value *, 4> Allocas;
|
||||
GetUnderlyingObjects(I.getArgOperand(1), Allocas, *DL);
|
||||
GetUnderlyingObjects(ObjectPtr, Allocas, *DL);
|
||||
|
||||
for (SmallVectorImpl<Value*>::iterator Object = Allocas.begin(),
|
||||
E = Allocas.end(); Object != E; ++Object) {
|
||||
|
@ -6390,15 +6393,13 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||
if (SI == FuncInfo.StaticAllocaMap.end())
|
||||
return nullptr;
|
||||
|
||||
int FI = SI->second;
|
||||
|
||||
SDValue Ops[2];
|
||||
Ops[0] = getRoot();
|
||||
Ops[1] =
|
||||
DAG.getFrameIndex(FI, TLI.getFrameIndexTy(DAG.getDataLayout()), true);
|
||||
unsigned Opcode = (IsStart ? ISD::LIFETIME_START : ISD::LIFETIME_END);
|
||||
|
||||
Res = DAG.getNode(Opcode, sdl, MVT::Other, Ops);
|
||||
const int FrameIndex = SI->second;
|
||||
int64_t Offset;
|
||||
if (GetPointerBaseWithConstantOffset(
|
||||
ObjectPtr, Offset, DAG.getDataLayout()) != LifetimeObject)
|
||||
Offset = -1; // Cannot determine offset from alloca to lifetime object.
|
||||
Res = DAG.getLifetimeNode(IsStart, sdl, getRoot(), FrameIndex, ObjectSize,
|
||||
Offset);
|
||||
DAG.setRoot(Res);
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -709,6 +709,9 @@ void SDNode::print_details(raw_ostream &OS, const SelectionDAG *G) const {
|
|||
<< " -> "
|
||||
<< ASC->getDestAddressSpace()
|
||||
<< ']';
|
||||
} else if (const LifetimeSDNode *LN = dyn_cast<LifetimeSDNode>(this)) {
|
||||
if (LN->hasOffset())
|
||||
OS << "<" << LN->getOffset() << " to " << LN->getOffset() + LN->getSize() << ">";
|
||||
}
|
||||
|
||||
if (VerboseDAGDumping) {
|
||||
|
|
Loading…
Reference in New Issue