[RDF] Add "dead" flag to node attributes

llvm-svn: 282520
This commit is contained in:
Krzysztof Parzyszek 2016-09-27 18:24:33 +00:00
parent 1d32220721
commit 586fc12e32
3 changed files with 48 additions and 14 deletions

View File

@ -65,6 +65,8 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeId> &P) {
case NodeAttrs::Ref:
if (Flags & NodeAttrs::Undef)
OS << '/';
if (Flags & NodeAttrs::Dead)
OS << '\\';
if (Flags & NodeAttrs::Preserving)
OS << '+';
if (Flags & NodeAttrs::Clobbering)
@ -1316,7 +1318,8 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
while (uint16_t R = *ImpU++)
ImpUses.insert({R, 0});
bool NeedsImplicit = isCall(In) || In.isInlineAsm() || In.isReturn();
bool IsCall = isCall(In);
bool NeedsImplicit = IsCall || In.isInlineAsm() || In.isReturn();
bool IsPredicated = TII.isPredicated(In);
unsigned NumOps = In.getNumOperands();
@ -1342,6 +1345,8 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
if (IsCall && Op.isDead())
Flags |= NodeAttrs::Dead;
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
DoneDefs.insert(RR);
@ -1369,6 +1374,8 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
if (IsCall && Op.isDead())
Flags |= NodeAttrs::Dead;
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
DoneDefs.insert(RR);

View File

@ -191,6 +191,13 @@
// imply that the use in (3) may indeed be reached by some prior def.
// Adding Undef flag to the def in (1) prevents that. The Undef flag
// may be applied to both defs and uses.
// - Dead: applies only to defs. The value coming out of a "dead" def is
// assumed to be unused, even if the def appears to be reaching other defs
// or uses. The motivation for this flag comes from dead defs on function
// calls: there is no way to determine if such a def is dead without
// analyzing the target's ABI. Hence the graph should contain this info,
// as it is unavailable otherwise. On the other hand, a def without any
// uses on a typical instruction is not the intended target for this flag.
//
// *** Shadow references
//
@ -261,14 +268,15 @@ namespace rdf {
Block = 0x0005 << 2, // 101
Func = 0x0006 << 2, // 110
// Flags: 6 bits for now
FlagMask = 0x003F << 5,
Shadow = 0x0001 << 5, // 000001, Has extra reaching defs.
Clobbering = 0x0002 << 5, // 000010, Produces unspecified values.
PhiRef = 0x0004 << 5, // 000100, Member of PhiNode.
Preserving = 0x0008 << 5, // 001000, Def can keep original bits.
Fixed = 0x0010 << 5, // 010000, Fixed register.
Undef = 0x0020 << 5, // 100000, Has no pre-existing value.
// Flags: 7 bits for now
FlagMask = 0x007F << 5,
Shadow = 0x0001 << 5, // 0000001, Has extra reaching defs.
Clobbering = 0x0002 << 5, // 0000010, Produces unspecified values.
PhiRef = 0x0004 << 5, // 0000100, Member of PhiNode.
Preserving = 0x0008 << 5, // 0001000, Def can keep original bits.
Fixed = 0x0010 << 5, // 0010000, Fixed register.
Undef = 0x0020 << 5, // 0100000, Has no pre-existing value.
Dead = 0x0040 << 5, // 1000000, Does not define a value.
};
static uint16_t type(uint16_t T) { return T & TypeMask; }

View File

@ -86,9 +86,18 @@ namespace rdf {
NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
NodeAddr<RefNode*> RefA, bool FullChain, const RegisterSet &DefRRs) {
NodeList RDefs; // Return value.
SetVector<NodeId> DefQ;
SetVector<NodeId> Owners;
// Dead defs will be treated as if they were live, since they are actually
// on the data-flow path. They cannot be ignored because even though they
// do not generate meaningful values, they still modify registers.
// If the reference is undefined, there is nothing to do.
if (RefA.Addr->getFlags() & NodeAttrs::Undef)
return RDefs;
// The initial queue should not have reaching defs for shadows. The
// whole point of a shadow is that it will have a reaching def that
// is not aliased to the reaching defs of the related shadows.
@ -186,7 +195,6 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
// covered if we added A first, and A would be covered
// if we added B first.
NodeList RDefs;
RegisterSet RRs = DefRRs;
auto DefInSet = [&Defs] (NodeAddr<RefNode*> TA) -> bool {
@ -223,6 +231,11 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
}
}
auto DeadP = [](const NodeAddr<DefNode*> DA) -> bool {
return DA.Addr->getFlags() & NodeAttrs::Dead;
};
RDefs.resize(std::distance(RDefs.begin(), remove_if(RDefs, DeadP)));
return RDefs;
}
@ -285,7 +298,9 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
return Uses;
// Add all directly reached uses.
NodeId U = DefA.Addr->getReachedUse();
// If the def is dead, it does not provide a value for any use.
bool IsDead = DefA.Addr->getFlags() & NodeAttrs::Dead;
NodeId U = !IsDead ? DefA.Addr->getReachedUse() : 0;
while (U != 0) {
auto UA = DFG.addr<UseNode*>(U);
if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) {
@ -296,7 +311,7 @@ NodeSet Liveness::getAllReachedUses(RegisterRef RefRR,
U = UA.Addr->getSibling();
}
// Traverse all reached defs.
// Traverse all reached defs. This time dead defs cannot be ignored.
for (NodeId D = DefA.Addr->getReachedDef(), NextD; D != 0; D = NextD) {
auto DA = DFG.addr<DefNode*>(D);
NextD = DA.Addr->getSibling();
@ -360,8 +375,10 @@ void Liveness::computePhiInfo() {
// are actually reached by the phi defs.
for (unsigned i = 0; i < DefQ.size(); ++i) {
NodeAddr<DefNode*> DA = DFG.addr<DefNode*>(DefQ[i]);
// Visit all reached uses.
NodeId UN = DA.Addr->getReachedUse();
// Visit all reached uses. Phi defs should not really have the "dead"
// flag set, but check it anyway for consistency.
bool IsDead = DA.Addr->getFlags() & NodeAttrs::Dead;
NodeId UN = !IsDead ? DA.Addr->getReachedUse() : 0;
while (UN != 0) {
NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN);
uint16_t F = A.Addr->getFlags();
@ -409,6 +426,8 @@ void Liveness::computePhiInfo() {
NodeSet &Uses = UI->second;
for (auto I = Uses.begin(), E = Uses.end(); I != E; ) {
auto UA = DFG.addr<UseNode*>(*I);
// Undef flag is checked above.
assert((UA.Addr->getFlags() & NodeAttrs::Undef) == 0);
NodeList RDs = getAllReachingDefs(UI->first, UA);
if (any_of(RDs, InPhiDefs))
++I;