From 46ce66232548903ed1efc68dc810f826a5ee86f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Parzyszek Date: Tue, 2 May 2017 18:00:37 +0000 Subject: [PATCH] [Hexagon] Move checking AXOK to checker Patch by Colin LeMahieu. llvm-svn: 301949 --- .../Hexagon/MCTargetDesc/HexagonMCChecker.cpp | 78 ++++++++++++++++++- .../Hexagon/MCTargetDesc/HexagonMCChecker.h | 1 + .../Hexagon/MCTargetDesc/HexagonShuffler.cpp | 70 +---------------- test/MC/Hexagon/PacketRules/restrict_ax.s | 4 + test/MC/Hexagon/solo-axok.s | 9 +++ 5 files changed, 93 insertions(+), 69 deletions(-) create mode 100644 test/MC/Hexagon/PacketRules/restrict_ax.s create mode 100644 test/MC/Hexagon/solo-axok.s diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp index 6ce0277a073..7b464c3d60f 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp @@ -255,8 +255,9 @@ bool HexagonMCChecker::check(bool FullCheck) { bool chkSl = true; if (FullCheck) chkSl = checkSlots(); + bool chkAXOK = checkAXOK(); bool chk = chkB && chkP && chkNV && chkR && chkRRO && chkELB && chkS && - chkSh && chkSl; + chkSh && chkSl && chkAXOK; return chk; } @@ -279,6 +280,81 @@ bool HexagonMCChecker::checkEndloopBranches() { return true; } +namespace { +bool isDuplexAGroup(unsigned Opcode) { + switch (Opcode) { + case Hexagon::SA1_addi: + case Hexagon::SA1_addrx: + case Hexagon::SA1_addsp: + case Hexagon::SA1_and1: + case Hexagon::SA1_clrf: + case Hexagon::SA1_clrfnew: + case Hexagon::SA1_clrt: + case Hexagon::SA1_clrtnew: + case Hexagon::SA1_cmpeqi: + case Hexagon::SA1_combine0i: + case Hexagon::SA1_combine1i: + case Hexagon::SA1_combine2i: + case Hexagon::SA1_combine3i: + case Hexagon::SA1_combinerz: + case Hexagon::SA1_combinezr: + case Hexagon::SA1_dec: + case Hexagon::SA1_inc: + case Hexagon::SA1_seti: + case Hexagon::SA1_setin1: + case Hexagon::SA1_sxtb: + case Hexagon::SA1_sxth: + case Hexagon::SA1_tfr: + case Hexagon::SA1_zxtb: + case Hexagon::SA1_zxth: + return true; + break; + default: + return false; + } +} + +bool isNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) { + unsigned Result = 0; + unsigned Type = HexagonMCInstrInfo::getType(MCII, ID); + if (Type == HexagonII::TypeDUPLEX) { + unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode(); + unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode(); + Result += !isDuplexAGroup(subInst0Opcode); + Result += !isDuplexAGroup(subInst1Opcode); + } else + Result += + Type != HexagonII::TypeALU32_2op && Type != HexagonII::TypeALU32_3op && + Type != HexagonII::TypeALU32_ADDI && Type != HexagonII::TypeS_2op && + Type != HexagonII::TypeS_3op && + (Type != HexagonII::TypeALU64 || HexagonMCInstrInfo::isFloat(MCII, ID)); + return Result != 0; +} +} // namespace + +bool HexagonMCChecker::checkAXOK() { + MCInst const *HasSoloAXInst = nullptr; + for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) { + if (HexagonMCInstrInfo::isSoloAX(MCII, I)) { + HasSoloAXInst = &I; + } + } + if (!HasSoloAXInst) + return true; + for (auto const &I : HexagonMCInstrInfo::bundleInstructions(MCII, MCB)) { + if (&I != HasSoloAXInst && isNeitherAnorX(MCII, I)) { + reportError( + HasSoloAXInst->getLoc(), + llvm::Twine("Instruction can only be in a packet with ALU or " + "non-FPU XTYPE instructions")); + reportError(I.getLoc(), + llvm::Twine("Not an ALU or non-FPU XTYPE instruction")); + return false; + } + } + return true; +} + bool HexagonMCChecker::checkSlots() { unsigned slotsUsed = 0; for (auto HMI : HexagonMCInstrInfo::bundleInstructions(MCB)) { diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h index 2937c7a9c5c..2095a4a556e 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h @@ -118,6 +118,7 @@ class HexagonMCChecker { bool checkSolo(); bool checkShuffle(); bool checkSlots(); + bool checkAXOK(); static void compoundRegisterMap(unsigned &); diff --git a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp index 4350c199e26..4844862e6d1 100644 --- a/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp +++ b/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp @@ -205,58 +205,6 @@ static struct { } jumpSlots[] = {{8, 4}, {8, 2}, {8, 1}, {4, 2}, {4, 1}, {2, 1}}; #define MAX_JUMP_SLOTS (sizeof(jumpSlots) / sizeof(jumpSlots[0])) -namespace { -bool isDuplexAGroup(unsigned Opcode) { - switch (Opcode) { - case Hexagon::SA1_addi: - case Hexagon::SA1_addrx: - case Hexagon::SA1_addsp: - case Hexagon::SA1_and1: - case Hexagon::SA1_clrf: - case Hexagon::SA1_clrfnew: - case Hexagon::SA1_clrt: - case Hexagon::SA1_clrtnew: - case Hexagon::SA1_cmpeqi: - case Hexagon::SA1_combine0i: - case Hexagon::SA1_combine1i: - case Hexagon::SA1_combine2i: - case Hexagon::SA1_combine3i: - case Hexagon::SA1_combinerz: - case Hexagon::SA1_combinezr: - case Hexagon::SA1_dec: - case Hexagon::SA1_inc: - case Hexagon::SA1_seti: - case Hexagon::SA1_setin1: - case Hexagon::SA1_sxtb: - case Hexagon::SA1_sxth: - case Hexagon::SA1_tfr: - case Hexagon::SA1_zxtb: - case Hexagon::SA1_zxth: - return true; - break; - default: - return false; - } -} - -unsigned countNeitherAnorX(MCInstrInfo const &MCII, MCInst const &ID) { - unsigned Result = 0; - unsigned Type = HexagonMCInstrInfo::getType(MCII, ID); - if (Type == HexagonII::TypeDUPLEX) { - unsigned subInst0Opcode = ID.getOperand(0).getInst()->getOpcode(); - unsigned subInst1Opcode = ID.getOperand(1).getInst()->getOpcode(); - Result += !isDuplexAGroup(subInst0Opcode); - Result += !isDuplexAGroup(subInst1Opcode); - } else - Result += - Type != HexagonII::TypeALU32_2op && Type != HexagonII::TypeALU32_3op && - Type != HexagonII::TypeALU32_ADDI && Type != HexagonII::TypeS_2op && - Type != HexagonII::TypeS_3op && Type != HexagonII::TypeALU64 && - (Type != HexagonII::TypeM || HexagonMCInstrInfo::isFloat(MCII, ID)); - return Result; -} -} // namespace - /// Check that the packet is legal and enforce relative insn order. bool HexagonShuffler::check() { // Descriptive slot masks. @@ -271,18 +219,12 @@ bool HexagonShuffler::check() { // Number of memory operations, loads, solo loads, stores, solo stores, single // stores. unsigned memory = 0, loads = 0, load0 = 0, stores = 0, store0 = 0, store1 = 0; - // Number of HVX loads, HVX stores. - unsigned CVIloads = 0, CVIstores = 0; // Number of duplex insns unsigned duplex = 0; - // Number of insns restricting other insns in the packet to A and X types, - // which is neither A or X types. - unsigned onlyAX = 0, neitherAnorX = 0; // Number of insns restricting other insns in slot #1 to A type. unsigned onlyAin1 = 0; // Number of insns restricting any insn in slot #1, except A2_nop. unsigned onlyNo1 = 0; - unsigned xtypeFloat = 0; unsigned pSlot3Cnt = 0; unsigned nvstores = 0; unsigned memops = 0; @@ -295,11 +237,8 @@ bool HexagonShuffler::check() { for (iterator ISJ = begin(); ISJ != end(); ++ISJ) { MCInst const &ID = ISJ->getDesc(); - if (HexagonMCInstrInfo::isSoloAX(MCII, ID)) - ++onlyAX; - else if (HexagonMCInstrInfo::isSoloAin1(MCII, ID)) + if (HexagonMCInstrInfo::isSoloAin1(MCII, ID)) ++onlyAin1; - neitherAnorX += countNeitherAnorX(MCII, ID); if (HexagonMCInstrInfo::prefersSlot3(MCII, ID)) { ++pSlot3Cnt; slot3ISJ = ISJ; @@ -312,8 +251,6 @@ bool HexagonShuffler::check() { case HexagonII::TypeS_2op: case HexagonII::TypeS_3op: case HexagonII::TypeALU64: - if (HexagonMCInstrInfo::isFloat(MCII, ID)) - ++xtypeFloat; break; case HexagonII::TypeJ: ++jumps; @@ -323,7 +260,6 @@ bool HexagonShuffler::check() { ++onlyNo1; case HexagonII::TypeCVI_VM_LD: case HexagonII::TypeCVI_VM_TMP_LD: - ++CVIloads; case HexagonII::TypeLD: ++loads; ++memory; @@ -339,7 +275,6 @@ bool HexagonShuffler::check() { ++onlyNo1; case HexagonII::TypeCVI_VM_ST: case HexagonII::TypeCVI_VM_NEW_ST: - ++CVIstores; case HexagonII::TypeST: ++stores; ++memory; @@ -408,8 +343,7 @@ bool HexagonShuffler::check() { // Check if the packet is legal. if ((load0 > 1 || store0 > 1) || - (duplex > 1 || (duplex && memory)) || - (onlyAX && neitherAnorX > 1) || (onlyAX && xtypeFloat)) { + (duplex > 1 || (duplex && memory))) { reportError(llvm::Twine("invalid instruction packet")); return false; } diff --git a/test/MC/Hexagon/PacketRules/restrict_ax.s b/test/MC/Hexagon/PacketRules/restrict_ax.s new file mode 100644 index 00000000000..b8f7a1f782c --- /dev/null +++ b/test/MC/Hexagon/PacketRules/restrict_ax.s @@ -0,0 +1,4 @@ +{ r0=memw_locked(r0) + r1=-mpyi(r0,#0) } +# RUN: not llvm-mc -arch=hexagon -filetype=asm %s 2>%t; FileCheck %s --check-prefix=CHECK00 <%t +# CHECK00: 1:3: error: Instruction can only be in a packet with ALU or non-FPU XTYPE instructions diff --git a/test/MC/Hexagon/solo-axok.s b/test/MC/Hexagon/solo-axok.s new file mode 100644 index 00000000000..2df5796e628 --- /dev/null +++ b/test/MC/Hexagon/solo-axok.s @@ -0,0 +1,9 @@ +# RUN: not llvm-mc -arch=hexagon -filetype=asm -mcpu=hexagonv55 %s 2>%t; FileCheck %s < %t +# +{ + sp=asrh(r6) + l2fetch(fp,r23:22) + p2=r7 + p1=dfclass(r31:30,#6) +} +# CHECK: rror: Instruction can only