[llvm] [RISCV] Support RVV register overlapping constraints (PR #145004)

Pengcheng Wang via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 22 21:05:51 PDT 2025


================
@@ -1040,3 +1047,221 @@ bool RISCVRegisterInfo::getRegAllocationHints(
 
   return BaseImplRetVal;
 }
+
+unsigned RISCVRegisterInfo::getMCRegIndex(MCRegister Reg,
+                                          const MachineRegisterInfo *MRI) {
+  const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
+  return TRI->getEncodingValue(Reg);
+}
+
+unsigned RISCVRegisterInfo::getMCRegLMUL(MCRegister Reg) {
+  if (RISCVMCRegisterClasses[RISCV::VRRegClassID].contains(Reg))
+    return 1;
+  if (RISCVMCRegisterClasses[RISCV::VRM2RegClassID].contains(Reg))
+    return 2;
+  if (RISCVMCRegisterClasses[RISCV::VRM4RegClassID].contains(Reg))
+    return 4;
+  if (RISCVMCRegisterClasses[RISCV::VRM8RegClassID].contains(Reg))
+    return 8;
+
+  llvm_unreachable("Not supported Register.");
+}
+
+// The destination EEW is smaller than the source EEW and the overlap is in the
+// lowest-numbered part of the source register group (e.g., when LMUL=1,
+// vnsrl.wi v0, v0, 3 is legal, but a destination of v1 is not).
+bool RISCVRegisterInfo::isRVVConstraintsType2(unsigned DestRegIndex,
+                                              unsigned DestRegLMUL,
+                                              unsigned SrcRegIndex,
+                                              unsigned SrcRegLMUL) {
+  if (DestRegIndex == SrcRegIndex)
+    return false;
+
+  return SrcRegIndex < DestRegIndex && DestRegIndex < SrcRegIndex + SrcRegLMUL;
+}
+
+// The destination EEW is greater than the source EEW, the source EMUL is at
+// least 1, and the overlap is in the highest-numbered part of the destination
+// register group (e.g., when LMUL=8, vzext.vf4 v0, v6 is legal, but a source of
+// v0, v2, or v4 is not).
+bool RISCVRegisterInfo::isRVVConstraintsType3(unsigned DestRegIndex,
+                                              unsigned DestRegLMUL,
+                                              unsigned SrcRegIndex,
+                                              unsigned SrcRegLMUL) {
+  if (DestRegLMUL == SrcRegLMUL && DestRegIndex == SrcRegIndex)
+    return true;
+
+  if (SrcRegIndex == DestRegIndex + DestRegLMUL - SrcRegLMUL)
+    return false;
+
+  return DestRegIndex <= SrcRegIndex &&
+         SrcRegIndex < DestRegIndex + DestRegLMUL - SrcRegLMUL;
+}
+
+static MCRegister getPhysicalReg(const MachineOperand MO,
+                                 const MachineOperand MObeAllocated,
+                                 MCRegister PhysRegbeAllocated,
+                                 const VirtRegMap *VRM) {
+  if (MObeAllocated.isIdenticalTo(MO))
+    return PhysRegbeAllocated;
+
+  if (MO.getReg().isPhysical())
+    return MO.getReg().asMCReg();
+
+  if (MO.getReg().isVirtual() && VRM->hasPhys(MO.getReg()))
+    return VRM->getPhys(MO.getReg());
+
+  return PhysRegbeAllocated;
+}
+
+static bool checkConstraintsWithTwoOperand(
+    const MachineInstr *MI, const MachineOperand MObeAllocated,
+    MCRegister PhysRegbeAllocated, MachineOperand DestMO, MachineOperand SrcMO,
+    const MachineRegisterInfo *MRI, const VirtRegMap *VRM) {
+
+  assert(DestMO.isReg() && SrcMO.isReg() && "Must be Register");
+
+  // Allocate for DestMO or SrcMO.
+  if (!MObeAllocated.isIdenticalTo(DestMO) &&
+      !MObeAllocated.isIdenticalTo(SrcMO))
+    return false;
+
+  // Another Operand already assign phyiscal register.
+  if (DestMO.getReg().isVirtual() && !VRM->hasPhys(DestMO.getReg()) &&
+      SrcMO.getReg().isVirtual() && !VRM->hasPhys(SrcMO.getReg()))
+    return false;
+
+  MCRegister DestReg =
+      getPhysicalReg(DestMO, MObeAllocated, PhysRegbeAllocated, VRM);
+  MCRegister SrcReg =
+      getPhysicalReg(SrcMO, MObeAllocated, PhysRegbeAllocated, VRM);
+
+  const TargetRegisterInfo *TRI = MRI->getTargetRegisterInfo();
+
+  // Handle sub-register like sub_vrm4_0:vrm8
+  if (DestMO.getSubReg() != 0)
+    DestReg = TRI->getSubReg(DestReg, DestMO.getSubReg());
+
+  if (SrcMO.getSubReg() != 0)
+    SrcReg = TRI->getSubReg(SrcReg, SrcMO.getSubReg());
+
+  unsigned DestRegIndex = RISCVRegisterInfo::getMCRegIndex(DestReg, MRI);
+  unsigned DestRegLMUL = RISCVRegisterInfo::getMCRegLMUL(DestReg);
+  unsigned SrcRegIndex = RISCVRegisterInfo::getMCRegIndex(SrcReg, MRI);
+  unsigned SrcRegLMUL = RISCVRegisterInfo::getMCRegLMUL(SrcReg);
+
+  unsigned OverlapConstraints =
+      RISCVInstrInfo::getOverlapConstraintsFromMI(MI->getOpcode());
+  if (OverlapConstraints == 2)
+    return RISCVRegisterInfo::isRVVConstraintsType2(DestRegIndex, DestRegLMUL,
+                                                    SrcRegIndex, SrcRegLMUL);
+  if (OverlapConstraints == 3)
+    return RISCVRegisterInfo::isRVVConstraintsType3(DestRegIndex, DestRegLMUL,
+                                                    SrcRegIndex, SrcRegLMUL);
+  return false;
+}
+
+static bool isVectorVirtRegClass(MachineOperand MO, Register R,
+                                 const MachineRegisterInfo *MRI) {
+  // Register like sub_vrm4_0:vrn2m4 also need check.
+  return RISCV::VRRegClass.hasSubClassEq(MRI->getRegClass(R)) ||
----------------
wangpc-pp wrote:

Use isRVVRegClass?

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


More information about the llvm-commits mailing list