[RDF] Introduce "undef" flag for ref nodes

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@280851 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Krzysztof Parzyszek 2016-09-07 20:10:56 +00:00
parent f1708bca49
commit 80708afe43
3 changed files with 74 additions and 24 deletions

View File

@ -62,6 +62,8 @@ raw_ostream &operator<< (raw_ostream &OS, const Print<NodeId> &P) {
}
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<BlockNode*> BA, MachineInstr &In) {
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<BlockNode*> BA, MachineInstr &In) {
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<BlockNode*> BA, MachineInstr &In) {
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<BlockNode*> BA, MachineInstr &In) {
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<BlockNode*> BA, MachineInstr &In) {
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);

View File

@ -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();

View File

@ -109,11 +109,9 @@ NodeList Liveness::getAllReachingDefs(RegisterRef RefRR,
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(RegisterRef RefRR,
// 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(RegisterRef RefRR,
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(RegisterRef RefRR,
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(MachineBasicBlock *B, RefMap &LiveIn) {
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(MachineBasicBlock *B, RefMap &LiveIn) {
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);