[llvm] [AArch64] Hint regalloc to choose distinct predicate for MATCH/CMP (PR #190139)

Mikael Holmen via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 14 06:42:43 PDT 2026


================
@@ -1115,6 +1115,55 @@ unsigned AArch64RegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
   }
 }
 
+static bool HandleMatchCmpPredicateHint(
+    Register VirtReg, ArrayRef<MCPhysReg> Order,
+    SmallVectorImpl<MCPhysReg> &Hints, const VirtRegMap *VRM,
+    const MachineRegisterInfo &MRI, const TargetInstrInfo &TII,
+    const AArch64Subtarget &ST, const LiveRegMatrix *Matrix) {
+  const TargetRegisterClass *RegRC = MRI.getRegClass(VirtReg);
+  if (!ST.useDistinctPredicateDstReg() ||
+      !AArch64::PPRRegClass.hasSubClassEq(RegRC) || !MRI.hasOneDef(VirtReg) ||
+      Order.size() < 2)
+    return false;
+
+  const MachineInstr *DefInst = MRI.getOneDef(VirtReg)->getParent();
+  if ((TII.get(DefInst->getOpcode()).TSFlags &
+       AArch64::DestructiveInstTypeMask) != AArch64::DestructivePredicate)
+    return false;
+
+  Register Op1Reg = DefInst->getOperand(1).getReg();
+  if (Op1Reg.isVirtual())
+    Op1Reg = VRM->getPhys(Op1Reg);
+
+  // If no register is allocated for the general-predicate, it's not yet
+  // possible to choose a distinct register.
+  if (!Op1Reg.isValid())
+    return false;
+
+  // Move Op1Reg as the least preferred register.
+  //
+  // This might result in callee-save spills when the function takes/returns
+  // arguments in SVE registers (i.e. needs to preserve p4-p15) and can't reuse
+  // p0-p3. That's why we limit it to non-callee saved registers or to
+  // callee-saved registers that have already been allocated for other uses in
+  // the function.
+  DenseSet<unsigned> CSRs;
+  for (unsigned I = 0;; ++I) {
+    Register R = MRI.getCalleeSavedRegs()[I];
+    if (!R.isValid())
+      break;
+    if (AArch64::PPRRegClass.contains(R))
+      CSRs.insert(R);
+  }
+
+  Hints.append(Order.begin(), Order.end());
+  llvm::stable_sort(Hints, [&](Register A, Register B) {
----------------
mikaelholmen wrote:

Hi @sdesmalen-arm 

Wwith EXPENSIVE_CHECKS I currently see 85 failing AArch64 lit tests. One example:
```
********************
Testing:  0.. 10.. 20.. 30
FAIL: LLVM :: CodeGen/AArch64/sve2-intrinsics-reinterpret.ll (32364 of 98064)
******************** TEST 'LLVM :: CodeGen/AArch64/sve2-intrinsics-reinterpret.ll' FAILED ********************
Exit Code: 2

Command Output (stdout):
--
# RUN: at line 2
/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc -mtriple=aarch64-linux-gnu -mattr=+sve2 < /repo/llvm-main-expensive-checks/llvm/test/CodeGen/AArch64/sve2-intrinsics-reinterpret.ll | /repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/FileCheck /repo/llvm-main-expensive-checks/llvm/test/CodeGen/AArch64/sve2-intrinsics-reinterpret.ll
# executed command: /repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc -mtriple=aarch64-linux-gnu -mattr=+sve2
# .---command stderr------------
# | [...]/include/c++/13.3.0/bits/stl_algo.h:5117:
# | In function:
# |     void std::stable_sort(_RandomAccessIterator, _RandomAccessIterator,
# |     _Compare) [_RandomAccessIterator = unsigned short *, _Compare = (lambda
# |     at
# |     /repo/llvm-main-expensive-checks/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp:1160:28)]
# |
# | Error: comparison doesn't meet irreflexive requirements, assert(!(a < a)).
# |
# | Objects involved in the operation:
# |     instance "functor" @ 0x7fffd1fcc190 {
# |     }
# |     iterator::value_type "ordered type"  {
# |     }
# | PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
# | Stack dump:
# | 0.  Program arguments: /repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc -mtriple=aarch64-linux-gnu -mattr=+sve2
# | 1.  Running pass 'Function Pass Manager' on module '<stdin>'.
# | 2.  Running pass 'Greedy Register Allocator' on function '@cmpeq_d_fun'
# |  #0 0x0000561e9988e956 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x92c1956)
# |  #1 0x0000561e9988b781 llvm::sys::RunSignalHandlers() (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x92be781)
# |  #2 0x0000561e9988f789 SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
# |  #3 0x00007fdf233ea990 __restore_rt (/lib64/libpthread.so.0+0x12990)
# |  #4 0x00007fdf20d8a5af raise (/lib64/libc.so.6+0x4e5af)
# |  #5 0x00007fdf20d5dee5 abort (/lib64/libc.so.6+0x21ee5)
# |  #6 0x0000561e9a8adef3 (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0xa2e0ef3)
# |  #7 0x0000561e95f8a5a1 llvm::AArch64RegisterInfo::getRegAllocationHints(llvm::Register, llvm::ArrayRef<unsigned short>, llvm::SmallVectorImpl<unsigned short>&, llvm::MachineFunction const&, llvm::VirtRegMap const*, llvm::LiveRegMatrix const*) const AArch64RegisterInfo.cpp:0:0
# |  #8 0x0000561e984d5ee2 llvm::AllocationOrder::create(llvm::Register, llvm::VirtRegMap const&, llvm::RegisterClassInfo const&, llvm::LiveRegMatrix const*) AllocationOrder.cpp:0:0
# |  #9 0x0000561e9850706a llvm::RAGreedy::selectOrSplitImpl(llvm::LiveInterval const&, llvm::SmallVectorImpl<llvm::Register>&, llvm::SmallSet<llvm::Register, 16u, std::less<llvm::Register>>&, llvm::SmallVector<std::pair<llvm::LiveInterval const*, llvm::MCRegister>, 8u>&, unsigned int) RegAllocGreedy.cpp:0:0
# | #10 0x0000561e9850791e llvm::RAGreedy::selectOrSplit(llvm::LiveInterval const&, llvm::SmallVectorImpl<llvm::Register>&) RegAllocGreedy.cpp:0:0
# | #11 0x0000561e984d1cea llvm::RegAllocBase::allocatePhysRegs() (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x7f04cea)
# | #12 0x0000561e984f949d llvm::RAGreedy::run(llvm::MachineFunction&) RegAllocGreedy.cpp:0:0
# | #13 0x0000561e9850c71a (anonymous namespace)::RAGreedyLegacy::runOnMachineFunction(llvm::MachineFunction&) RegAllocGreedy.cpp:0:0
# | #14 0x0000561e98241747 llvm::MachineFunctionPass::runOnFunction(llvm::Function&) (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x7c74747)
# | #15 0x0000561e9888a9c4 llvm::FPPassManager::runOnFunction(llvm::Function&) (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x82bd9c4)
# | #16 0x0000561e98892bf2 llvm::FPPassManager::runOnModule(llvm::Module&) (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x82c5bf2)
# | #17 0x0000561e9888b4e6 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x82be4e6)
# | #18 0x0000561e95c774e8 compileModule(char**, llvm::SmallVectorImpl<llvm::PassPlugin>&, llvm::LLVMContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>&) llc.cpp:0:0
# | #19 0x0000561e95c747a6 main (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x56a77a6)
# | #20 0x00007fdf20d76865 __libc_start_main (/lib64/libc.so.6+0x3a865)
# | #21 0x0000561e95c7392e _start (/repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/llc+0x56a692e)
# `-----------------------------
# error: command failed with exit status: -6
# executed command: /repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/FileCheck /repo/llvm-main-expensive-checks/llvm/test/CodeGen/AArch64/sve2-intrinsics-reinterpret.ll
# .---command stderr------------
# | FileCheck error: '<stdin>' is empty.
# | FileCheck command line:  /repo/llvm-main-expensive-checks/llvm/build-all-expensive/bin/FileCheck /repo/llvm-main-expensive-checks/llvm/test/CodeGen/AArch64/sve2-intrinsics-reinterpret.ll
# `-----------------------------
# error: command failed with exit status: 2
```

https://github.com/llvm/llvm-project/pull/190139


More information about the llvm-commits mailing list