forked from OSchip/llvm-project
[RDF] Add "dead" flag to node attributes
llvm-svn: 282520
This commit is contained in:
parent
1d32220721
commit
586fc12e32
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue