[llvm] [SystemZ] Improve handling of memmoves. (PR #196285)

Ulrich Weigand via llvm-commits llvm-commits at lists.llvm.org
Fri May 8 07:53:54 PDT 2026


================
@@ -10820,6 +10832,89 @@ SystemZTargetLowering::emitMemMemWrapper(MachineInstr &MI,
   return MBB;
 }
 
+MachineBasicBlock *
+SystemZTargetLowering::emitMemmoveImm(MachineInstr &MI,
+                                      MachineBasicBlock *MBB) const {
+  MachineFunction &MF = *MBB->getParent();
+  const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
+  MachineRegisterInfo &MRI = MF.getRegInfo();
+
+  DebugLoc DL = MI.getDebugLoc();
+  MachineOperand DstBase = earlyUseOperand(MI.getOperand(0));
+  uint64_t DstDisp = MI.getOperand(1).getImm();
+  MachineOperand SrcBase = earlyUseOperand(MI.getOperand(2));
+  uint64_t SrcDisp = MI.getOperand(3).getImm();
+  uint64_t Len = MI.getOperand(4).getImm();
+  assert(Len >= 1 && Len <= 256 &&
+         "Memmove of of unsupported constant length.");
+  assert(isUInt<12>(DstDisp) && isUInt<12>(SrcDisp) &&
+         "Unexpected large displacement.");
+
+  // Fold any displacement (or frame index reference) into a new register.
+  auto foldAddressIfNeeded = [&](MachineOperand &Base, uint64_t &Disp) -> void {
+    if (Disp || Base.isFI()) {
+      Register Reg = MRI.createVirtualRegister(&SystemZ::ADDR64BitRegClass);
+      unsigned Opcode = TII->getOpcodeForOffset(SystemZ::LA, Disp);
+      BuildMI(*MBB, MI, DL, TII->get(Opcode), Reg)
+          .add(Base).addImm(Disp).addReg(0);
+      Base = MachineOperand::CreateReg(Reg, false);
+      Disp = 0;
+    }
+  };
+
+  if (Len <= 15 && MEMMOVEVLL) {
+    Register HighByteReg = MRI.createVirtualRegister(&SystemZ::GR32BitRegClass);
+    BuildMI(*MBB, MI, DL, TII->get(SystemZ::LHI), HighByteReg).addImm(Len - 1);
+
+    Register VecReg = MRI.createVirtualRegister(&SystemZ::VR128BitRegClass);
+    BuildMI(*MBB, MI, DL, TII->get(SystemZ::VLL), VecReg)
+        .addReg(HighByteReg)
+        .add(SrcBase).addImm(SrcDisp);
+
+    BuildMI(*MBB, MI, DL, TII->get(SystemZ::VSTL))
+        .addReg(VecReg)
+        .addReg(HighByteReg)
+        .add(DstBase).addImm(DstDisp);
+
+    MI.eraseFromParent();
+    return MBB;
+  }
+
+  // Use MVC or MVCRL after comparing the addresses.
+  MachineBasicBlock *DoneMBB = SystemZ::splitBlockAfter(MI, MBB);
+  MachineBasicBlock *MvcMBB = SystemZ::emitBlockAfter(MBB);
+  MachineBasicBlock *MvcrlMBB = SystemZ::emitBlockAfter(MvcMBB);
+  MBB->addSuccessor(MvcMBB);
+  MBB->addSuccessor(MvcrlMBB);
+  MvcMBB->addSuccessor(DoneMBB);
+  MvcrlMBB->addSuccessor(DoneMBB);
+
+  // Fold any displacements in order to do the compare.
+  foldAddressIfNeeded(SrcBase, SrcDisp);
+  foldAddressIfNeeded(DstBase, DstDisp);
+
+  BuildMI(MBB, DL, TII->get(SystemZ::CLGR)).add(SrcBase).add(DstBase);
+  BuildMI(MBB, DL, TII->get(SystemZ::BRC))
+      .addImm(SystemZ::CCMASK_ICMP).addImm(SystemZ::CCMASK_CMP_LT)
+      .addMBB(MvcrlMBB);
----------------
uweigand wrote:

I'm wondering if we can constant-fold this comparison and make the decision at run time in some cases.  (That probably would also best be done in EmitTargetCodeForMemmove, though.)

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


More information about the llvm-commits mailing list