[llvm] r280851 - [RDF] Introduce "undef" flag for ref nodes
Krzysztof Parzyszek via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 7 13:10:56 PDT 2016
Author: kparzysz
Date: Wed Sep 7 15:10:56 2016
New Revision: 280851
URL: http://llvm.org/viewvc/llvm-project?rev=280851&view=rev
Log:
[RDF] Introduce "undef" flag for ref nodes
Modified:
llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp
llvm/trunk/lib/Target/Hexagon/RDFGraph.h
llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp
Modified: llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp?rev=280851&r1=280850&r2=280851&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFGraph.cpp Wed Sep 7 15:10:56 2016
@@ -62,6 +62,8 @@ raw_ostream &operator<< (raw_ostream &OS
}
break;
case NodeAttrs::Ref:
+ if (Flags & NodeAttrs::Undef)
+ OS << '/';
if (Flags & NodeAttrs::Preserving)
OS << '+';
if (Flags & NodeAttrs::Clobbering)
@@ -1189,6 +1191,19 @@ void DataFlowGraph::buildStmt(NodeAddr<B
return false;
};
+ auto isDefUndef = [this] (const MachineInstr &In, RegisterRef DR) -> bool {
+ // This instruction defines DR. Check if there is a use operand that
+ // would make DR live on entry to the instruction.
+ for (const MachineOperand &UseOp : In.operands()) {
+ if (!UseOp.isReg() || !UseOp.isUse() || UseOp.isUndef())
+ continue;
+ RegisterRef UR = { UseOp.getReg(), UseOp.getSubReg() };
+ if (RAI.alias(DR, UR))
+ return false;
+ }
+ return true;
+ };
+
// Collect a set of registers that this instruction implicitly uses
// or defines. Implicit operands from an instruction will be ignored
// unless they are listed here.
@@ -1216,8 +1231,12 @@ void DataFlowGraph::buildStmt(NodeAddr<B
continue;
RegisterRef RR = { Op.getReg(), Op.getSubReg() };
uint16_t Flags = NodeAttrs::None;
- if (TOI.isPreserving(In, OpN))
+ if (TOI.isPreserving(In, OpN)) {
Flags |= NodeAttrs::Preserving;
+ // If the def is preserving, check if it is also undefined.
+ if (isDefUndef(In, RR))
+ Flags |= NodeAttrs::Undef;
+ }
if (TOI.isClobbering(In, OpN))
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
@@ -1239,8 +1258,12 @@ void DataFlowGraph::buildStmt(NodeAddr<B
if (DoneDefs.count(RR))
continue;
uint16_t Flags = NodeAttrs::None;
- if (TOI.isPreserving(In, OpN))
+ if (TOI.isPreserving(In, OpN)) {
Flags |= NodeAttrs::Preserving;
+ // If the def is preserving, check if it is also undefined.
+ if (isDefUndef(In, RR))
+ Flags |= NodeAttrs::Undef;
+ }
if (TOI.isClobbering(In, OpN))
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
@@ -1252,7 +1275,7 @@ void DataFlowGraph::buildStmt(NodeAddr<B
for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
MachineOperand &Op = In.getOperand(OpN);
- if (!Op.isReg() || !Op.isUse() || Op.isUndef())
+ if (!Op.isReg() || !Op.isUse())
continue;
RegisterRef RR = { Op.getReg(), Op.getSubReg() };
// Add implicit uses on return and call instructions, and on predicated
@@ -1263,6 +1286,8 @@ void DataFlowGraph::buildStmt(NodeAddr<B
if (Implicit && !TakeImplicit && !ImpUses.count(RR))
continue;
uint16_t Flags = NodeAttrs::None;
+ if (Op.isUndef())
+ Flags |= NodeAttrs::Undef;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
NodeAddr<UseNode*> UA = newUse(SA, Op, Flags);
Modified: llvm/trunk/lib/Target/Hexagon/RDFGraph.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFGraph.h?rev=280851&r1=280850&r2=280851&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFGraph.h (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFGraph.h Wed Sep 7 15:10:56 2016
@@ -175,7 +175,22 @@
// - Clobbering: applied only to defs, indicates that the value generated
// by this def is unspecified. A typical example would be volatile registers
// after function calls.
-//
+// - Fixed: the register in this def/use cannot be replaced with any other
+// register. A typical case would be a parameter register to a call, or
+// the register with the return value from a function.
+// - Undef: the register in this reference the register is assumed to have
+// no pre-existing value, even if it appears to be reached by some def.
+// This is typically used to prevent keeping registers artificially live
+// in cases when they are defined via predicated instructions. For example:
+// r0 = add-if-true cond, r10, r11 (1)
+// r0 = add-if-false cond, r12, r13, r0<imp-use> (2)
+// ... = r0 (3)
+// Before (1), r0 is not intended to be live, and the use of r0 in (3) is
+// not meant to be reached by any def preceding (1). However, since the
+// defs in (1) and (2) are both preserving, these properties alone would
+// 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.
//
// *** Shadow references
//
@@ -244,13 +259,14 @@ namespace rdf {
Block = 0x0005 << 2, // 101
Func = 0x0006 << 2, // 110
- // Flags: 5 bits for now
- FlagMask = 0x001F << 5,
- Shadow = 0x0001 << 5, // 00001, Has extra reaching defs.
- Clobbering = 0x0002 << 5, // 00010, Produces unspecified values.
- PhiRef = 0x0004 << 5, // 00100, Member of PhiNode.
- Preserving = 0x0008 << 5, // 01000, Def can keep original bits.
- Fixed = 0x0010 << 5, // 10000, Fixed register.
+ // 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.
};
static uint16_t type(uint16_t T) { return T & TypeMask; }
@@ -742,6 +758,10 @@ namespace rdf {
return BA.Addr->getType() == NodeAttrs::Code &&
BA.Addr->getKind() == NodeAttrs::Phi;
}
+ static bool IsPreservingDef(const NodeAddr<DefNode*> DA) {
+ uint16_t Flags = DA.Addr->getFlags();
+ return (Flags & NodeAttrs::Preserving) && !(Flags & NodeAttrs::Undef);
+ }
private:
void reset();
Modified: llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp?rev=280851&r1=280850&r2=280851&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp (original)
+++ llvm/trunk/lib/Target/Hexagon/RDFLiveness.cpp Wed Sep 7 15:10:56 2016
@@ -109,11 +109,9 @@ NodeList Liveness::getAllReachingDefs(Re
continue;
// Stop at the covering/overwriting def of the initial register reference.
RegisterRef RR = TA.Addr->getRegRef();
- if (RAI.covers(RR, RefRR)) {
- uint16_t Flags = TA.Addr->getFlags();
- if (!(Flags & NodeAttrs::Preserving))
+ if (RAI.covers(RR, RefRR))
+ if (!DFG.IsPreservingDef(TA))
continue;
- }
// Get the next level of reaching defs. This will include multiple
// reaching defs for shadows.
for (auto S : DFG.getRelatedRefs(TA.Addr->getOwner(DFG), TA))
@@ -221,7 +219,7 @@ NodeList Liveness::getAllReachingDefs(Re
// defs to actually define a register.
uint16_t Flags = DA.Addr->getFlags();
if (!FullChain || !(Flags & NodeAttrs::PhiRef))
- if (!(Flags & NodeAttrs::Preserving))
+ if (!(Flags & NodeAttrs::Preserving)) // Don't care about Undef here.
RRs.insert(DA.Addr->getRegRef());
}
}
@@ -291,9 +289,11 @@ NodeSet Liveness::getAllReachedUses(Regi
NodeId U = DefA.Addr->getReachedUse();
while (U != 0) {
auto UA = DFG.addr<UseNode*>(U);
- auto UR = UA.Addr->getRegRef();
- if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR))
- Uses.insert(U);
+ if (!(UA.Addr->getFlags() & NodeAttrs::Undef)) {
+ auto UR = UA.Addr->getRegRef();
+ if (RAI.alias(RefRR, UR) && !RAI.covers(DefRRs, UR))
+ Uses.insert(U);
+ }
U = UA.Addr->getSibling();
}
@@ -307,7 +307,7 @@ NodeSet Liveness::getAllReachedUses(Regi
if (RAI.covers(DefRRs, DR) || !RAI.alias(RefRR, DR))
continue;
NodeSet T;
- if (DA.Addr->getFlags() & NodeAttrs::Preserving) {
+ if (DFG.IsPreservingDef(DA)) {
// If it is a preserving def, do not update the set of intervening defs.
T = getAllReachedUses(RefRR, DA, DefRRs);
} else {
@@ -358,7 +358,8 @@ void Liveness::computePhiInfo() {
NodeId UN = DA.Addr->getReachedUse();
while (UN != 0) {
NodeAddr<UseNode*> A = DFG.addr<UseNode*>(UN);
- if (!(A.Addr->getFlags() & NodeAttrs::PhiRef))
+ uint16_t F = A.Addr->getFlags();
+ if ((F & (NodeAttrs::Undef | NodeAttrs::PhiRef)) == 0)
RealUses[getRestrictedRegRef(A)].insert(A.Id);
UN = A.Addr->getSibling();
}
@@ -847,14 +848,16 @@ void Liveness::traverse(MachineBasicBloc
if (B != BA.Addr->getCode())
Defs.insert(R);
else {
- bool IsPreserving = DA.Addr->getFlags() & NodeAttrs::Preserving;
+ bool IsPreserving = DFG.IsPreservingDef(DA);
if (IA.Addr->getKind() != NodeAttrs::Phi && !IsPreserving) {
bool Covering = RAI.covers(DDR, I.first);
NodeId U = DA.Addr->getReachedUse();
while (U && Covering) {
auto DUA = DFG.addr<UseNode*>(U);
- RegisterRef Q = DUA.Addr->getRegRef();
- Covering = RAI.covers(DA.Addr->getRegRef(), Q);
+ if (!(DUA.Addr->getFlags() & NodeAttrs::Undef)) {
+ RegisterRef Q = DUA.Addr->getRegRef();
+ Covering = RAI.covers(DA.Addr->getRegRef(), Q);
+ }
U = DUA.Addr->getSibling();
}
if (!Covering)
@@ -898,6 +901,8 @@ void Liveness::traverse(MachineBasicBloc
continue;
for (NodeAddr<UseNode*> UA : IA.Addr->members_if(DFG.IsUse, DFG)) {
RegisterRef RR = UA.Addr->getRegRef();
+ if (UA.Addr->getFlags() & NodeAttrs::Undef)
+ continue;
for (auto D : getAllReachingDefs(UA))
if (getBlockWithRef(D.Id) != B)
LiveIn[RR].insert(D.Id);
More information about the llvm-commits
mailing list