[Hexagon] Extract function that checks endloops with other branches

Change location number to point to conflicting branch instruction.

Patch by Colin LeMahieu.

llvm-svn: 301946
This commit is contained in:
Krzysztof Parzyszek 2017-05-02 17:56:11 +00:00
parent 1cc6bfbc83
commit c15f8d2a08
4 changed files with 51 additions and 55 deletions

View File

@ -246,6 +246,7 @@ bool HexagonMCChecker::check(bool FullCheck) {
bool chkNV = checkNewValues();
bool chkR = checkRegisters();
bool chkRRO = checkRegistersReadOnly();
bool chkELB = checkEndloopBranches();
checkRegisterCurDefs();
bool chkS = checkSolo();
bool chkSh = true;
@ -254,11 +255,30 @@ bool HexagonMCChecker::check(bool FullCheck) {
bool chkSl = true;
if (FullCheck)
chkSl = checkSlots();
bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkS && chkSh && chkSl;
bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkELB && chkS &&
chkSh && chkSl;
return chk;
}
bool HexagonMCChecker::checkEndloopBranches() {
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
MCInstrDesc const &Desc = HexagonMCInstrInfo::getDesc(MCII, I);
if (Desc.isBranch() || Desc.isCall()) {
auto Inner = HexagonMCInstrInfo::isInnerLoop(MCB);
if (Inner || HexagonMCInstrInfo::isOuterLoop(MCB)) {
reportError(I.getLoc(),
llvm::Twine("packet marked with `:endloop") +
(Inner ? "0" : "1") + "' " +
"cannot contain instructions that modify register " +
"`" + llvm::Twine(RI.getName(Hexagon::PC)) + "'");
return false;
}
}
}
return true;
}
bool HexagonMCChecker::checkSlots() {
unsigned slotsUsed = 0;
for (auto HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) {
@ -304,16 +324,6 @@ bool HexagonMCChecker::checkBranches() {
}
}
if (Branches) // FIXME: should "Defs.count(Hexagon::PC)" be here too?
if (HexagonMCInstrInfo::isInnerLoop(MCB) ||
HexagonMCInstrInfo::isOuterLoop(MCB)) {
// Error out if there's any branch in a loop-end packet.
Twine N(HexagonMCInstrInfo::isInnerLoop(MCB) ? '0' : '1');
reportError("packet marked with `:endloop" + N + "' " +
"cannot contain instructions that modify register " + "`" +
llvm::Twine(RI.getName(Hexagon::PC)) + "'");
return false;
}
if (Branches > 1)
if (!hasConditional || Conditional > Unconditional) {
// Error out if more than one unconditional branch or
@ -391,29 +401,23 @@ bool HexagonMCChecker::checkRegistersReadOnly() {
return true;
}
bool HexagonMCChecker::registerUsed(MCInst const &Inst, unsigned Register) {
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) {
for (auto const &I: HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
if (registerUsed(I, Register))
return true;
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB))
for (unsigned j = HexagonMCInstrInfo::getDesc(MCII, I).getNumDefs(),
n = I.getNumOperands();
j < n; ++j) {
MCOperand const &Operand = I.getOperand(j);
if (Operand.isReg() && Operand.getReg() == Register)
return true;
}
return false;
}
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();
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
if (HexagonMCInstrInfo::isCVINew(MCII, I) &&
HexagonMCInstrInfo::getDesc(MCII, I).mayLoad()) {
unsigned Register = I.getOperand(0).getReg();
if (!registerUsed(Register))
reportWarning("Register `" + llvm::Twine(RI.getName(Register)) +
"' used with `.cur' "
@ -512,12 +516,11 @@ bool HexagonMCChecker::checkRegisters() {
// Check for legal use of solo insns.
bool HexagonMCChecker::checkSolo() {
if (HexagonMCInstrInfo::bundleSize(MCB) > 1)
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCB)) {
if (llvm::HexagonMCInstrInfo::isSolo(MCII, *I.getInst())) {
SMLoc Loc = I.getInst()->getLoc();
reportError(Loc, "Instruction is marked `isSolo' and "
"cannot have other instructions in "
"the same packet");
for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) {
if (llvm::HexagonMCInstrInfo::isSolo(MCII, I)) {
reportError(I.getLoc(), "Instruction is marked `isSolo' and "
"cannot have other instructions in "
"the same packet");
return false;
}
}

View File

@ -107,13 +107,13 @@ class HexagonMCChecker {
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();
bool checkEndloopBranches();
void checkRegisterCurDefs();
bool checkSolo();
bool checkShuffle();

View File

@ -0,0 +1,12 @@
# RUN: not llvm-mc -triple=hexagon -filetype=asm %s 2>&1 | FileCheck %s
# Check that a branch in an end-loop packet is caught.
{ jump unknown
}:endloop0
# CHECK: 5:3: error: packet marked with `:endloop0' cannot contain instructions that modify register
{ jump unknown
}:endloop1
# CHECK: 9:3: error: packet marked with `:endloop1' cannot contain instructions that modify register

View File

@ -1,19 +0,0 @@
# RUN: not llvm-mc -triple=hexagon -filetype=asm %s 2>&1 | FileCheck %s
# Check that a branch in an end-loop packet is caught.
1:
{
r0 = #1
p0 = cmp.eq (r1, r2)
if (p0) jump 1b
}:endloop0
2:
{
r0 = #1
p0 = cmp.eq (r1, r2)
if (p0) jump 2b
}:endloop1
# CHECK: rror: packet marked with `:endloop{{.}}' cannot contain instructions that modify register