isPredicateRegister(*SRI))
// Some insns produce predicates too late to be used in the same packet.
LatePreds.insert(*SRI);
- else if (i == 0 && HexagonMCInstrInfo::isCVINew(MCII, MCI) &&
- MCID.mayLoad())
- // Current loads should be used in the same packet.
- // TODO: relies on the impossibility of a current and a temporary loads
- // in the same packet.
- CurDefs.insert(*SRI), Defs[*SRI].insert(PredSense(PredReg, isTrue));
else if (i == 0 && llvm::HexagonMCInstrInfo::getType(MCII, MCI) ==
HexagonII::TypeCVI_VM_TMP_LD)
// Temporary loads should be used in the same packet, but don't commit
bool chkNV = checkNewValues();
bool chkR = checkRegisters();
bool chkRRO = checkRegistersReadOnly();
+ checkRegisterCurDefs();
bool chkS = checkSolo();
bool chkSh = true;
if (FullCheck)
return true;
}
+bool HexagonMCChecker::registerUsed(MCInst const &Inst, unsigned Register) {
+ if (HexagonMCInstrInfo::isDuplex(MCII, Inst)) {
+ if (registerUsed(*Inst.getOperand(0).getInst(), Register) ||
+ registerUsed(*Inst.getOperand(1).getInst(), Register))
+ return true;
+ } else {
+ unsigned Defs = HexagonMCInstrInfo::getDesc(MCII, Inst).getNumDefs();
+ for (unsigned j = Defs, n = Inst.getNumOperands(); j < n; ++j) {
+ MCOperand const &Operand = Inst.getOperand(j);
+ if (Operand.isReg() && Operand.getReg() == Register)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool HexagonMCChecker::registerUsed(unsigned Register) {
+ auto Range = HexagonMCInstrInfo::bundleInstructions(MCB);
+ return std::any_of(Range.begin(), Range.end(), [&](MCOperand const &Operand) {
+ return registerUsed(*Operand.getInst(), Register);
+ });
+}
+
+void HexagonMCChecker::checkRegisterCurDefs() {
+ for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
+ MCInst const &Inst = *I.getInst();
+ if (HexagonMCInstrInfo::isCVINew(MCII, Inst) &&
+ HexagonMCInstrInfo::getDesc(MCII, Inst).mayLoad()) {
+ unsigned Register = Inst.getOperand(0).getReg();
+ if (!registerUsed(Register))
+ reportWarning("Register `" + llvm::Twine(RI.getName(Register)) +
+ "' used with `.cur' "
+ "but not used in the same packet");
+ }
+ }
+}
+
// Check for legal register uses and definitions.
bool HexagonMCChecker::checkRegisters() {
// Check for proper register definitions.
}
}
- // Check for use of current definitions.
- for (const auto &I : CurDefs) {
- unsigned R = I;
-
- if (!Uses.count(R)) {
- // Warn on an unused current definition.
- reportWarning("register `" + llvm::Twine(RI.getName(R)) +
- "' used with `.cur' "
- "but not used in the same packet");
- return true;
- }
- }
-
// Check for use of temporary definitions.
for (const auto &I : TmpDefs) {
unsigned R = I;
typedef std::set<unsigned>::iterator SoftDefsIterator;
std::set<unsigned> SoftDefs;
- /// Set of current definitions committed to the register file.
- typedef std::set<unsigned>::iterator CurDefsIterator;
- std::set<unsigned> CurDefs;
-
/// Set of temporary definitions not committed to the register file.
typedef std::set<unsigned>::iterator TmpDefsIterator;
std::set<unsigned> TmpDefs;
void init();
void init(MCInst const &);
void initReg(MCInst const &, unsigned, unsigned &PredReg, bool &isTrue);
-
+
+ bool registerUsed(unsigned Register);
+ bool registerUsed(MCInst const &Inst, unsigned Register);
// Checks performed.
bool checkBranches();
bool checkPredicates();
bool checkNewValues();
bool checkRegisters();
bool checkRegistersReadOnly();
+ void checkRegisterCurDefs();
bool checkSolo();
bool checkShuffle();
bool checkSlots();