[llvm] [GlobalISel] Add a shared matcher for memcpy-family instructions (NFC) (PR #201766)
Cullen Rhodes via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 8 00:22:00 PDT 2026
================
@@ -2078,3 +2081,177 @@ llvm::GFConstant::getConstant(Register Const, const MachineRegisterInfo &MRI) {
return GFConstant(MayBeConstant->Value, GFConstantKind::Scalar);
}
+
+// Returns a list of types to use for memory op lowering in MemOps. A partial
+// port of findOptimalMemOpLowering in TargetLowering.
+static bool findGISelOptimalMemOpLowering(std::vector<LLT> &MemOps,
+ unsigned Limit, const MemOp &Op,
+ unsigned DstAS, unsigned SrcAS,
+ const AttributeList &FuncAttributes,
+ const TargetLowering &TLI) {
+ if (Op.isMemcpyWithFixedDstAlign() && Op.getSrcAlign() < Op.getDstAlign())
+ return false;
+
+ LLT Ty = TLI.getOptimalMemOpLLT(Op, FuncAttributes);
+
+ if (Ty == LLT()) {
+ // Use the largest scalar type whose alignment constraints are satisfied.
+ // We only need to check DstAlign here as SrcAlign is always greater or
+ // equal to DstAlign (or zero).
+ Ty = LLT::integer(64);
+ if (Op.isFixedDstAlign())
+ while (Op.getDstAlign() < Ty.getSizeInBytes() &&
+ !TLI.allowsMisalignedMemoryAccesses(Ty, DstAS, Op.getDstAlign()))
+ Ty = LLT::integer(Ty.getSizeInBytes());
+ assert(Ty.getSizeInBits() > 0 && "Could not find valid type");
+ // FIXME: check for the largest legal type we can load/store to.
+ }
+
+ unsigned NumMemOps = 0;
+ uint64_t Size = Op.size();
+ while (Size) {
+ unsigned TySize = Ty.getSizeInBytes();
+ while (TySize > Size) {
+ // For now, only use non-vector load / store's for the left-over pieces.
+ LLT NewTy = Ty;
+ // FIXME: check for mem op safety and legality of the types. Not all of
+ // SDAGisms map cleanly to GISel concepts.
+ if (NewTy.isVector())
+ NewTy =
+ NewTy.getSizeInBits() > 64 ? LLT::integer(64) : LLT::integer(32);
+ NewTy = LLT::integer(llvm::bit_floor(NewTy.getSizeInBits() - 1));
+ unsigned NewTySize = NewTy.getSizeInBytes();
+ assert(NewTySize > 0 && "Could not find appropriate type");
+
+ // If the new LLT cannot cover all of the remaining bits, then consider
+ // issuing a (or a pair of) unaligned and overlapping load / store.
+ unsigned Fast;
+ // Need to get a VT equivalent for allowMisalignedMemoryAccesses().
+ MVT VT = getMVTForLLT(Ty);
+ if (NumMemOps && Op.allowOverlap() && NewTySize < Size &&
+ TLI.allowsMisalignedMemoryAccesses(
+ VT, DstAS, Op.isFixedDstAlign() ? Op.getDstAlign() : Align(1),
+ MachineMemOperand::MONone, &Fast) &&
+ Fast)
+ TySize = Size;
+ else {
+ Ty = NewTy;
+ TySize = NewTySize;
+ }
+ }
+
+ if (++NumMemOps > Limit)
+ return false;
+
+ MemOps.push_back(Ty);
+ Size -= TySize;
+ }
+
+ return true;
+}
+
+bool llvm::canLowerMemCpyFamily(const MachineInstr &MI,
+ const MachineRegisterInfo &MRI, unsigned MaxLen,
+ Register &Dst, Register &Src,
+ uint64_t &KnownLen, Align &DstAlign,
+ Align &SrcAlign, bool &IsVolatile,
+ bool &DstAlignCanChange,
+ std::vector<LLT> &MemOps) {
+ const unsigned Opc = MI.getOpcode();
+ assert((Opc == TargetOpcode::G_MEMCPY ||
+ Opc == TargetOpcode::G_MEMCPY_INLINE ||
+ Opc == TargetOpcode::G_MEMMOVE || Opc == TargetOpcode::G_MEMSET) &&
+ "Expected memcpy like instruction");
+
+ auto MMOIt = MI.memoperands_begin();
+ const MachineMemOperand *MemOp = *MMOIt;
+
+ DstAlign = MemOp->getBaseAlign();
+ Register Len;
+ std::tie(Dst, Src, Len) = MI.getFirst3Regs();
+
+ if (Opc != TargetOpcode::G_MEMSET) {
+ assert(MMOIt != MI.memoperands_end() && "Expected a second MMO on MI");
+ MemOp = *(++MMOIt);
+ SrcAlign = MemOp->getBaseAlign();
+ }
+
+ // See if this is a constant length copy.
+ auto LenVRegAndVal = getIConstantVRegValWithLookThrough(Len, MRI);
+ if (!LenVRegAndVal) {
+ // FIXME: support dynamically sized G_MEMCPY_INLINE
+ assert(Opc != TargetOpcode::G_MEMCPY_INLINE &&
+ "inline memcpy with dynamic size is not yet supported");
+ return false;
+ }
+
+ KnownLen = LenVRegAndVal->Value.getZExtValue();
+ DstAlignCanChange = false;
+
+ if (KnownLen == 0)
+ return true;
+
+ if (Opc != TargetOpcode::G_MEMCPY_INLINE && MaxLen && KnownLen > MaxLen)
+ return false;
+
+ IsVolatile = MemOp->isVolatile();
----------------
c-rhodes wrote:
I need to drop for an hour so I've reverted it while i fix
https://github.com/llvm/llvm-project/pull/201766
More information about the llvm-commits
mailing list