summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/Hexagon/RDFGraph.cpp
diff options
context:
space:
mode:
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>2017-01-30 19:16:30 +0000
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>2017-01-30 19:16:30 +0000
commit3695d06a10df6dca79758150c5d0bca882f42d7a (patch)
tree20faa33763341722e176eda92f597184c244b8b4 /llvm/lib/Target/Hexagon/RDFGraph.cpp
parent480609d0f3bc392bf1fbf36b7f467a6e050e51e1 (diff)
downloadbcm5719-llvm-3695d06a10df6dca79758150c5d0bca882f42d7a.tar.gz
bcm5719-llvm-3695d06a10df6dca79758150c5d0bca882f42d7a.zip
[RDF] Add support for regmasks
llvm-svn: 293538
Diffstat (limited to 'llvm/lib/Target/Hexagon/RDFGraph.cpp')
-rw-r--r--llvm/lib/Target/Hexagon/RDFGraph.cpp116
1 files changed, 73 insertions, 43 deletions
diff --git a/llvm/lib/Target/Hexagon/RDFGraph.cpp b/llvm/lib/Target/Hexagon/RDFGraph.cpp
index 98744d5c8de..4b5c212a7f8 100644
--- a/llvm/lib/Target/Hexagon/RDFGraph.cpp
+++ b/llvm/lib/Target/Hexagon/RDFGraph.cpp
@@ -424,7 +424,7 @@ RegisterRef RefNode::getRegRef(const DataFlowGraph &G) const {
if (NodeAttrs::flags(Attrs) & NodeAttrs::PhiRef)
return G.unpack(Ref.PR);
assert(Ref.Op != nullptr);
- return G.makeRegRef(Ref.Op->getReg(), Ref.Op->getSubReg());
+ return G.makeRegRef(*Ref.Op);
}
// Set the register reference in the reference node directly (for references
@@ -755,17 +755,6 @@ unsigned DataFlowGraph::DefStack::nextDown(unsigned P) const {
// Register information.
-// Get the list of references aliased to RR. Lane masks are ignored.
-RegisterSet DataFlowGraph::getAliasSet(RegisterId Reg) const {
- // Do not include RR in the alias set.
- RegisterSet AS;
- assert(TargetRegisterInfo::isPhysicalRegister(Reg));
-
- for (MCRegAliasIterator AI(Reg, &TRI, false); AI.isValid(); ++AI)
- AS.insert(RegisterRef(*AI));
- return AS;
-}
-
RegisterSet DataFlowGraph::getLandingPadLiveIns() const {
RegisterSet LR;
const Function &F = *MF.getFunction();
@@ -977,26 +966,34 @@ void DataFlowGraph::build(unsigned Options) {
}
RegisterRef DataFlowGraph::makeRegRef(unsigned Reg, unsigned Sub) const {
- assert(TargetRegisterInfo::isPhysicalRegister(Reg));
+ assert(PhysicalRegisterInfo::isRegMaskId(Reg) ||
+ TargetRegisterInfo::isPhysicalRegister(Reg));
+ assert(Reg != 0);
if (Sub != 0)
Reg = TRI.getSubReg(Reg, Sub);
return RegisterRef(Reg);
}
+RegisterRef DataFlowGraph::makeRegRef(const MachineOperand &Op) const {
+ assert(Op.isReg() || Op.isRegMask());
+ if (Op.isReg())
+ return makeRegRef(Op.getReg(), Op.getSubReg());
+ return RegisterRef(PRI.getRegMaskId(Op.getRegMask()), LaneBitmask::getAll());
+}
+
RegisterRef DataFlowGraph::normalizeRef(RegisterRef RR) const {
// FIXME copied from RegisterAggr
- RegisterId SuperReg = RR.Reg;
- while (true) {
- MCSuperRegIterator SR(SuperReg, &TRI, false);
- if (!SR.isValid())
- break;
- SuperReg = *SR;
- }
-
- uint32_t Sub = TRI.getSubRegIndex(SuperReg, RR.Reg);
- const TargetRegisterClass &RC = *TRI.getMinimalPhysRegClass(RR.Reg);
- LaneBitmask SuperMask = RR.Mask &
- TRI.composeSubRegIndexLaneMask(Sub, RC.LaneMask);
+ if (PhysicalRegisterInfo::isRegMaskId(RR.Reg))
+ return RR;
+ const TargetRegisterClass *RC = PRI.RegInfos[RR.Reg].RegClass;
+ LaneBitmask RCMask = RC != nullptr ? RC->LaneMask : LaneBitmask(0x00000001);
+ LaneBitmask Common = RR.Mask & RCMask;
+
+ RegisterId SuperReg = PRI.RegInfos[RR.Reg].MaxSuper;
+// Ex: IP/EIP/RIP
+// assert(RC != nullptr || RR.Reg == SuperReg);
+ uint32_t Sub = PRI.getTRI().getSubRegIndex(SuperReg, RR.Reg);
+ LaneBitmask SuperMask = PRI.getTRI().composeSubRegIndexLaneMask(Sub, Common);
return RegisterRef(SuperReg, SuperMask);
}
@@ -1012,7 +1009,7 @@ RegisterRef DataFlowGraph::restrictRef(RegisterRef AR, RegisterRef BR) const {
#endif
// This isn't strictly correct, because the overlap may happen in the
// part masked out.
- if (TRI.regsOverlap(AR.Reg, BR.Reg))
+ if (PRI.alias(AR, BR))
return AR;
return RegisterRef();
}
@@ -1083,10 +1080,10 @@ void DataFlowGraph::pushDefs(NodeAddr<InstrNode*> IA, DefStackMap &DefM) {
// Push the definition on the stack for the register and all aliases.
// The def stack traversal in linkNodeUp will check the exact aliasing.
DefM[RR.Reg].push(DA);
- for (RegisterRef A : getAliasSet(RR.Reg /*FIXME? use RegisterRef*/)) {
+ for (RegisterId A : PRI.getAliasSet(RR.Reg)) {
// Check that we don't push the same def twice.
- assert(A != RR);
- DefM[A.Reg].push(DA);
+ assert(A != RR.Reg);
+ DefM[A].push(DA);
}
// Mark all the related defs as visited.
for (NodeAddr<NodeBase*> T : Rel)
@@ -1223,20 +1220,26 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
if (In.isCall())
return true;
// Is tail call?
- if (In.isBranch())
+ if (In.isBranch()) {
for (const MachineOperand &Op : In.operands())
if (Op.isGlobal() || Op.isSymbol())
return true;
+ // Assume indirect branches are calls. This is for the purpose of
+ // keeping implicit operands, and so it won't hurt on intra-function
+ // indirect branches.
+ if (In.isIndirectBranch())
+ return true;
+ }
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())
+ for (const MachineOperand &Op : In.operands()) {
+ if (!Op.isReg() || Op.getReg() == 0 || !Op.isUse() || Op.isUndef())
continue;
- RegisterRef UR = makeRegRef(UseOp.getReg(), UseOp.getSubReg());
+ RegisterRef UR = makeRegRef(Op);
if (PRI.alias(DR, UR))
return false;
}
@@ -1263,18 +1266,20 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
// defs that define registers that overlap, but it is not clear how to
// interpret that in the absence of explicit defs. Overlapping explicit
// defs are likely illegal already.
- RegisterSet DoneDefs;
+ BitVector DoneDefs(TRI.getNumRegs());
// Process explicit defs first.
for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isDef() || Op.isImplicit())
continue;
- RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
+ unsigned R = Op.getReg();
+ if (!R || !TargetRegisterInfo::isPhysicalRegister(R))
+ continue;
uint16_t Flags = NodeAttrs::None;
if (TOI.isPreserving(In, OpN)) {
Flags |= NodeAttrs::Preserving;
// If the def is preserving, check if it is also undefined.
- if (isDefUndef(In, RR))
+ if (isDefUndef(In, makeRegRef(Op)))
Flags |= NodeAttrs::Undef;
}
if (TOI.isClobbering(In, OpN))
@@ -1285,7 +1290,25 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
Flags |= NodeAttrs::Dead;
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
- DoneDefs.insert(RR);
+ assert(!DoneDefs.test(R));
+ DoneDefs.set(R);
+ }
+
+ // Process reg-masks (as clobbers).
+ BitVector DoneClobbers(TRI.getNumRegs());
+ for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
+ MachineOperand &Op = In.getOperand(OpN);
+ if (!Op.isRegMask())
+ continue;
+ uint16_t Flags = NodeAttrs::Clobbering | NodeAttrs::Fixed |
+ NodeAttrs::Dead;
+ NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
+ SA.Addr->addMember(DA, *this);
+ // Record all clobbered registers in DoneDefs.
+ const uint32_t *RM = Op.getRegMask();
+ for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i)
+ if (!(RM[i/32] & (1u << (i%32))))
+ DoneClobbers.set(i);
}
// Process implicit defs, skipping those that have already been added
@@ -1294,10 +1317,11 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isDef() || !Op.isImplicit())
continue;
- RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
- if (!NeedsImplicit && !ImpDefs.count(RR))
+ unsigned R = Op.getReg();
+ if (!R || !TargetRegisterInfo::isPhysicalRegister(R) || DoneDefs.test(R))
continue;
- if (DoneDefs.count(RR))
+ RegisterRef RR = makeRegRef(Op);
+ if (!NeedsImplicit && !ImpDefs.count(RR))
continue;
uint16_t Flags = NodeAttrs::None;
if (TOI.isPreserving(In, OpN)) {
@@ -1310,18 +1334,24 @@ void DataFlowGraph::buildStmt(NodeAddr<BlockNode*> BA, MachineInstr &In) {
Flags |= NodeAttrs::Clobbering;
if (TOI.isFixedReg(In, OpN))
Flags |= NodeAttrs::Fixed;
- if (IsCall && Op.isDead())
+ if (IsCall && Op.isDead()) {
+ if (DoneClobbers.test(R))
+ continue;
Flags |= NodeAttrs::Dead;
+ }
NodeAddr<DefNode*> DA = newDef(SA, Op, Flags);
SA.Addr->addMember(DA, *this);
- DoneDefs.insert(RR);
+ DoneDefs.set(R);
}
for (unsigned OpN = 0; OpN < NumOps; ++OpN) {
MachineOperand &Op = In.getOperand(OpN);
if (!Op.isReg() || !Op.isUse())
continue;
- RegisterRef RR = makeRegRef(Op.getReg(), Op.getSubReg());
+ unsigned R = Op.getReg();
+ if (!R || !TargetRegisterInfo::isPhysicalRegister(R))
+ continue;
+ RegisterRef RR = makeRegRef(Op);
// Add implicit uses on return and call instructions, and on predicated
// instructions regardless of whether or not they appear in the instruction
// descriptor's list.
OpenPOWER on IntegriCloud