[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