[Hexagon] Move checking AXOK to checker
authorKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 2 May 2017 18:00:37 +0000 (18:00 +0000)
committerKrzysztof Parzyszek <kparzysz@codeaurora.org>
Tue, 2 May 2017 18:00:37 +0000 (18:00 +0000)
Patch by Colin LeMahieu.

llvm-svn: 301949

llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.cpp
llvm/lib/Target/Hexagon/MCTargetDesc/HexagonMCChecker.h
llvm/lib/Target/Hexagon/MCTargetDesc/HexagonShuffler.cpp
llvm/test/MC/Hexagon/PacketRules/restrict_ax.s [new file with mode: 0644]
llvm/test/MC/Hexagon/solo-axok.s [new file with mode: 0644]

index 6ce0277..7b464c3 100644 (file)
@@ -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)) {
index 2937c7a..2095a4a 100644 (file)
@@ -118,6 +118,7 @@ class HexagonMCChecker {
   bool checkSolo();
   bool checkShuffle();
   bool checkSlots();
+  bool checkAXOK();
 
   static void compoundRegisterMap(unsigned &);
 
index 4350c19..4844862 100644 (file)
@@ -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/llvm/test/MC/Hexagon/PacketRules/restrict_ax.s b/llvm/test/MC/Hexagon/PacketRules/restrict_ax.s
new file mode 100644 (file)
index 0000000..b8f7a1f
--- /dev/null
@@ -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/llvm/test/MC/Hexagon/solo-axok.s b/llvm/test/MC/Hexagon/solo-axok.s
new file mode 100644 (file)
index 0000000..2df5796
--- /dev/null
@@ -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