From: Krzysztof Parzyszek Date: Tue, 27 Sep 2016 18:24:33 +0000 (+0000) Subject: [RDF] Add "dead" flag to node attributes X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8263469827bbcb4f1a10db9f33513b3d63023dcf;p=llvm [RDF] Add "dead" flag to node attributes git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282520 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Hexagon/RDFGraph.cpp b/lib/Target/Hexagon/RDFGraph.cpp index 72a55f2b9de..c180f99f219 100644 --- a/lib/Target/Hexagon/RDFGraph.cpp +++ b/lib/Target/Hexagon/RDFGraph.cpp @@ -65,6 +65,8 @@ raw_ostream &operator<< (raw_ostream &OS, const Print &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 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 BA, MachineInstr &In) { Flags |= NodeAttrs::Clobbering; if (TOI.isFixedReg(In, OpN)) Flags |= NodeAttrs::Fixed; + if (IsCall && Op.isDead()) + Flags |= NodeAttrs::Dead; NodeAddr DA = newDef(SA, Op, Flags); SA.Addr->addMember(DA, *this); DoneDefs.insert(RR); @@ -1369,6 +1374,8 @@ void DataFlowGraph::buildStmt(NodeAddr BA, MachineInstr &In) { Flags |= NodeAttrs::Clobbering; if (TOI.isFixedReg(In, OpN)) Flags |= NodeAttrs::Fixed; + if (IsCall && Op.isDead()) + Flags |= NodeAttrs::Dead; NodeAddr DA = newDef(SA, Op, Flags); SA.Addr->addMember(DA, *this); DoneDefs.insert(RR); diff --git a/lib/Target/Hexagon/RDFGraph.h b/lib/Target/Hexagon/RDFGraph.h index 596bf342885..79ae8850ab9 100644 --- a/lib/Target/Hexagon/RDFGraph.h +++ b/lib/Target/Hexagon/RDFGraph.h @@ -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; } diff --git a/lib/Target/Hexagon/RDFLiveness.cpp b/lib/Target/Hexagon/RDFLiveness.cpp index 48de9a6dbea..7e1c39df9b8 100644 --- a/lib/Target/Hexagon/RDFLiveness.cpp +++ b/lib/Target/Hexagon/RDFLiveness.cpp @@ -86,9 +86,18 @@ namespace rdf { NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, NodeAddr RefA, bool FullChain, const RegisterSet &DefRRs) { + NodeList RDefs; // Return value. SetVector DefQ; SetVector 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 TA) -> bool { @@ -223,6 +231,11 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR, } } + auto DeadP = [](const NodeAddr 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(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(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 DA = DFG.addr(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 A = DFG.addr(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(*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;