Repository: llvm/llvm-project

Issue:
[LoongArch] Assertion failure 'MachineOperand::getIndex() const: (isFI() || isCPI() || isTargetIndex() || isJTI()) && "Wrong MachineOperand accessor"' failed.'
While building the Linux kernel for the LoongArch using Clang, the following assertion failure occurs:

```
llvm/include/llvm/CodeGen/MachineOperand.h:572: int llvm::MachineOperand::getIndex() const: Assertion (isFI() || isCPI() || isTargetIndex() || isJT
I()) && "Wrong MachineOperand accessor"' failed.
```

This happens when compiling the file `drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c`.

Clang invocation:

```sh
clang -Wp,-MMD,drivers/net/wireless/realtek/rtlwifi/rtl8821ae/.phy.o.d -nostdinc -I./arch/loongarch/include -I./arch/loongarch/include/generated -I./include -I./include -I./arch/loongarch/include/uapi -I./arch/loongarch/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ --target=loongarch64-linux-gnusf -fintegrated-as -Werror=unknown-warning-option -Werror=ignored-optimization-argument -Werror=option-ignored -Werror=unused-command-line-argument -DCC_USING_PATCHABLE_FUNCTION_ENTRY -DVMLINUX_LOAD_ADDRESS=0x9000000000200000 -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -mno-relax -mannotate-tablejump -mabi=lp64s -mcmodel=normal -pipe -msoft-float -fno-builtin-memcpy -fno-builtin-memmove -fno-builtin-memset -fno-asynchronous-unwind-tables -mstrict-align -isystem /tmp/rel/lib/clang/21/include -fno-delete-null-pointer-checks -O2 -fstack-protector-strong -ftrivial-auto-var-init=zero -fpatchable-function-entry=2 -fstrict-flex-arrays=3 -fno-strict-overflow -fno-stack-check -fno-builtin-wcslen -Wall -Wextra -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=2048 -Wno-gnu -Wno-format-overflow-non-kprintf -Wno-format-truncation-non-kprintf -Wno-default-const-init-unsafe -Wvla -Wno-pointer-sign -Wcast-function-type -Wno-unterminated-string-initialization -Wimplicit-fallthrough -Werror=date-time -Werror=incompatible-pointer-types -Wenum-conversion -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-format-overflow -Wno-override-init -Wno-pointer-to-enum-cast -Wno-tautological-constant-out-of-range-compare -Wno-unaligned-access -Wno-enum-compare-conditional -Wno-missing-field-initializers -Wno-type-limits -Wno-shift-negative-value -Wno-enum-enum-conversion -Wno-sign-compare -Wno-unused-parameter -g -DMODULE -fno-direct-access-external-data -DKBUILD_BASENAME=\"phy\" -DKBUILD_MODNAME=\"rtl8821ae\" -D__KBUILD_MODNAME=kmod_rtl8821ae -c -o drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.o drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
```

Clang version:

```
clang version 21.0.0git (https://github.com/llvm/llvm-project 1a08aa2680da76258a2f8252ab63d05e5638b9da)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /tmp/rel/bin
Build config: +assertions
```

Linux kernel version:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tag/?h=v6.15-rc7

Kernel config:

