[llvm] [GlobalISel] Implement `llvm.memset.inline` (PR #203198)
Ömer Sinan Ağacan via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 12 06:58:14 PDT 2026
https://github.com/osa1 updated https://github.com/llvm/llvm-project/pull/203198
>From 303949d0a02ddfd66e17776d4551c672faebe8e7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 17:09:36 +0100
Subject: [PATCH 01/13] Implement G_MEMSET_INLINE, legalize in AArch64
---
.../llvm/CodeGen/GlobalISel/CombinerHelper.h | 4 +++
.../llvm/CodeGen/GlobalISel/LegalizerHelper.h | 2 +-
llvm/include/llvm/Support/TargetOpcodes.def | 3 +++
llvm/include/llvm/Target/GenericOpcodes.td | 7 ++++++
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 8 ++++++
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 5 +++-
.../CodeGen/GlobalISel/LegalizerHelper.cpp | 25 ++++++++++++-------
.../AArch64/GISel/AArch64LegalizerInfo.cpp | 3 +++
.../GISel/AArch64PreLegalizerCombiner.cpp | 2 ++
9 files changed, 48 insertions(+), 11 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index aa61310994a67..f744a61285c4a 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -866,6 +866,10 @@ class CombinerHelper {
/// and rename: s/bool tryEmit/void emit/
LLVM_ABI bool tryEmitMemcpyInline(MachineInstr &MI) const;
+ /// Emit stores that perform the given memset.
+ /// Assumes \p MI is a G_MEMSET_INLINE
+ LLVM_ABI bool tryEmitMemsetInline(MachineInstr &MI) const;
+
/// Match:
/// (G_UMULO x, 2) -> (G_UADDO x, x)
/// (G_SMULO x, 2) -> (G_SADDO x, x)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
index 47d7da7a0eb52..e33b534067229 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/LegalizerHelper.h
@@ -304,7 +304,7 @@ class LegalizerHelper {
// Memcpy family legalization helpers.
LegalizeResult lowerMemset(MachineInstr &MI, Register Dst, Register Val,
- uint64_t KnownLen, Align Alignment,
+ uint64_t KnownLen, uint64_t Limit, Align Alignment,
bool IsVolatile);
LegalizeResult lowerMemcpy(MachineInstr &MI, Register Dst, Register Src,
uint64_t KnownLen, uint64_t Limit, Align DstAlign,
diff --git a/llvm/include/llvm/Support/TargetOpcodes.def b/llvm/include/llvm/Support/TargetOpcodes.def
index 19b48cb9765ff..051cea764e5a0 100644
--- a/llvm/include/llvm/Support/TargetOpcodes.def
+++ b/llvm/include/llvm/Support/TargetOpcodes.def
@@ -959,6 +959,9 @@ HANDLE_TARGET_OPCODE(G_MEMMOVE)
HANDLE_TARGET_OPCODE(G_MEMSET)
HANDLE_TARGET_OPCODE(G_BZERO)
+/// llvm.memset.inline intrinsic
+HANDLE_TARGET_OPCODE(G_MEMSET_INLINE)
+
/// llvm.trap, llvm.debugtrap and llvm.ubsantrap intrinsics
HANDLE_TARGET_OPCODE(G_TRAP)
HANDLE_TARGET_OPCODE(G_DEBUGTRAP)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index b0edb462f0f9d..e22813021b409 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1863,6 +1863,13 @@ def G_BZERO : GenericInstruction {
let mayStore = true;
}
+def G_MEMSET_INLINE : GenericInstruction {
+ let OutOperandList = (outs);
+ let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
+ let hasSideEffects = false;
+ let mayStore = true;
+}
+
//------------------------------------------------------------------------------
// Trap intrinsics
//------------------------------------------------------------------------------
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 88b68d7685c63..f7159ad0617b6 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1729,6 +1729,14 @@ bool CombinerHelper::tryEmitMemcpyInline(MachineInstr &MI) const {
LegalizerHelper::LegalizeResult::Legalized;
}
+bool CombinerHelper::tryEmitMemsetInline(MachineInstr &MI) const {
+ MachineIRBuilder HelperBuilder(MI);
+ GISelObserverWrapper DummyObserver;
+ LegalizerHelper Helper(HelperBuilder.getMF(), DummyObserver, HelperBuilder);
+ return Helper.lowerMemCpyFamily(MI) ==
+ LegalizerHelper::LegalizeResult::Legalized;
+}
+
bool CombinerHelper::tryCombineMemCpyFamily(MachineInstr &MI,
unsigned MaxLen) const {
MachineIRBuilder HelperBuilder(MI);
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 28755da8327aa..7e4e209c727e5 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1835,7 +1835,8 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
ICall.addMemOperand(
MF->getMachineMemOperand(MachinePointerInfo(CI.getArgOperand(0)),
StoreFlags, 1, DstAlign, AAInfo));
- if (Opcode != TargetOpcode::G_MEMSET)
+ if (Opcode != TargetOpcode::G_MEMSET &&
+ Opcode != TargetOpcode::G_MEMSET_INLINE)
ICall.addMemOperand(MF->getMachineMemOperand(
MachinePointerInfo(SrcPtr), LoadFlags, 1, SrcAlign, AAInfo));
@@ -2445,6 +2446,8 @@ bool IRTranslator::translateKnownIntrinsic(const CallInst &CI, Intrinsic::ID ID,
return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMMOVE);
case Intrinsic::memset:
return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMSET);
+ case Intrinsic::memset_inline:
+ return translateMemFunc(CI, MIRBuilder, TargetOpcode::G_MEMSET_INLINE);
case Intrinsic::eh_typeid_for: {
GlobalValue *GV = ExtractTypeInfo(CI.getArgOperand(0));
Register Reg = getOrCreateVReg(CI);
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index afe93f617a119..8dc6e637334cb 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -10811,7 +10811,7 @@ static Register getMemsetValue(Register Val, LLT Ty, MachineIRBuilder &MIB) {
LegalizerHelper::LegalizeResult
LegalizerHelper::lowerMemset(MachineInstr &MI, Register Dst, Register Val,
- uint64_t KnownLen, Align Alignment,
+ uint64_t KnownLen, uint64_t Limit, Align Alignment,
bool IsVolatile) {
auto &MF = *MI.getParent()->getParent();
const auto &TLI = *MF.getSubtarget().getTargetLowering();
@@ -10822,13 +10822,11 @@ LegalizerHelper::lowerMemset(MachineInstr &MI, Register Dst, Register Val,
bool DstAlignCanChange = false;
MachineFrameInfo &MFI = MF.getFrameInfo();
- bool OptSize = shouldLowerMemFuncForSize(MF);
MachineInstr *FIDef = getOpcodeDef(TargetOpcode::G_FRAME_INDEX, Dst, MRI);
if (FIDef && !MFI.isFixedObjectIndex(FIDef->getOperand(1).getIndex()))
DstAlignCanChange = true;
- unsigned Limit = TLI.getMaxStoresPerMemset(OptSize);
std::vector<LLT> MemOps;
const auto &DstMMO = **MI.memoperands_begin();
@@ -11143,7 +11141,8 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
// matcher function.
assert((Opc == TargetOpcode::G_MEMCPY ||
Opc == TargetOpcode::G_MEMCPY_INLINE ||
- Opc == TargetOpcode::G_MEMMOVE || Opc == TargetOpcode::G_MEMSET) &&
+ Opc == TargetOpcode::G_MEMMOVE || Opc == TargetOpcode::G_MEMSET ||
+ Opc == TargetOpcode::G_MEMSET_INLINE) &&
"Expected memcpy like instruction");
auto MMOIt = MI.memoperands_begin();
@@ -11153,7 +11152,7 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
Align SrcAlign;
auto [Dst, Src, Len] = MI.getFirst3Regs();
- if (Opc != TargetOpcode::G_MEMSET) {
+ if (Opc != TargetOpcode::G_MEMSET && Opc != TargetOpcode::G_MEMSET_INLINE) {
assert(MMOIt != MI.memoperands_end() && "Expected a second MMO on MI");
MemOp = *(++MMOIt);
SrcAlign = MemOp->getBaseAlign();
@@ -11162,8 +11161,9 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
// See if this is a constant length copy
auto LenVRegAndVal = getIConstantVRegValWithLookThrough(Len, MRI);
if (!LenVRegAndVal) {
- // FIXME: support dynamically sized G_MEMCPY_INLINE
+ // FIXME: support dynamically sized G_MEMCPY_INLINE and G_MEMSET_INLINE
assert(Opc != TargetOpcode::G_MEMCPY_INLINE &&
+ Opc != TargetOpcode::G_MEMSET_INLINE &&
"inline memcpy with dynamic size is not yet supported");
return UnableToLegalize;
}
@@ -11174,7 +11174,8 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
return Legalized;
}
- if (Opc != TargetOpcode::G_MEMCPY_INLINE && MaxLen && KnownLen > MaxLen)
+ if (Opc != TargetOpcode::G_MEMCPY_INLINE &&
+ Opc != TargetOpcode::G_MEMSET_INLINE && MaxLen && KnownLen > MaxLen)
return UnableToLegalize;
bool IsVolatile = MemOp->isVolatile();
@@ -11190,7 +11191,13 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
}
if (Opc == TargetOpcode::G_MEMMOVE)
return lowerMemmove(MI, Dst, Src, KnownLen, DstAlign, SrcAlign, IsVolatile);
- if (Opc == TargetOpcode::G_MEMSET)
- return lowerMemset(MI, Dst, Src, KnownLen, DstAlign, IsVolatile);
+ if (Opc == TargetOpcode::G_MEMSET || Opc == TargetOpcode::G_MEMSET_INLINE) {
+ auto &MF = *MI.getParent()->getParent();
+ bool OptSize = shouldLowerMemFuncForSize(MF);
+ uint64_t Limit = Opc == TargetOpcode::G_MEMSET_INLINE
+ ? std::numeric_limits<uint64_t>::max()
+ : TLI.getMaxStoresPerMemset(OptSize);
+ return lowerMemset(MI, Dst, Src, KnownLen, Limit, DstAlign, IsVolatile);
+ }
return UnableToLegalize;
}
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index c0756ab66cb49..eca93c51760ac 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1376,6 +1376,9 @@ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
getActionDefinitionsBuilder(G_MEMCPY_INLINE)
.legalForCartesianProduct({p0}, {p0}, {s64});
+ getActionDefinitionsBuilder(G_MEMSET_INLINE)
+ .legalForCartesianProduct({p0}, {s64}, {s64})
+ .customForCartesianProduct({p0}, {s8}, {s64});
} else {
getActionDefinitionsBuilder({G_BZERO, G_MEMCPY, G_MEMMOVE, G_MEMSET})
.libcall();
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
index d8aae8bf420aa..cf4c1546efdfd 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
@@ -793,6 +793,8 @@ bool AArch64PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
switch (Opc) {
case TargetOpcode::G_MEMCPY_INLINE:
return Helper.tryEmitMemcpyInline(MI);
+ case TargetOpcode::G_MEMSET_INLINE:
+ return Helper.tryEmitMemsetInline(MI);
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET: {
>From b8b9d8c33d33583a83bea48e12fdd30f636d9a31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 17:22:01 +0100
Subject: [PATCH 02/13] Add more handling around existing G_MEMCPY_INLINE code
---
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 2 ++
llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp | 3 ++-
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 1 +
llvm/lib/CodeGen/MachineVerifier.cpp | 4 +++-
llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp | 2 ++
.../Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp | 2 ++
llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp | 3 ++-
llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp | 2 ++
llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 2 ++
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 1 +
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 2 +-
11 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index f744a61285c4a..da127baeff08c 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -868,6 +868,8 @@ class CombinerHelper {
/// Emit stores that perform the given memset.
/// Assumes \p MI is a G_MEMSET_INLINE
+ /// TODO: implement dynamically sized inline memset,
+ /// and rename: s/bool tryEmit/void emit/
LLVM_ABI bool tryEmitMemsetInline(MachineInstr &MI) const;
/// Match:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 7e4e209c727e5..4547b0c41cb96 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -1805,7 +1805,8 @@ bool IRTranslator::translateMemFunc(const CallInst &CI,
DstAlign = MSI->getDestAlign().valueOrOne();
}
- if (Opcode != TargetOpcode::G_MEMCPY_INLINE) {
+ if (Opcode != TargetOpcode::G_MEMCPY_INLINE &&
+ Opcode != TargetOpcode::G_MEMSET_INLINE) {
// We need to propagate the tail call flag from the IR inst as an argument.
// Otherwise, we have to pessimize and assume later that we cannot tail call
// any memory intrinsics.
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 8dc6e637334cb..4dc2fcb951c8a 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -4947,6 +4947,7 @@ LegalizerHelper::lower(MachineInstr &MI, unsigned TypeIdx, LLT LowerHintTy) {
case G_MEMCPY:
case G_MEMMOVE:
case G_MEMCPY_INLINE:
+ case G_MEMSET_INLINE:
return lowerMemCpyFamily(MI);
case G_ZEXT:
case G_SEXT:
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index c611b837a86b4..5c68851c2e122 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2128,7 +2128,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
break;
}
case TargetOpcode::G_BZERO:
- case TargetOpcode::G_MEMSET: {
+ case TargetOpcode::G_MEMSET:
+ case TargetOpcode::G_MEMSET_INLINE:
+ {
ArrayRef<MachineMemOperand *> MMOs = MI->memoperands();
std::string Name = Opc == TargetOpcode::G_MEMSET ? "memset" : "bzero";
if (MMOs.size() != 1) {
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index cf650fd5c4e72..4f4c999ab244d 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -3603,6 +3603,7 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
case TargetOpcode::G_MEMCPY_INLINE:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET:
+ case TargetOpcode::G_MEMSET_INLINE:
assert(STI.hasMOPS() && "Shouldn't get here without +mops feature");
return selectMOPS(I, MRI);
}
@@ -3629,6 +3630,7 @@ bool AArch64InstructionSelector::selectMOPS(MachineInstr &GI,
Mopcode = AArch64::MOPSMemoryMovePseudo;
break;
case TargetOpcode::G_MEMSET:
+ case TargetOpcode::G_MEMSET_INLINE:
// For tagged memset see llvm.aarch64.mops.memset.tag
Mopcode = AArch64::MOPSMemorySetPseudo;
break;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
index 613cf24ed0aa6..3bca9053ca429 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
@@ -96,6 +96,8 @@ bool AArch64O0PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
switch (Opc) {
case TargetOpcode::G_MEMCPY_INLINE:
return Helper.tryEmitMemcpyInline(MI);
+ case TargetOpcode::G_MEMSET_INLINE:
+ return Helper.tryEmitMemsetInline(MI);
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET: {
diff --git a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
index e341392ae068a..84ed533863fd9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPULegalizerInfo.cpp
@@ -2238,7 +2238,8 @@ AMDGPULegalizerInfo::AMDGPULegalizerInfo(const GCNSubtarget &ST_,
.lower();
}
- getActionDefinitionsBuilder({G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET})
+ getActionDefinitionsBuilder(
+ {G_MEMCPY, G_MEMCPY_INLINE, G_MEMMOVE, G_MEMSET, G_MEMSET_INLINE})
.lower();
getActionDefinitionsBuilder({G_TRAP, G_DEBUGTRAP}).custom();
diff --git a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
index 5ada356de7e44..43cf18517026b 100644
--- a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
@@ -59,6 +59,8 @@ class MipsPreLegalizerCombinerImpl : public Combiner {
return false;
case TargetOpcode::G_MEMCPY_INLINE:
return Helper.tryEmitMemcpyInline(MI);
+ case TargetOpcode::G_MEMSET_INLINE:
+ return Helper.tryEmitMemsetInline(MI);
case TargetOpcode::G_LOAD:
case TargetOpcode::G_SEXTLOAD:
case TargetOpcode::G_ZEXTLOAD: {
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 716fab95eb943..305f977d14914 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -529,6 +529,8 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
getActionDefinitionsBuilder(G_MEMCPY_INLINE).lower();
+ getActionDefinitionsBuilder(G_MEMSET_INLINE).lower();
+
getActionDefinitionsBuilder({G_DYN_STACKALLOC, G_STACKSAVE, G_STACKRESTORE})
.lower();
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79577505157fd..e87cb961a83a8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1042,6 +1042,7 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMCPY_INLINE:
case TargetOpcode::G_MEMSET:
+ case TargetOpcode::G_MEMSET_INLINE:
return selectMemOperation(ResVReg, I);
case TargetOpcode::G_ICMP:
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 6c9b7eb2ef37e..116f861d341c8 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -307,7 +307,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.unsupportedIf(LegalityPredicates::any(typeIs(0, p9), typeIs(1, p9)))
.legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allPtrs)));
- getActionDefinitionsBuilder(G_MEMSET)
+ getActionDefinitionsBuilder(G_MEMSET, G_MEMSET_INLINE)
.unsupportedIf(typeIs(0, p9))
.legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allIntScalars)));
>From a7474f737307b9e201a39e0e731aa45065ed8a5e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 17:27:52 +0100
Subject: [PATCH 03/13] Fix errors
---
llvm/include/llvm/Target/GenericOpcodes.td | 2 +-
llvm/lib/CodeGen/MachineVerifier.cpp | 4 +++-
llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp | 2 +-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/llvm/include/llvm/Target/GenericOpcodes.td b/llvm/include/llvm/Target/GenericOpcodes.td
index e22813021b409..8270ae7690953 100644
--- a/llvm/include/llvm/Target/GenericOpcodes.td
+++ b/llvm/include/llvm/Target/GenericOpcodes.td
@@ -1865,7 +1865,7 @@ def G_BZERO : GenericInstruction {
def G_MEMSET_INLINE : GenericInstruction {
let OutOperandList = (outs);
- let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size, untyped_imm_0:$tailcall);
+ let InOperandList = (ins ptype0:$dst_addr, type1:$value, type2:$size);
let hasSideEffects = false;
let mayStore = true;
}
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 5c68851c2e122..313c1d305c922 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2132,7 +2132,9 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
case TargetOpcode::G_MEMSET_INLINE:
{
ArrayRef<MachineMemOperand *> MMOs = MI->memoperands();
- std::string Name = Opc == TargetOpcode::G_MEMSET ? "memset" : "bzero";
+ std::string Name = Opc == TargetOpcode::G_MEMSET ? "memset"
+ : Opc == TargetOpcode::G_MEMSET_INLINE ? "memset_inline"
+ : "bzero";
if (MMOs.size() != 1) {
report(Twine(Name, " must have 1 memory operand"), MI);
break;
diff --git a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
index 116f861d341c8..512d1494a7b36 100644
--- a/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVLegalizerInfo.cpp
@@ -307,7 +307,7 @@ SPIRVLegalizerInfo::SPIRVLegalizerInfo(const SPIRVSubtarget &ST) {
.unsupportedIf(LegalityPredicates::any(typeIs(0, p9), typeIs(1, p9)))
.legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allPtrs)));
- getActionDefinitionsBuilder(G_MEMSET, G_MEMSET_INLINE)
+ getActionDefinitionsBuilder({G_MEMSET, G_MEMSET_INLINE})
.unsupportedIf(typeIs(0, p9))
.legalIf(all(typeInSet(0, allPtrs), typeInSet(1, allIntScalars)));
>From 68da09702a287ebae834172e13070be3eaee2bd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 17:31:45 +0100
Subject: [PATCH 04/13] More missing memset_inline handling
---
llvm/lib/CodeGen/MachineVerifier.cpp | 7 ++++---
llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 3 ++-
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 313c1d305c922..f68ff34654ffe 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2154,9 +2154,10 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
if (DstPtrTy.getAddressSpace() != MMOs[0]->getAddrSpace())
report("inconsistent " + Twine(Name, " address space"), MI);
- if (!MI->getOperand(MI->getNumOperands() - 1).isImm() ||
- (MI->getOperand(MI->getNumOperands() - 1).getImm() & ~1LL))
- report("'tail' flag (last operand) must be an immediate 0 or 1", MI);
+ if (Opc != TargetOpcode::G_MEMSET_INLINE)
+ if (!MI->getOperand(MI->getNumOperands() - 1).isImm() ||
+ (MI->getOperand(MI->getNumOperands() - 1).getImm() & ~1LL))
+ report("'tail' flag (last operand) must be an immediate 0 or 1", MI);
break;
}
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index e87cb961a83a8..2841fd38f5b04 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2330,7 +2330,8 @@ bool SPIRVInstructionSelector::selectMemOperation(Register ResVReg,
return true;
Register SrcReg = I.getOperand(1).getReg();
- if (I.getOpcode() == TargetOpcode::G_MEMSET) {
+ if (I.getOpcode() == TargetOpcode::G_MEMSET ||
+ I.getOpcode() == TargetOpcode::G_MEMSET_INLINE) {
Register VarReg = getOrCreateMemSetGlobal(I);
if (!VarReg.isValid())
return false;
>From 9f5a4cf0d0a05bc445ea0420b45af00e106e2a1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 18:11:50 +0100
Subject: [PATCH 05/13] Tests
---
.../GlobalISel/inline-memset-forced.mir | 75 ++++++++++
.../GlobalISel/irtranslator-memset-inline.ll | 141 ++++++++++++++++++
.../GlobalISel/legalize-memsetinline.mir | 59 ++++++++
.../AMDGPU/GlobalISel/llvm.memset.inline.ll | 20 +++
.../inline-memset.mir | 57 +++++++
.../legalizer/legalize-memset-inline.mir | 44 ++++++
.../CodeGen/RISCV/GlobalISel/memset-inline.ll | 69 +++++++++
7 files changed, 465 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-memsetinline.mir
create mode 100644 llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.memset.inline.ll
create mode 100644 llvm/test/CodeGen/Mips/GlobalISel/mips-prelegalizer-combiner/inline-memset.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-memset-inline.mir
create mode 100644 llvm/test/CodeGen/RISCV/GlobalISel/memset-inline.ll
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir b/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
new file mode 100644
index 0000000000000..bce7d6fe3c094
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
@@ -0,0 +1,75 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+--- |
+ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+ target triple = "arm64-apple-darwin"
+
+ declare void @llvm.memset.inline.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0
+
+ define void @test_memset_inline(ptr nocapture %dst, i8 %val) local_unnamed_addr {
+ entry:
+ tail call void @llvm.memset.inline.p0.i64(ptr align 4 %dst, i8 %val, i64 143, i1 false)
+ ret void
+ }
+
+ attributes #0 = { argmemonly nounwind }
+
+...
+---
+name: test_memset_inline
+alignment: 4
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _ }
+ - { id: 1, class: _ }
+ - { id: 2, class: _ }
+ - { id: 3, class: _ }
+machineFunctionInfo: {}
+body: |
+ bb.1.entry:
+ liveins: $w1, $x0
+
+ ; CHECK-LABEL: name: test_memset_inline
+ ; CHECK: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[TRUNC]](i8)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 72340172838076673
+ ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(i64) = G_MUL [[ZEXT]], [[C]]
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[MUL]](i64), [[MUL]](i64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[COPY]](p0) :: (store (<2 x i64>) into %ir.dst, align 4)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C1]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD]](p0) :: (store (<2 x i64>) into %ir.dst + 16, align 4)
+ ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
+ ; CHECK-NEXT: [[PTR_ADD1:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C2]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD1]](p0) :: (store (<2 x i64>) into %ir.dst + 32, align 4)
+ ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 48
+ ; CHECK-NEXT: [[PTR_ADD2:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C3]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD2]](p0) :: (store (<2 x i64>) into %ir.dst + 48, align 4)
+ ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 64
+ ; CHECK-NEXT: [[PTR_ADD3:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C4]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD3]](p0) :: (store (<2 x i64>) into %ir.dst + 64, align 4)
+ ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 80
+ ; CHECK-NEXT: [[PTR_ADD4:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C5]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD4]](p0) :: (store (<2 x i64>) into %ir.dst + 80, align 4)
+ ; CHECK-NEXT: [[C6:%[0-9]+]]:_(s64) = G_CONSTANT i64 96
+ ; CHECK-NEXT: [[PTR_ADD5:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C6]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD5]](p0) :: (store (<2 x i64>) into %ir.dst + 96, align 4)
+ ; CHECK-NEXT: [[C7:%[0-9]+]]:_(s64) = G_CONSTANT i64 112
+ ; CHECK-NEXT: [[PTR_ADD6:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C7]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD6]](p0) :: (store (<2 x i64>) into %ir.dst + 112, align 4)
+ ; CHECK-NEXT: [[C8:%[0-9]+]]:_(s64) = G_CONSTANT i64 127
+ ; CHECK-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C8]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD7]](p0) :: (store (<2 x i64>) into %ir.dst + 127, align 1, basealign 4)
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(i32) = COPY $w1
+ %2:_(i8) = G_TRUNC %1(i32)
+ %3:_(s64) = G_CONSTANT i64 143
+ G_MEMSET_INLINE %0(p0), %2(i8), %3(s64) :: (store (s8) into %ir.dst, align 4)
+ RET_ReallyLR
+
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
new file mode 100644
index 0000000000000..cd67cc8af4367
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
@@ -0,0 +1,141 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=irtranslator %s -o - | FileCheck %s
+
+define void @memset(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: memset
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64), 0 :: (store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 4, i1 false)
+ ret void
+}
+
+define void @inline_memset(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: inline_memset
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET_INLINE [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64) :: (store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.memset.inline.p0.i32(ptr %dst, i8 %val, i32 4, i1 false)
+ ret void
+}
+
+define void @memset_volatile(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: memset_volatile
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64), 0 :: (volatile store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 4, i1 true)
+ ret void
+}
+
+define void @inline_memset_volatile(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: inline_memset_volatile
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET_INLINE [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64) :: (volatile store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ call void @llvm.memset.inline.p0.i32(ptr %dst, i8 %val, i32 4, i1 true)
+ ret void
+}
+
+define void @tail_memset(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: tail_memset
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64), 1 :: (store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ tail call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 4, i1 false)
+ ret void
+}
+
+define void @tail_inline_memset(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: tail_inline_memset
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET_INLINE [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64) :: (store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ tail call void @llvm.memset.inline.p0.i32(ptr %dst, i8 %val, i32 4, i1 false)
+ ret void
+}
+
+define void @tail_memset_volatile(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: tail_memset_volatile
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64), 1 :: (volatile store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ tail call void @llvm.memset.p0.i32(ptr %dst, i8 %val, i32 4, i1 true)
+ ret void
+}
+
+define void @tail_inline_memset_volatile(ptr %dst, i8 %val) {
+ ; CHECK-LABEL: name: tail_inline_memset_volatile
+ ; CHECK: bb.1.entry:
+ ; CHECK-NEXT: liveins: $w1, $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(i32) = COPY $w1
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(i8) = G_TRUNC [[COPY1]](i32)
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i32) = G_CONSTANT i32 4
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(i64) = G_ZEXT [[C]](i32)
+ ; CHECK-NEXT: G_MEMSET_INLINE [[COPY]](p0), [[TRUNC]](i8), [[ZEXT]](i64) :: (volatile store (s8) into %ir.dst)
+ ; CHECK-NEXT: RET_ReallyLR
+entry:
+ tail call void @llvm.memset.inline.p0.i32(ptr %dst, i8 %val, i32 4, i1 true)
+ ret void
+}
+
+declare void @llvm.memset.p0.i32(ptr nocapture writeonly, i8, i32, i1) nounwind
+declare void @llvm.memset.inline.p0.i32(ptr nocapture writeonly, i8, i32, i1) nounwind
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-memsetinline.mir b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-memsetinline.mir
new file mode 100644
index 0000000000000..e689bc107a07b
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/legalize-memsetinline.mir
@@ -0,0 +1,59 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=amdgcn-- -run-pass=legalizer -verify-machineinstrs -o - %s | FileCheck %s
+
+---
+name: memsetinline_test
+body: |
+ bb.0:
+ liveins: $vgpr0, $vgpr1, $vgpr2
+
+ ; CHECK-LABEL: name: memsetinline_test
+ ; CHECK: liveins: $vgpr0, $vgpr1, $vgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1
+ ; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32)
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s8) = COPY [[TRUNC]](s8)
+ ; CHECK-NEXT: G_STORE [[COPY2]](s32), [[MV]](p0) :: (store (s8))
+ ; CHECK-NEXT: S_ENDPGM 0
+ %0:_(s32) = COPY $vgpr0
+ %1:_(s32) = COPY $vgpr1
+ %2:_(p0) = G_MERGE_VALUES %0:_(s32), %1:_(s32)
+ %3:_(s32) = COPY $vgpr2
+ %4:_(s8) = G_TRUNC %3:_(s32)
+ %5:_(s32) = G_CONSTANT i32 1
+ %6:_(s64) = G_ZEXT %5:_(s32)
+ G_MEMSET_INLINE %2:_(p0), %4:_(s8), %6:_(s64) :: (store (s8))
+ S_ENDPGM 0
+
+...
+---
+name: memsetinline_test_volatile
+body: |
+ bb.0:
+ liveins: $vgpr0, $vgpr1, $vgpr2
+
+ ; CHECK-LABEL: name: memsetinline_test_volatile
+ ; CHECK: liveins: $vgpr0, $vgpr1, $vgpr2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $vgpr0
+ ; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $vgpr1
+ ; CHECK-NEXT: [[MV:%[0-9]+]]:_(p0) = G_MERGE_VALUES [[COPY]](s32), [[COPY1]](s32)
+ ; CHECK-NEXT: [[COPY2:%[0-9]+]]:_(s32) = COPY $vgpr2
+ ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY2]](s32)
+ ; CHECK-NEXT: [[COPY3:%[0-9]+]]:_(s8) = COPY [[TRUNC]](s8)
+ ; CHECK-NEXT: G_STORE [[COPY2]](s32), [[MV]](p0) :: (volatile store (s8))
+ ; CHECK-NEXT: S_ENDPGM 0
+ %0:_(s32) = COPY $vgpr0
+ %1:_(s32) = COPY $vgpr1
+ %2:_(p0) = G_MERGE_VALUES %0:_(s32), %1:_(s32)
+ %3:_(s32) = COPY $vgpr2
+ %4:_(s8) = G_TRUNC %3:_(s32)
+ %5:_(s32) = G_CONSTANT i32 1
+ %6:_(s64) = G_ZEXT %5:_(s32)
+ G_MEMSET_INLINE %2:_(p0), %4:_(s8), %6:_(s64) :: (volatile store (s8))
+ S_ENDPGM 0
+
+...
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.memset.inline.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.memset.inline.ll
new file mode 100644
index 0000000000000..1e73bc416f795
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.memset.inline.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mem-intrinsic-expand-size=3 %s -o - | FileCheck -check-prefix=GCN %s
+; RUN: llc -global-isel -new-reg-bank-select -mtriple=amdgcn -mem-intrinsic-expand-size=5 %s -o - | FileCheck -check-prefix=GCN %s
+
+declare void @llvm.memset.inline.p1.i32(ptr addrspace(1), i8, i32, i1 immarg)
+
+define amdgpu_cs void @test(ptr addrspace(1) %dst, i8 %val) {
+; GCN-LABEL: test:
+; GCN: ; %bb.0:
+; GCN-NEXT: s_mov_b32 s2, 0
+; GCN-NEXT: s_mov_b32 s3, 0xf000
+; GCN-NEXT: s_mov_b64 s[0:1], 0
+; GCN-NEXT: buffer_store_byte v2, v[0:1], s[0:3], 0 addr64
+; GCN-NEXT: buffer_store_byte v2, v[0:1], s[0:3], 0 addr64 offset:1
+; GCN-NEXT: buffer_store_byte v2, v[0:1], s[0:3], 0 addr64 offset:2
+; GCN-NEXT: buffer_store_byte v2, v[0:1], s[0:3], 0 addr64 offset:3
+; GCN-NEXT: s_endpgm
+ call void @llvm.memset.inline.p1.i32(ptr addrspace(1) %dst, i8 %val, i32 4, i1 false)
+ ret void
+}
diff --git a/llvm/test/CodeGen/Mips/GlobalISel/mips-prelegalizer-combiner/inline-memset.mir b/llvm/test/CodeGen/Mips/GlobalISel/mips-prelegalizer-combiner/inline-memset.mir
new file mode 100644
index 0000000000000..48a8052da0d72
--- /dev/null
+++ b/llvm/test/CodeGen/Mips/GlobalISel/mips-prelegalizer-combiner/inline-memset.mir
@@ -0,0 +1,57 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -O0 -mtriple=mipsel-linux-gnu -run-pass=mips-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=MIPS32
+--- |
+ target datalayout = "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"
+ target triple = "mipsel-pc-linux-gnu"
+
+ declare void @llvm.memset.inline.p0.i64(ptr noalias nocapture writeonly, i8, i64 immarg, i1 immarg) #0
+
+ define void @test_memset_inline(ptr nocapture %dst, i8 %val) local_unnamed_addr {
+ entry:
+ tail call void @llvm.memset.inline.p0.i64(ptr align 4 %dst, i8 %val, i64 2, i1 false)
+ ret void
+ }
+
+ attributes #0 = { argmemonly nofree nounwind willreturn }
+
+...
+---
+name: test_memset_inline
+alignment: 4
+tracksRegLiveness: true
+registers:
+ - { id: 0, class: _ }
+ - { id: 1, class: _ }
+ - { id: 2, class: _ }
+ - { id: 3, class: _ }
+ - { id: 4, class: _ }
+liveins:
+ - { reg: '$a0' }
+ - { reg: '$a1' }
+frameInfo:
+ maxAlignment: 1
+machineFunctionInfo: {}
+body: |
+ bb.1.entry:
+ liveins: $a0, $a1
+
+ ; MIPS32-LABEL: name: test_memset_inline
+ ; MIPS32: liveins: $a0, $a1
+ ; MIPS32-NEXT: {{ $}}
+ ; MIPS32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $a0
+ ; MIPS32-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $a1
+ ; MIPS32-NEXT: [[TRUNC:%[0-9]+]]:_(s8) = G_TRUNC [[COPY1]](s32)
+ ; MIPS32-NEXT: G_STORE [[TRUNC]](s8), [[COPY]](p0) :: (store (s8) into %ir.dst, align 4)
+ ; MIPS32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; MIPS32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C]](s32)
+ ; MIPS32-NEXT: G_STORE [[TRUNC]](s8), [[PTR_ADD]](p0) :: (store (s8) into %ir.dst + 1, basealign 4)
+ ; MIPS32-NEXT: RetRA
+ %0:_(p0) = COPY $a0
+ %1:_(s32) = COPY $a1
+ %2:_(s8) = G_TRUNC %1(s32)
+ %3:_(s64) = G_CONSTANT i64 2
+ %4:_(s32) = G_TRUNC %3(s64)
+ G_MEMSET_INLINE %0(p0), %2(s8), %4(s32) :: (store (s8) into %ir.dst, align 4)
+ RetRA
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-memset-inline.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-memset-inline.mir
new file mode 100644
index 0000000000000..dd4b9a57c9b32
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer/legalize-memset-inline.mir
@@ -0,0 +1,44 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=riscv32 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=RISCV32
+# RUN: llc -mtriple=riscv64 -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=RISCV64
+
+---
+name: test_memset_inline
+alignment: 4
+liveins:
+ - { reg: '$x10', virtual-reg: '' }
+body: |
+ bb.0.entry:
+ liveins: $x10
+ ; RISCV32-LABEL: name: test_memset_inline
+ ; RISCV32: liveins: $x10
+ ; RISCV32-NEXT: {{ $}}
+ ; RISCV32-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
+ ; RISCV32-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+ ; RISCV32-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s32)
+ ; RISCV32-NEXT: G_STORE [[TRUNC]](s16), [[COPY]](p0) :: (store (s8), align 4)
+ ; RISCV32-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+ ; RISCV32-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C1]](s32)
+ ; RISCV32-NEXT: G_STORE [[TRUNC]](s16), [[PTR_ADD]](p0) :: (store (s8) into unknown-address + 1)
+ ; RISCV32-NEXT: PseudoRET
+ ;
+ ; RISCV64-LABEL: name: test_memset_inline
+ ; RISCV64: liveins: $x10
+ ; RISCV64-NEXT: {{ $}}
+ ; RISCV64-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x10
+ ; RISCV64-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 7
+ ; RISCV64-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = G_TRUNC [[C]](s64)
+ ; RISCV64-NEXT: G_STORE [[TRUNC]](s16), [[COPY]](p0) :: (store (s8), align 4)
+ ; RISCV64-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+ ; RISCV64-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C1]](s64)
+ ; RISCV64-NEXT: G_STORE [[TRUNC]](s16), [[PTR_ADD]](p0) :: (store (s8) into unknown-address + 1)
+ ; RISCV64-NEXT: PseudoRET
+ %0:_(p0) = COPY $x10
+ %1:_(s64) = G_CONSTANT i64 7
+ %2:_(s8) = G_TRUNC %1(s64)
+ %3:_(s64) = G_CONSTANT i64 2
+ %4:_(s32) = G_TRUNC %3(s64)
+ G_MEMSET_INLINE %0(p0), %2(s8), %4(s32) :: (store (s8), align 4)
+ PseudoRET
+
+...
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/memset-inline.ll b/llvm/test/CodeGen/RISCV/GlobalISel/memset-inline.ll
new file mode 100644
index 0000000000000..50f1f6cf9a24d
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/memset-inline.ll
@@ -0,0 +1,69 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -global-isel -mtriple=riscv32 < %s \
+; RUN: | FileCheck -check-prefix=RV32I %s
+; RUN: llc -global-isel -mtriple=riscv64 < %s \
+; RUN: | FileCheck -check-prefix=RV64I %s
+
+define void @test_memset_inline_2bytes(ptr %dst, i8 %val) {
+; RV32I-LABEL: test_memset_inline_2bytes:
+; RV32I: # %bb.0:
+; RV32I-NEXT: sb a1, 0(a0)
+; RV32I-NEXT: sb a1, 1(a0)
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: test_memset_inline_2bytes:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sb a1, 0(a0)
+; RV64I-NEXT: sb a1, 1(a0)
+; RV64I-NEXT: ret
+ call void @llvm.memset.inline.p0.i64(ptr %dst, i8 %val, i64 2, i1 false)
+ ret void
+}
+
+define void @test_memset_inline_4bytes(ptr %dst, i8 %val) {
+; RV32I-LABEL: test_memset_inline_4bytes:
+; RV32I: # %bb.0:
+; RV32I-NEXT: sb a1, 0(a0)
+; RV32I-NEXT: sb a1, 1(a0)
+; RV32I-NEXT: sb a1, 2(a0)
+; RV32I-NEXT: sb a1, 3(a0)
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: test_memset_inline_4bytes:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sb a1, 0(a0)
+; RV64I-NEXT: sb a1, 1(a0)
+; RV64I-NEXT: sb a1, 2(a0)
+; RV64I-NEXT: sb a1, 3(a0)
+; RV64I-NEXT: ret
+ call void @llvm.memset.inline.p0.i64(ptr %dst, i8 %val, i64 4, i1 false)
+ ret void
+}
+
+define void @test_memset_inline_8bytes(ptr %dst, i8 %val) {
+; RV32I-LABEL: test_memset_inline_8bytes:
+; RV32I: # %bb.0:
+; RV32I-NEXT: sb a1, 0(a0)
+; RV32I-NEXT: sb a1, 1(a0)
+; RV32I-NEXT: sb a1, 2(a0)
+; RV32I-NEXT: sb a1, 3(a0)
+; RV32I-NEXT: sb a1, 4(a0)
+; RV32I-NEXT: sb a1, 5(a0)
+; RV32I-NEXT: sb a1, 6(a0)
+; RV32I-NEXT: sb a1, 7(a0)
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: test_memset_inline_8bytes:
+; RV64I: # %bb.0:
+; RV64I-NEXT: sb a1, 0(a0)
+; RV64I-NEXT: sb a1, 1(a0)
+; RV64I-NEXT: sb a1, 2(a0)
+; RV64I-NEXT: sb a1, 3(a0)
+; RV64I-NEXT: sb a1, 4(a0)
+; RV64I-NEXT: sb a1, 5(a0)
+; RV64I-NEXT: sb a1, 6(a0)
+; RV64I-NEXT: sb a1, 7(a0)
+; RV64I-NEXT: ret
+ call void @llvm.memset.inline.p0.i64(ptr %dst, i8 %val, i64 8, i1 false)
+ ret void
+}
>From 2a8ac50de0817d535f96d06cc971f216025821b1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 19:34:25 +0100
Subject: [PATCH 06/13] Formatting, minor fixes
---
llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp | 3 +--
llvm/lib/CodeGen/MachineVerifier.cpp | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
index 4dc2fcb951c8a..7ae9c354440d1 100644
--- a/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/LegalizerHelper.cpp
@@ -11165,7 +11165,7 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
// FIXME: support dynamically sized G_MEMCPY_INLINE and G_MEMSET_INLINE
assert(Opc != TargetOpcode::G_MEMCPY_INLINE &&
Opc != TargetOpcode::G_MEMSET_INLINE &&
- "inline memcpy with dynamic size is not yet supported");
+ "inline memcpy and memset with dynamic size are not yet supported");
return UnableToLegalize;
}
uint64_t KnownLen = LenVRegAndVal->Value.getZExtValue();
@@ -11182,7 +11182,6 @@ LegalizerHelper::lowerMemCpyFamily(MachineInstr &MI, unsigned MaxLen) {
bool IsVolatile = MemOp->isVolatile();
if (Opc == TargetOpcode::G_MEMCPY || Opc == TargetOpcode::G_MEMCPY_INLINE) {
auto &MF = *MI.getParent()->getParent();
- const auto &TLI = *MF.getSubtarget().getTargetLowering();
bool OptSize = shouldLowerMemFuncForSize(MF);
uint64_t Limit = Opc == TargetOpcode::G_MEMCPY_INLINE
? std::numeric_limits<uint64_t>::max()
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index f68ff34654ffe..86187fe3950fb 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2129,8 +2129,7 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
}
case TargetOpcode::G_BZERO:
case TargetOpcode::G_MEMSET:
- case TargetOpcode::G_MEMSET_INLINE:
- {
+ case TargetOpcode::G_MEMSET_INLINE: {
ArrayRef<MachineMemOperand *> MMOs = MI->memoperands();
std::string Name = Opc == TargetOpcode::G_MEMSET ? "memset"
: Opc == TargetOpcode::G_MEMSET_INLINE ? "memset_inline"
>From 333735ff987095b1117a8b6c23e9242bc6fab413 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Wed, 10 Jun 2026 19:49:22 +0100
Subject: [PATCH 07/13] MOPS support
---
llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp | 4 +++-
llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir | 2 ++
.../CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll | 1 +
.../CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir | 3 +++
.../CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir | 3 +++
5 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
index eca93c51760ac..e6521a211226e 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64LegalizerInfo.cpp
@@ -1555,6 +1555,7 @@ bool AArch64LegalizerInfo::legalizeCustom(
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET:
+ case TargetOpcode::G_MEMSET_INLINE:
return legalizeMemOps(MI, Helper);
case TargetOpcode::G_EXTRACT_VECTOR_ELT:
return legalizeExtractVectorElt(MI, MRI, Helper);
@@ -2554,7 +2555,8 @@ bool AArch64LegalizerInfo::legalizeMemOps(MachineInstr &MI,
MachineIRBuilder &MIRBuilder = Helper.MIRBuilder;
// Tagged version MOPSMemorySetTagged is legalised in legalizeIntrinsic
- if (MI.getOpcode() == TargetOpcode::G_MEMSET) {
+ if (MI.getOpcode() == TargetOpcode::G_MEMSET ||
+ MI.getOpcode() == TargetOpcode::G_MEMSET_INLINE) {
// Anyext the value being set to 64 bit (only the bottom 8 bits are read by
// the instruction).
auto &Value = MI.getOperand(1);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir b/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
index bce7d6fe3c094..816ce08acfb93 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/inline-memset-forced.mir
@@ -1,5 +1,6 @@
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
# RUN: llc -mtriple=aarch64 -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -mtriple=aarch64 -mattr=+mops -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs %s -o - | FileCheck %s
--- |
target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
target triple = "arm64-apple-darwin"
@@ -65,6 +66,7 @@ body: |
; CHECK-NEXT: [[PTR_ADD7:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C8]](s64)
; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD7]](p0) :: (store (<2 x i64>) into %ir.dst + 127, align 1, basealign 4)
; CHECK-NEXT: RET_ReallyLR
+ ;
%0:_(p0) = COPY $x0
%1:_(i32) = COPY $w1
%2:_(i8) = G_TRUNC %1(i32)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
index cd67cc8af4367..4e299a2eec47d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-memset-inline.ll
@@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
; RUN: llc -mtriple=aarch64-unknown-unknown -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=irtranslator %s -o - | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-unknown -mattr=+mops -global-isel -global-isel-abort=1 -verify-machineinstrs -stop-after=irtranslator %s -o - | FileCheck %s
define void @memset(ptr %dst, i8 %val) {
; CHECK-LABEL: name: memset
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
index c82627a1e8c8d..190761c4124e0 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/legalizer-info-validation.mir
@@ -911,6 +911,9 @@
# DEBUG-NEXT: G_BZERO (opcode {{[0-9]+}}): 2 type indices, 1 imm index
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: G_MEMSET_INLINE (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index 2aa2f2efcdc17..df971ec7db334 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -900,6 +900,9 @@
# DEBUG-NEXT: G_BZERO (opcode {{[0-9]+}}): 2 type indices, 1 imm index
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
+# DEBUG-NEXT: G_MEMSET_INLINE (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
+# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
+# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
>From dfb1365d05c4a0e80cd6022a33ce6b3a3d30e82f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Thu, 11 Jun 2026 09:54:44 +0100
Subject: [PATCH 08/13] Post-merge fixups
---
llvm/lib/CodeGen/GlobalISel/Utils.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/Utils.cpp b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
index bd8c8219e1220..fbb54d8971502 100644
--- a/llvm/lib/CodeGen/GlobalISel/Utils.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/Utils.cpp
@@ -2247,8 +2247,8 @@ bool llvm::canLowerMemCpyFamily(const MachineInstr &MI,
}
case TargetOpcode::G_MEMSET:
case TargetOpcode::G_MEMSET_INLINE: {
- uint64_t Limit = Opc == TargetOpcode::G_MEMSET_INLINE
- ? std::numeric_limits<uint64_t>::max()
+ unsigned Limit = Opc == TargetOpcode::G_MEMSET_INLINE
+ ? std::numeric_limits<unsigned>::max()
: TLI.getMaxStoresPerMemset(OptSize);
auto ValVRegAndVal = getIConstantVRegValWithLookThrough(Src, MRI);
bool IsZeroVal = ValVRegAndVal && ValVRegAndVal->Value == 0;
>From 7be6391749846972bf01453237a6cf800dd19a4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Thu, 11 Jun 2026 10:09:34 +0100
Subject: [PATCH 09/13] Remove dupd fun tryEmitMemsetInline, refactor
tryEmitMemcpyInline
---
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 10 ++--------
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 10 +---------
.../AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp | 3 +--
.../AArch64/GISel/AArch64PreLegalizerCombiner.cpp | 3 +--
llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp | 3 +--
5 files changed, 6 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index da127baeff08c..a04ff991b2cf8 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -861,16 +861,10 @@ class CombinerHelper {
LLVM_ABI bool tryCombine(MachineInstr &MI) const;
/// Emit loads and stores that perform the given memcpy.
- /// Assumes \p MI is a G_MEMCPY_INLINE
+ /// Assumes \p MI is a G_MEMCPY_INLINE or a G_MEMSET_INLINE
/// TODO: implement dynamically sized inline memcpy,
/// and rename: s/bool tryEmit/void emit/
- LLVM_ABI bool tryEmitMemcpyInline(MachineInstr &MI) const;
-
- /// Emit stores that perform the given memset.
- /// Assumes \p MI is a G_MEMSET_INLINE
- /// TODO: implement dynamically sized inline memset,
- /// and rename: s/bool tryEmit/void emit/
- LLVM_ABI bool tryEmitMemsetInline(MachineInstr &MI) const;
+ LLVM_ABI bool tryEmitMemcpyInlineFamily(MachineInstr &MI) const;
/// Match:
/// (G_UMULO x, 2) -> (G_UADDO x, x)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index f7159ad0617b6..3cc00d816c0e6 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -1721,15 +1721,7 @@ void CombinerHelper::applyOptBrCondByInvertingCond(
Observer.changedInstr(*BrCond);
}
-bool CombinerHelper::tryEmitMemcpyInline(MachineInstr &MI) const {
- MachineIRBuilder HelperBuilder(MI);
- GISelObserverWrapper DummyObserver;
- LegalizerHelper Helper(HelperBuilder.getMF(), DummyObserver, HelperBuilder);
- return Helper.lowerMemCpyFamily(MI) ==
- LegalizerHelper::LegalizeResult::Legalized;
-}
-
-bool CombinerHelper::tryEmitMemsetInline(MachineInstr &MI) const {
+bool CombinerHelper::tryEmitMemcpyInlineFamily(MachineInstr &MI) const {
MachineIRBuilder HelperBuilder(MI);
GISelObserverWrapper DummyObserver;
LegalizerHelper Helper(HelperBuilder.getMF(), DummyObserver, HelperBuilder);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
index 3bca9053ca429..0846bd7994a31 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64O0PreLegalizerCombiner.cpp
@@ -95,9 +95,8 @@ bool AArch64O0PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
unsigned Opc = MI.getOpcode();
switch (Opc) {
case TargetOpcode::G_MEMCPY_INLINE:
- return Helper.tryEmitMemcpyInline(MI);
case TargetOpcode::G_MEMSET_INLINE:
- return Helper.tryEmitMemsetInline(MI);
+ return Helper.tryEmitMemcpyInlineFamily(MI);
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET: {
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
index cf4c1546efdfd..9834ea8ce5df9 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64PreLegalizerCombiner.cpp
@@ -792,9 +792,8 @@ bool AArch64PreLegalizerCombinerImpl::tryCombineAll(MachineInstr &MI) const {
unsigned Opc = MI.getOpcode();
switch (Opc) {
case TargetOpcode::G_MEMCPY_INLINE:
- return Helper.tryEmitMemcpyInline(MI);
case TargetOpcode::G_MEMSET_INLINE:
- return Helper.tryEmitMemsetInline(MI);
+ return Helper.tryEmitMemcpyInlineFamily(MI);
case TargetOpcode::G_MEMCPY:
case TargetOpcode::G_MEMMOVE:
case TargetOpcode::G_MEMSET: {
diff --git a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
index 43cf18517026b..dd9b76d9c9ecc 100644
--- a/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
+++ b/llvm/lib/Target/Mips/MipsPreLegalizerCombiner.cpp
@@ -58,9 +58,8 @@ class MipsPreLegalizerCombinerImpl : public Combiner {
default:
return false;
case TargetOpcode::G_MEMCPY_INLINE:
- return Helper.tryEmitMemcpyInline(MI);
case TargetOpcode::G_MEMSET_INLINE:
- return Helper.tryEmitMemsetInline(MI);
+ return Helper.tryEmitMemcpyInlineFamily(MI);
case TargetOpcode::G_LOAD:
case TargetOpcode::G_SEXTLOAD:
case TargetOpcode::G_ZEXTLOAD: {
>From a7c38b926b071ec17172cf548b3e9acc915ddef8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Fri, 12 Jun 2026 12:55:54 +0100
Subject: [PATCH 10/13] Add inline-small-memset test
---
.../GlobalISel/inline-small-memset.mir | 72 +++++++++++++++++++
1 file changed, 72 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/inline-small-memset.mir
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/inline-small-memset.mir b/llvm/test/CodeGen/AArch64/GlobalISel/inline-small-memset.mir
new file mode 100644
index 0000000000000..4c1b28d32fcdd
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/inline-small-memset.mir
@@ -0,0 +1,72 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple=aarch64 -run-pass=aarch64-prelegalizer-combiner -O0 -verify-machineinstrs %s -o - | FileCheck %s
+--- |
+ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128"
+ target triple = "arm64-apple-darwin"
+
+ declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #0
+
+ define void @test_small_memset(ptr nocapture %dst) {
+ entry:
+ tail call void @llvm.memset.p0.i64(ptr align 4 %dst, i8 12, i64 32, i1 false)
+ ret void
+ }
+
+ define void @test_large_memset(ptr nocapture %dst) {
+ entry:
+ tail call void @llvm.memset.p0.i64(ptr align 4 %dst, i8 12, i64 36, i1 false)
+ ret void
+ }
+
+ attributes #0 = { argmemonly nounwind }
+
+...
+---
+name: test_small_memset
+alignment: 4
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: test_small_memset
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i64) = G_CONSTANT i64 868082074056920076
+ ; CHECK-NEXT: [[BUILD_VECTOR:%[0-9]+]]:_(<2 x i64>) = G_BUILD_VECTOR [[C]](i64), [[C]](i64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[COPY]](p0) :: (store (<2 x i64>) into %ir.dst, align 4)
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 16
+ ; CHECK-NEXT: [[PTR_ADD:%[0-9]+]]:_(p0) = nuw inbounds G_PTR_ADD [[COPY]], [[C1]](s64)
+ ; CHECK-NEXT: G_STORE [[BUILD_VECTOR]](<2 x i64>), [[PTR_ADD]](p0) :: (store (<2 x i64>) into %ir.dst + 16, align 4)
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(i8) = G_CONSTANT i8 12
+ %2:_(i64) = G_CONSTANT i64 32
+ G_MEMSET %0(p0), %1(i8), %2(i64), 1 :: (store (s8) into %ir.dst, align 4)
+ RET_ReallyLR
+
+...
+---
+name: test_large_memset
+alignment: 4
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $x0
+
+ ; CHECK-LABEL: name: test_large_memset
+ ; CHECK: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(p0) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(i8) = G_CONSTANT i8 12
+ ; CHECK-NEXT: [[C1:%[0-9]+]]:_(i64) = G_CONSTANT i64 36
+ ; CHECK-NEXT: G_MEMSET [[COPY]](p0), [[C]](i8), [[C1]](i64), 1 :: (store (s8) into %ir.dst, align 4)
+ ; CHECK-NEXT: RET_ReallyLR
+ %0:_(p0) = COPY $x0
+ %1:_(i8) = G_CONSTANT i8 12
+ %2:_(i64) = G_CONSTANT i64 36
+ G_MEMSET %0(p0), %1(i8), %2(i64), 1 :: (store (s8) into %ir.dst, align 4)
+ RET_ReallyLR
+
+...
>From 5a99d4b8d2c10ea13e609ec16de5730074bb7062 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Fri, 12 Jun 2026 13:00:24 +0100
Subject: [PATCH 11/13] Fold getActionDefinitionsBuilder call
---
llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
index 305f977d14914..fdd5e71c32830 100644
--- a/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
+++ b/llvm/lib/Target/RISCV/GISel/RISCVLegalizerInfo.cpp
@@ -527,9 +527,7 @@ RISCVLegalizerInfo::RISCVLegalizerInfo(const RISCVSubtarget &ST)
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE, G_MEMSET}).libcall();
- getActionDefinitionsBuilder(G_MEMCPY_INLINE).lower();
-
- getActionDefinitionsBuilder(G_MEMSET_INLINE).lower();
+ getActionDefinitionsBuilder({G_MEMCPY_INLINE, G_MEMSET_INLINE}).lower();
getActionDefinitionsBuilder({G_DYN_STACKALLOC, G_STACKSAVE, G_STACKRESTORE})
.lower();
>From 48c580eaa70a5b9102a2b181028789f09c1c0e79 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Fri, 12 Jun 2026 13:26:06 +0100
Subject: [PATCH 12/13] Style fix
---
llvm/lib/CodeGen/MachineVerifier.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp
index 86187fe3950fb..b442a65057256 100644
--- a/llvm/lib/CodeGen/MachineVerifier.cpp
+++ b/llvm/lib/CodeGen/MachineVerifier.cpp
@@ -2153,10 +2153,11 @@ void MachineVerifier::verifyPreISelGenericInstruction(const MachineInstr *MI) {
if (DstPtrTy.getAddressSpace() != MMOs[0]->getAddrSpace())
report("inconsistent " + Twine(Name, " address space"), MI);
- if (Opc != TargetOpcode::G_MEMSET_INLINE)
+ if (Opc != TargetOpcode::G_MEMSET_INLINE) {
if (!MI->getOperand(MI->getNumOperands() - 1).isImm() ||
(MI->getOperand(MI->getNumOperands() - 1).getImm() & ~1LL))
report("'tail' flag (last operand) must be an immediate 0 or 1", MI);
+ }
break;
}
>From 60d19c4ef4582cc9442a6971775fb345d272f26d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=C3=96mer=20Sinan=20A=C4=9Facan?= <omeragacan at gmail.com>
Date: Fri, 12 Jun 2026 14:57:54 +0100
Subject: [PATCH 13/13] Update test expectation
---
llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
index df971ec7db334..8fa04041fb4a8 100644
--- a/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
+++ b/llvm/test/CodeGen/RISCV/GlobalISel/legalizer-info-validation.mir
@@ -901,6 +901,7 @@
# DEBUG-NEXT: .. type index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: .. imm index coverage check SKIPPED: no rules defined
# DEBUG-NEXT: G_MEMSET_INLINE (opcode {{[0-9]+}}): 3 type indices, 0 imm indices
+# DEBUG-NEXT: .. opcode {{[0-9]+}} is aliased to {{[0-9]+}}
# DEBUG-NEXT: .. type index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: .. imm index coverage check SKIPPED: user-defined predicate detected
# DEBUG-NEXT: G_TRAP (opcode {{[0-9]+}}): 0 type indices, 0 imm indices
More information about the llvm-commits
mailing list