diff options
author | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-09-27 18:24:33 +0000 |
---|---|---|
committer | Krzysztof Parzyszek <kparzysz@codeaurora.org> | 2016-09-27 18:24:33 +0000 |
commit | 586fc12e320d243b0efde5b0a058ffd9b0ef9c3f (patch) | |
tree | 0e2ce57a41485095c171bdd665dfe0028032b79f /llvm | |
parent | 1d3222072111953cf5ebb16de5ca0fd680bc3fff (diff) | |
download | bcm5719-llvm-586fc12e320d243b0efde5b0a058ffd9b0ef9c3f.tar.gz bcm5719-llvm-586fc12e320d243b0efde5b0a058ffd9b0ef9c3f.zip |
[RDF] Add "dead" flag to node attributes
llvm-svn: 282520
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFGraph.h | 24 | ||||
-rw-r--r-- | llvm/lib/Target/Hexagon/RDFLiveness.cpp | 29 |
3 files changed, 48 insertions, 14 deletions
diff --git a/llvm/lib/Target/Hexagon/RDFGraph.cpp b/llvm/lib/Target/Hexagon/RDFGraph.cpp index 72a55f2b9de..c180f99f219 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.cpp +++ b/llvm/lib/Target/Hexagon/RDFGraph.cpp @@ -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); diff --git a/llvm/lib/Target/Hexagon/RDFGraph.h b/llvm/lib/Target/Hexagon/RDFGraph.h index 596bf342885..79ae8850ab9 100644 --- a/llvm/lib/Target/Hexagon/RDFGraph.h +++ b/llvm/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/llvm/lib/Target/Hexagon/RDFLiveness.cpp b/llvm/lib/Target/Hexagon/RDFLiveness.cpp index 48de9a6dbea..7e1c39df9b8 100644 --- a/llvm/lib/Target/Hexagon/RDFLiveness.cpp +++ b/llvm/lib/Target/Hexagon/RDFLiveness.cpp @@ -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; |