[config](https://github.com/user-attachments/files/20380302/config.txt)


Discussion:

@llvm/issue-subscribers-backend-loongarch

Author: hev (heiher)

<details>
While building the Linux kernel for the LoongArch using Clang, the following assertion failure occurs:

```
llvm/include/llvm/CodeGen/MachineOperand.h:572: int llvm::MachineOperand::getIndex() const: Assertion (isFI() || isCPI() || isTargetIndex() || isJT
I()) &amp;&amp; "Wrong MachineOperand accessor"' failed.
```

This happens when compiling the file `drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c`.

Clang invocation:

```sh
clang -Wp,-MMD,drivers/net/wireless/realtek/rtlwifi/rtl8821ae/.phy.o.d -nostdinc -I./arch/loongarch/include -I./arch/loongarch/include/generated -I./include -I./include -I./arch/loongarch/include/uapi -I./arch/loongarch/include/generated/uapi -I./include/uapi -I./include/generated/uapi -include ./include/linux/compiler-version.h -include ./include/linux/kconfig.h -include ./include/linux/compiler_types.h -D__KERNEL__ --target=loongarch64-linux-gnusf -fintegrated-as -Werror=unknown-warning-option -Werror=ignored-optimization-argument -Werror=option-ignored -Werror=unused-command-line-argument -DCC_USING_PATCHABLE_FUNCTION_ENTRY -DVMLINUX_LOAD_ADDRESS=0x9000000000200000 -std=gnu11 -fshort-wchar -funsigned-char -fno-common -fno-PIE -fno-strict-aliasing -mno-relax -mannotate-tablejump -mabi=lp64s -mcmodel=normal -pipe -msoft-float -fno-builtin-memcpy -fno-builtin-memmove -fno-builtin-memset -fno-asynchronous-unwind-tables -mstrict-align -isystem /tmp/rel/lib/clang/21/include -fno-delete-null-pointer-checks -O2 -fstack-protector-strong -ftrivial-auto-var-init=zero -fpatchable-function-entry=2 -fstrict-flex-arrays=3 -fno-strict-overflow -fno-stack-check -fno-builtin-wcslen -Wall -Wextra -Wundef -Werror=implicit-function-declaration -Werror=implicit-int -Werror=return-type -Werror=strict-prototypes -Wno-format-security -Wno-trigraphs -Wno-frame-address -Wno-address-of-packed-member -Wmissing-declarations -Wmissing-prototypes -Wframe-larger-than=2048 -Wno-gnu -Wno-format-overflow-non-kprintf -Wno-format-truncation-non-kprintf -Wno-default-const-init-unsafe -Wvla -Wno-pointer-sign -Wcast-function-type -Wno-unterminated-string-initialization -Wimplicit-fallthrough -Werror=date-time -Werror=incompatible-pointer-types -Wenum-conversion -Wunused -Wno-unused-but-set-variable -Wno-unused-const-variable -Wno-format-overflow -Wno-override-init -Wno-pointer-to-enum-cast -Wno-tautological-constant-out-of-range-compare -Wno-unaligned-access -Wno-enum-compare-conditional -Wno-missing-field-initializers -Wno-type-limits -Wno-shift-negative-value -Wno-enum-enum-conversion -Wno-sign-compare -Wno-unused-parameter -g -DMODULE -fno-direct-access-external-data -DKBUILD_BASENAME=\"phy\" -DKBUILD_MODNAME=\"rtl8821ae\" -D__KBUILD_MODNAME=kmod_rtl8821ae -c -o drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.o drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
```

Clang version:

```
clang version 21.0.0git (https://github.com/llvm/llvm-project 1a08aa2680da76258a2f8252ab63d05e5638b9da)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /tmp/rel/bin
Build config: +assertions
```

Linux kernel version:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tag/?h=v6.15-rc7

Kernel config:

`arch/loongarch/configs/loongson3_defconfig`
</details>


Patch:
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index 895a8e2646692..9a383f0a79a5c 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -265,13 +265,16 @@ void LoongArchAsmPrinter::emitJumpTableInfo() {
 
   assert(TM.getTargetTriple().isOSBinFormatELF());
 
-  unsigned Size = getDataLayout().getPointerSize();
   auto *LAFI = MF->getInfo<LoongArchMachineFunctionInfo>();
   unsigned EntrySize = LAFI->getJumpInfoSize();
+  auto JTI = MF->getJumpTableInfo();
 
-  if (0 == EntrySize)
+  if (!JTI || 0 == EntrySize)
     return;
 
+  unsigned Size = getDataLayout().getPointerSize();
+  auto JT = JTI->getJumpTables();
+
   // Emit an additional section to store the correlation info as pairs of
   // addresses, each pair contains the address of a jump instruction (jr) and
   // the address of the jump table.
@@ -279,14 +282,15 @@ void LoongArchAsmPrinter::emitJumpTableInfo() {
       ".discard.tablejump_annotate", ELF::SHT_PROGBITS, 0));
 
   for (unsigned Idx = 0; Idx < EntrySize; ++Idx) {
+    int JTIIdx = LAFI->getJumpInfoJTIIndex(Idx);
+    if (JT[JTIIdx].MBBs.empty())
+      continue;
     OutStreamer->emitValue(
         MCSymbolRefExpr::create(LAFI->getJumpInfoJrMI(Idx)->getPreInstrSymbol(),
                                 OutContext),
         Size);
     OutStreamer->emitValue(
-        MCSymbolRefExpr::create(
-            GetJTISymbol(LAFI->getJumpInfoJTIMO(Idx)->getIndex()), OutContext),
-        Size);
+        MCSymbolRefExpr::create(GetJTISymbol(JTIIdx), OutContext), Size);
   }
 }
 
diff --git a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
index c2d73a260b1c1..2107908be34ca 100644
--- a/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
@@ -638,7 +638,8 @@ void LoongArchPreRAExpandPseudo::annotateTableJump(
         if (MO.isJTI()) {
           MBBI->setPreInstrSymbol(
               *MF, MF->getContext().createNamedTempSymbol("jrtb_"));
-          MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO);
+          MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(
+              &*MBBI, MO.getIndex());
           IsFound = true;
           return;
         }
diff --git a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
index daa47c4dc7e32..904985c189dba 100644
--- a/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
+++ b/llvm/lib/Target/LoongArch/LoongArchMachineFunctionInfo.h
@@ -41,7 +41,7 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
 
   /// Pairs of `jr` instructions and corresponding JTI operands, used for the
   /// `annotate-tablejump` option.
-  SmallVector<std::pair<MachineInstr *, MachineOperand *>, 4> JumpInfos;
+  SmallVector<std::pair<MachineInstr *, int>, 4> JumpInfos;
 
 public:
   LoongArchMachineFunctionInfo(const Function &F,
@@ -76,14 +76,12 @@ class LoongArchMachineFunctionInfo : public MachineFunctionInfo {
     return is_contained(SExt32Registers, Reg);
   }
 
-  void setJumpInfo(MachineInstr *JrMI, MachineOperand *JTIMO) {
-    JumpInfos.push_back(std::make_pair(JrMI, JTIMO));
+  void setJumpInfo(MachineInstr *JrMI, int JTIIdx) {
+    JumpInfos.push_back(std::make_pair(JrMI, JTIIdx));
   }
   unsigned getJumpInfoSize() { return JumpInfos.size(); }
   MachineInstr *getJumpInfoJrMI(unsigned Idx) { return JumpInfos[Idx].first; }
-  MachineOperand *getJumpInfoJTIMO(unsigned Idx) {
-    return JumpInfos[Idx].second;
-  }
+  int getJumpInfoJTIIndex(unsigned Idx) { return JumpInfos[Idx].second; }
 };
 
 } // end namespace llvm