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:
Clement Courbet 2019-02-21 12:59:36 +00:00
parent e9461a716d
commit a0321c23e8
5 changed files with 81 additions and 10 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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) {