[llvm] [SelectionDAG] zext/trunc size of memory libcalls to target pointer size (PR #226672)
Mitch Briles via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 26 03:22:33 PDT 2026
https://github.com/MitchBriles created https://github.com/llvm/llvm-project/pull/226672
Fixes #226666
For `memcpy`, `memmove`, and `memset`, the value for the number of bytes for the operation ("Size") used the type of the intrinsic. When the type of Size was narrower than that of the "length" parameter of the libcall, the value would be widened with ANY_EXTEND. On RISC-V, this can materialize as a sign extension, which leads to writing `2^33` times as many bytes.
Changes
- Zero-extends or truncates the Size to the target pointer width (Note that GISel already does this correctly).
- Added new RISC-V/AArch64 tests, and updated existing ones.
Note that this also fixed an AArch64 crash. With `-mattr=+mops`, SD crashed with any non-constant i32 length argument to one of these libcalls with "unimplemented reg-to-reg copy"
cc @RKSimon to assign, please, and thanks!
>From d000b535257c83458c74dcf9889fab949837ff7c Mon Sep 17 00:00:00 2001
From: Mitch <mitchbriles at gmail.com>
Date: Sat, 26 Sep 2026 03:51:14 -0600
Subject: [PATCH] [SelectionDAG] zext/trunc size of memory libcalls to target
pointer size
---
.../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 3 +
llvm/test/CodeGen/AArch64/aarch64-mops.ll | 194 ++++++++++++++++++
llvm/test/CodeGen/AArch64/func-argpassing.ll | 4 +-
.../streaming-compatible-memory-ops.ll | 156 ++++++++++++++
llvm/test/CodeGen/RISCV/memcpy.ll | 98 ++++++++-
llvm/test/CodeGen/RISCV/memmove.ll | 74 +++++++
llvm/test/CodeGen/RISCV/memset.ll | 125 +++++++++++
7 files changed, 650 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/memset.ll
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 8c67b0449ddb6..70592b73ba43b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -10123,6 +10123,7 @@ SDValue SelectionDAG::getMemcpy(
const CallInst *CI, std::optional<bool> OverrideTailCall,
MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo,
const AAMDNodes &AAInfo, BatchAAResults *BatchAA) {
+ Size = getZExtOrTrunc(Size, dl, TLI->getPointerTy(getDataLayout()));
// Check to see if we should lower the memcpy to loads and stores first.
// For cases within the target-specified limits, this is the best choice.
const MDNode *DstMemCacheHint =
@@ -10254,6 +10255,7 @@ SDValue SelectionDAG::getMemmove(SDValue Chain, const SDLoc &dl, SDValue Dst,
MachinePointerInfo SrcPtrInfo,
const AAMDNodes &AAInfo,
BatchAAResults *BatchAA) {
+ Size = getZExtOrTrunc(Size, dl, TLI->getPointerTy(getDataLayout()));
// Check to see if we should lower the memmove to loads and stores first.
// For cases within the target-specified limits, this is the best choice.
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
@@ -10365,6 +10367,7 @@ SDValue SelectionDAG::getMemset(SDValue Chain, const SDLoc &dl, SDValue Dst,
const CallInst *CI,
MachinePointerInfo DstPtrInfo,
const AAMDNodes &AAInfo) {
+ Size = getZExtOrTrunc(Size, dl, TLI->getPointerTy(getDataLayout()));
// Check to see if we should lower the memset to stores first.
// For cases within the target-specified limits, this is the best choice.
ConstantSDNode *ConstantSize = dyn_cast<ConstantSDNode>(Size);
diff --git a/llvm/test/CodeGen/AArch64/aarch64-mops.ll b/llvm/test/CodeGen/AArch64/aarch64-mops.ll
index 02eb780596494..f673c9b68800f 100644
--- a/llvm/test/CodeGen/AArch64/aarch64-mops.ll
+++ b/llvm/test/CodeGen/AArch64/aarch64-mops.ll
@@ -2838,3 +2838,197 @@ entry:
call void @llvm.memmove.inline.p0.p0.i64(ptr align 1 %dst, ptr align 1 %src, i64 300, i1 true)
ret void
}
+
+define void @memset_size_i32(ptr %dst, i32 %size, i32 %value) {
+; GISel-WITHOUT-MOPS-O0-LABEL: memset_size_i32:
+; GISel-WITHOUT-MOPS-O0: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w8, w1
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w1, w2
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w8, w8
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w2, w8
+; GISel-WITHOUT-MOPS-O0-NEXT: bl memset
+; GISel-WITHOUT-MOPS-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O0-NEXT: ret
+;
+; GISel-WITHOUT-MOPS-O3-LABEL: memset_size_i32:
+; GISel-WITHOUT-MOPS-O3: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O3-NEXT: mov w3, w2
+; GISel-WITHOUT-MOPS-O3-NEXT: mov w2, w1
+; GISel-WITHOUT-MOPS-O3-NEXT: mov w1, w3
+; GISel-WITHOUT-MOPS-O3-NEXT: bl memset
+; GISel-WITHOUT-MOPS-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O3-NEXT: ret
+;
+; GISel-MOPS-O0-LABEL: memset_size_i32:
+; GISel-MOPS-O0: // %bb.0: // %entry
+; GISel-MOPS-O0-NEXT: mov w8, w1
+; GISel-MOPS-O0-NEXT: // kill: def $x8 killed $w8
+; GISel-MOPS-O0-NEXT: // implicit-def: $x9
+; GISel-MOPS-O0-NEXT: mov w9, w2
+; GISel-MOPS-O0-NEXT: setp [x0]!, x8!, x9
+; GISel-MOPS-O0-NEXT: setm [x0]!, x8!, x9
+; GISel-MOPS-O0-NEXT: sete [x0]!, x8!, x9
+; GISel-MOPS-O0-NEXT: ret
+;
+; GISel-MOPS-O3-LABEL: memset_size_i32:
+; GISel-MOPS-O3: // %bb.0: // %entry
+; GISel-MOPS-O3-NEXT: mov w8, w1
+; GISel-MOPS-O3-NEXT: // kill: def $w2 killed $w2 def $x2
+; GISel-MOPS-O3-NEXT: setp [x0]!, x8!, x2
+; GISel-MOPS-O3-NEXT: setm [x0]!, x8!, x2
+; GISel-MOPS-O3-NEXT: sete [x0]!, x8!, x2
+; GISel-MOPS-O3-NEXT: ret
+;
+; SDAG-WITHOUT-MOPS-O2-LABEL: memset_size_i32:
+; SDAG-WITHOUT-MOPS-O2: // %bb.0: // %entry
+; SDAG-WITHOUT-MOPS-O2-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_def_cfa_offset 16
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_offset w30, -16
+; SDAG-WITHOUT-MOPS-O2-NEXT: mov w8, w2
+; SDAG-WITHOUT-MOPS-O2-NEXT: mov w2, w1
+; SDAG-WITHOUT-MOPS-O2-NEXT: mov w1, w8
+; SDAG-WITHOUT-MOPS-O2-NEXT: bl memset
+; SDAG-WITHOUT-MOPS-O2-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; SDAG-WITHOUT-MOPS-O2-NEXT: ret
+;
+; SDAG-MOPS-O2-LABEL: memset_size_i32:
+; SDAG-MOPS-O2: // %bb.0: // %entry
+; SDAG-MOPS-O2-NEXT: mov w8, w1
+; SDAG-MOPS-O2-NEXT: // kill: def $w2 killed $w2 def $x2
+; SDAG-MOPS-O2-NEXT: setp [x0]!, x8!, x2
+; SDAG-MOPS-O2-NEXT: setm [x0]!, x8!, x2
+; SDAG-MOPS-O2-NEXT: sete [x0]!, x8!, x2
+; SDAG-MOPS-O2-NEXT: ret
+entry:
+ %value_trunc = trunc i32 %value to i8
+ call void @llvm.memset.p0.i32(ptr align 1 %dst, i8 %value_trunc, i32 %size, i1 false)
+ ret void
+}
+
+define void @memcpy_n_i32(ptr %dst, ptr %src, i32 %size) {
+; GISel-WITHOUT-MOPS-O0-LABEL: memcpy_n_i32:
+; GISel-WITHOUT-MOPS-O0: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w8, w2
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w2, w8
+; GISel-WITHOUT-MOPS-O0-NEXT: bl memcpy
+; GISel-WITHOUT-MOPS-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O0-NEXT: ret
+;
+; GISel-WITHOUT-MOPS-O3-LABEL: memcpy_n_i32:
+; GISel-WITHOUT-MOPS-O3: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O3-NEXT: mov w2, w2
+; GISel-WITHOUT-MOPS-O3-NEXT: bl memcpy
+; GISel-WITHOUT-MOPS-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O3-NEXT: ret
+;
+; GISel-MOPS-O0-LABEL: memcpy_n_i32:
+; GISel-MOPS-O0: // %bb.0: // %entry
+; GISel-MOPS-O0-NEXT: mov w8, w2
+; GISel-MOPS-O0-NEXT: // kill: def $x8 killed $w8
+; GISel-MOPS-O0-NEXT: cpyfp [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: cpyfm [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: cpyfe [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: ret
+;
+; GISel-MOPS-O3-LABEL: memcpy_n_i32:
+; GISel-MOPS-O3: // %bb.0: // %entry
+; GISel-MOPS-O3-NEXT: mov w8, w2
+; GISel-MOPS-O3-NEXT: cpyfp [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: cpyfm [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: cpyfe [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: ret
+;
+; SDAG-WITHOUT-MOPS-O2-LABEL: memcpy_n_i32:
+; SDAG-WITHOUT-MOPS-O2: // %bb.0: // %entry
+; SDAG-WITHOUT-MOPS-O2-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_def_cfa_offset 16
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_offset w30, -16
+; SDAG-WITHOUT-MOPS-O2-NEXT: mov w2, w2
+; SDAG-WITHOUT-MOPS-O2-NEXT: bl memcpy
+; SDAG-WITHOUT-MOPS-O2-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; SDAG-WITHOUT-MOPS-O2-NEXT: ret
+;
+; SDAG-MOPS-O2-LABEL: memcpy_n_i32:
+; SDAG-MOPS-O2: // %bb.0: // %entry
+; SDAG-MOPS-O2-NEXT: mov w8, w2
+; SDAG-MOPS-O2-NEXT: cpyfp [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: cpyfm [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: cpyfe [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: ret
+entry:
+ call void @llvm.memcpy.p0.p0.i32(ptr align 1 %dst, ptr align 1 %src, i32 %size, i1 false)
+ ret void
+}
+
+define void @memmove_n_i32(ptr %dst, ptr %src, i32 %size) {
+; GISel-WITHOUT-MOPS-O0-LABEL: memmove_n_i32:
+; GISel-WITHOUT-MOPS-O0: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O0-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O0-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w8, w2
+; GISel-WITHOUT-MOPS-O0-NEXT: mov w2, w8
+; GISel-WITHOUT-MOPS-O0-NEXT: bl memmove
+; GISel-WITHOUT-MOPS-O0-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O0-NEXT: ret
+;
+; GISel-WITHOUT-MOPS-O3-LABEL: memmove_n_i32:
+; GISel-WITHOUT-MOPS-O3: // %bb.0: // %entry
+; GISel-WITHOUT-MOPS-O3-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_def_cfa_offset 16
+; GISel-WITHOUT-MOPS-O3-NEXT: .cfi_offset w30, -16
+; GISel-WITHOUT-MOPS-O3-NEXT: mov w2, w2
+; GISel-WITHOUT-MOPS-O3-NEXT: bl memmove
+; GISel-WITHOUT-MOPS-O3-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; GISel-WITHOUT-MOPS-O3-NEXT: ret
+;
+; GISel-MOPS-O0-LABEL: memmove_n_i32:
+; GISel-MOPS-O0: // %bb.0: // %entry
+; GISel-MOPS-O0-NEXT: mov w8, w2
+; GISel-MOPS-O0-NEXT: // kill: def $x8 killed $w8
+; GISel-MOPS-O0-NEXT: cpyp [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: cpym [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: cpye [x0]!, [x1]!, x8!
+; GISel-MOPS-O0-NEXT: ret
+;
+; GISel-MOPS-O3-LABEL: memmove_n_i32:
+; GISel-MOPS-O3: // %bb.0: // %entry
+; GISel-MOPS-O3-NEXT: mov w8, w2
+; GISel-MOPS-O3-NEXT: cpyp [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: cpym [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: cpye [x0]!, [x1]!, x8!
+; GISel-MOPS-O3-NEXT: ret
+;
+; SDAG-WITHOUT-MOPS-O2-LABEL: memmove_n_i32:
+; SDAG-WITHOUT-MOPS-O2: // %bb.0: // %entry
+; SDAG-WITHOUT-MOPS-O2-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_def_cfa_offset 16
+; SDAG-WITHOUT-MOPS-O2-NEXT: .cfi_offset w30, -16
+; SDAG-WITHOUT-MOPS-O2-NEXT: mov w2, w2
+; SDAG-WITHOUT-MOPS-O2-NEXT: bl memmove
+; SDAG-WITHOUT-MOPS-O2-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; SDAG-WITHOUT-MOPS-O2-NEXT: ret
+;
+; SDAG-MOPS-O2-LABEL: memmove_n_i32:
+; SDAG-MOPS-O2: // %bb.0: // %entry
+; SDAG-MOPS-O2-NEXT: mov w8, w2
+; SDAG-MOPS-O2-NEXT: cpyp [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: cpym [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: cpye [x0]!, [x1]!, x8!
+; SDAG-MOPS-O2-NEXT: ret
+entry:
+ call void @llvm.memmove.p0.p0.i32(ptr align 1 %dst, ptr align 1 %src, i32 %size, i1 false)
+ ret void
+}
diff --git a/llvm/test/CodeGen/AArch64/func-argpassing.ll b/llvm/test/CodeGen/AArch64/func-argpassing.ll
index 9d10f6cb23583..d75aae86a1650 100644
--- a/llvm/test/CodeGen/AArch64/func-argpassing.ll
+++ b/llvm/test/CodeGen/AArch64/func-argpassing.ll
@@ -183,9 +183,9 @@ define dso_local void @check_i128_stackalign(i32 %val0, i32 %val1, i32 %val2, i3
declare void @llvm.memcpy.p0.p0.i32(ptr, ptr, i32, i1)
-define dso_local i32 @test_extern() {
+define dso_local i32 @test_extern(ptr %dst, ptr %src, i32 %size) {
; CHECK-LABEL: test_extern:
- call void @llvm.memcpy.p0.p0.i32(ptr align 4 undef, ptr align 4 undef, i32 undef, i1 0)
+ call void @llvm.memcpy.p0.p0.i32(ptr align 4 %dst, ptr align 4 %src, i32 %size, i1 0)
; CHECK: bl memcpy
ret i32 0
}
diff --git a/llvm/test/CodeGen/AArch64/streaming-compatible-memory-ops.ll b/llvm/test/CodeGen/AArch64/streaming-compatible-memory-ops.ll
index 895271d8bfdc8..84916e0aae190 100644
--- a/llvm/test/CodeGen/AArch64/streaming-compatible-memory-ops.ll
+++ b/llvm/test/CodeGen/AArch64/streaming-compatible-memory-ops.ll
@@ -446,6 +446,162 @@ entry:
ret void
}
+define void @se_memcpy_i32(i32 %n) "aarch64_pstate_sm_enabled" nounwind {
+; CHECK-LABEL: se_memcpy_i32:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: adrp x8, :got:dst
+; CHECK-NEXT: adrp x1, :got:src
+; CHECK-NEXT: mov w2, w0
+; CHECK-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NEXT: ldr x1, [x1, :got_lo12:src]
+; CHECK-NEXT: mov x0, x8
+; CHECK-NEXT: bl __arm_sc_memcpy
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-NO-SME-ROUTINES-LABEL: se_memcpy_i32:
+; CHECK-NO-SME-ROUTINES: // %bb.0: // %entry
+; CHECK-NO-SME-ROUTINES-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: adrp x8, :got:dst
+; CHECK-NO-SME-ROUTINES-NEXT: adrp x1, :got:src
+; CHECK-NO-SME-ROUTINES-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: mov w2, w0
+; CHECK-NO-SME-ROUTINES-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: str x30, [sp, #64] // 8-byte Spill
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x1, [x1, :got_lo12:src]
+; CHECK-NO-SME-ROUTINES-NEXT: smstop sm
+; CHECK-NO-SME-ROUTINES-NEXT: mov x0, x8
+; CHECK-NO-SME-ROUTINES-NEXT: bl memcpy
+; CHECK-NO-SME-ROUTINES-NEXT: smstart sm
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x30, [sp, #64] // 8-byte Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ret
+;
+; CHECK-MOPS-LABEL: se_memcpy_i32:
+; CHECK-MOPS: // %bb.0: // %entry
+; CHECK-MOPS-NEXT: adrp x8, :got:src
+; CHECK-MOPS-NEXT: adrp x9, :got:dst
+; CHECK-MOPS-NEXT: mov w10, w0
+; CHECK-MOPS-NEXT: ldr x8, [x8, :got_lo12:src]
+; CHECK-MOPS-NEXT: ldr x9, [x9, :got_lo12:dst]
+; CHECK-MOPS-NEXT: cpyfp [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: cpyfm [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: cpyfe [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: ret
+entry:
+ tail call void @llvm.memcpy.p0.p0.i32(ptr align 1 @dst, ptr nonnull align 1 @src, i32 %n, i1 false)
+ ret void
+}
+
+define void @se_memset_i32(i32 %n) "aarch64_pstate_sm_enabled" nounwind {
+; CHECK-LABEL: se_memset_i32:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: adrp x8, :got:dst
+; CHECK-NEXT: mov w2, w0
+; CHECK-NEXT: mov w1, #2 // =0x2
+; CHECK-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NEXT: mov x0, x8
+; CHECK-NEXT: bl __arm_sc_memset
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-NO-SME-ROUTINES-LABEL: se_memset_i32:
+; CHECK-NO-SME-ROUTINES: // %bb.0: // %entry
+; CHECK-NO-SME-ROUTINES-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: adrp x8, :got:dst
+; CHECK-NO-SME-ROUTINES-NEXT: mov w2, w0
+; CHECK-NO-SME-ROUTINES-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: str x30, [sp, #64] // 8-byte Spill
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NO-SME-ROUTINES-NEXT: smstop sm
+; CHECK-NO-SME-ROUTINES-NEXT: mov x0, x8
+; CHECK-NO-SME-ROUTINES-NEXT: mov w1, #2 // =0x2
+; CHECK-NO-SME-ROUTINES-NEXT: bl memset
+; CHECK-NO-SME-ROUTINES-NEXT: smstart sm
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x30, [sp, #64] // 8-byte Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ret
+;
+; CHECK-MOPS-LABEL: se_memset_i32:
+; CHECK-MOPS: // %bb.0: // %entry
+; CHECK-MOPS-NEXT: adrp x8, :got:dst
+; CHECK-MOPS-NEXT: mov w9, w0
+; CHECK-MOPS-NEXT: mov w10, #2 // =0x2
+; CHECK-MOPS-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-MOPS-NEXT: setp [x8]!, x9!, x10
+; CHECK-MOPS-NEXT: setm [x8]!, x9!, x10
+; CHECK-MOPS-NEXT: sete [x8]!, x9!, x10
+; CHECK-MOPS-NEXT: ret
+entry:
+ tail call void @llvm.memset.p0.i32(ptr align 1 @dst, i8 2, i32 %n, i1 false)
+ ret void
+}
+
+define void @se_memmove_i32(i32 %n) "aarch64_pstate_sm_enabled" nounwind {
+; CHECK-LABEL: se_memmove_i32:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: str x30, [sp, #-16]! // 8-byte Folded Spill
+; CHECK-NEXT: adrp x8, :got:dst
+; CHECK-NEXT: adrp x1, :got:src
+; CHECK-NEXT: mov w2, w0
+; CHECK-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NEXT: ldr x1, [x1, :got_lo12:src]
+; CHECK-NEXT: mov x0, x8
+; CHECK-NEXT: bl __arm_sc_memmove
+; CHECK-NEXT: ldr x30, [sp], #16 // 8-byte Folded Reload
+; CHECK-NEXT: ret
+;
+; CHECK-NO-SME-ROUTINES-LABEL: se_memmove_i32:
+; CHECK-NO-SME-ROUTINES: // %bb.0: // %entry
+; CHECK-NO-SME-ROUTINES-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: adrp x8, :got:dst
+; CHECK-NO-SME-ROUTINES-NEXT: adrp x1, :got:src
+; CHECK-NO-SME-ROUTINES-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: mov w2, w0
+; CHECK-NO-SME-ROUTINES-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
+; CHECK-NO-SME-ROUTINES-NEXT: str x30, [sp, #64] // 8-byte Spill
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x8, [x8, :got_lo12:dst]
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x1, [x1, :got_lo12:src]
+; CHECK-NO-SME-ROUTINES-NEXT: smstop sm
+; CHECK-NO-SME-ROUTINES-NEXT: mov x0, x8
+; CHECK-NO-SME-ROUTINES-NEXT: bl memmove
+; CHECK-NO-SME-ROUTINES-NEXT: smstart sm
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldr x30, [sp, #64] // 8-byte Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
+; CHECK-NO-SME-ROUTINES-NEXT: ret
+;
+; CHECK-MOPS-LABEL: se_memmove_i32:
+; CHECK-MOPS: // %bb.0: // %entry
+; CHECK-MOPS-NEXT: adrp x8, :got:src
+; CHECK-MOPS-NEXT: adrp x9, :got:dst
+; CHECK-MOPS-NEXT: mov w10, w0
+; CHECK-MOPS-NEXT: ldr x8, [x8, :got_lo12:src]
+; CHECK-MOPS-NEXT: ldr x9, [x9, :got_lo12:dst]
+; CHECK-MOPS-NEXT: cpyp [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: cpym [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: cpye [x9]!, [x8]!, x10!
+; CHECK-MOPS-NEXT: ret
+entry:
+ tail call void @llvm.memmove.p0.p0.i32(ptr align 1 @dst, ptr nonnull align 1 @src, i32 %n, i1 false)
+ ret void
+}
+
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg)
declare void @llvm.memcpy.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
declare void @llvm.memmove.p0.p0.i64(ptr nocapture writeonly, ptr nocapture readonly, i64, i1 immarg)
diff --git a/llvm/test/CodeGen/RISCV/memcpy.ll b/llvm/test/CodeGen/RISCV/memcpy.ll
index 859d1039527ce..e2b1d0a6957a1 100644
--- a/llvm/test/CodeGen/RISCV/memcpy.ll
+++ b/llvm/test/CodeGen/RISCV/memcpy.ll
@@ -8,9 +8,9 @@
; RUN: llc < %s -mtriple=riscv32 -mcpu=andes-a45 -mtune=rocket \
; RUN: | FileCheck %s --check-prefixes=RV32-BOTH,RV32-FAST
; RUN: llc < %s -mtriple=riscv64 -mattr=+unaligned-scalar-mem \
-; RUN: | FileCheck %s --check-prefixes=RV64-BOTH,RV64-FAST
+; RUN: | FileCheck %s --check-prefixes=RV64-BOTH,RV64-FAST,RV64-UNALIGNED
; RUN: llc < %s -mtriple=riscv64 -mcpu=andes-ax45 -mtune=rocket \
-; RUN: | FileCheck %s --check-prefixes=RV64-BOTH,RV64-FAST
+; RUN: | FileCheck %s --check-prefixes=RV64-BOTH,RV64-FAST,RV64-ANDES
; ----------------------------------------------------------------------
; Fully unaligned cases
@@ -768,3 +768,97 @@ entry:
ret i32 0
}
+define void @memcpy_i32_var(ptr %dest, ptr %src, i32 %n) nounwind {
+; RV32-BOTH-LABEL: memcpy_i32_var:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: call memcpy
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-LABEL: memcpy_i32_var:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: slli a2, a2, 32
+; RV64-NEXT: srli a2, a2, 32
+; RV64-NEXT: call memcpy
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+;
+; RV64-UNALIGNED-LABEL: memcpy_i32_var:
+; RV64-UNALIGNED: # %bb.0: # %entry
+; RV64-UNALIGNED-NEXT: addi sp, sp, -16
+; RV64-UNALIGNED-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-UNALIGNED-NEXT: slli a2, a2, 32
+; RV64-UNALIGNED-NEXT: srli a2, a2, 32
+; RV64-UNALIGNED-NEXT: call memcpy
+; RV64-UNALIGNED-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-UNALIGNED-NEXT: addi sp, sp, 16
+; RV64-UNALIGNED-NEXT: ret
+;
+; RV64-ANDES-LABEL: memcpy_i32_var:
+; RV64-ANDES: # %bb.0: # %entry
+; RV64-ANDES-NEXT: addi sp, sp, -16
+; RV64-ANDES-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-ANDES-NEXT: nds.bfoz a2, a2, 31, 0
+; RV64-ANDES-NEXT: call memcpy
+; RV64-ANDES-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-ANDES-NEXT: addi sp, sp, 16
+; RV64-ANDES-NEXT: ret
+entry:
+ call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 %n, i1 false)
+ ret void
+}
+
+define void @memcpy_i32_2147483648(ptr %dest, ptr %src) nounwind {
+; RV32-BOTH-LABEL: memcpy_i32_2147483648:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: lui a2, 524288
+; RV32-BOTH-NEXT: call memcpy
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-BOTH-LABEL: memcpy_i32_2147483648:
+; RV64-BOTH: # %bb.0: # %entry
+; RV64-BOTH-NEXT: addi sp, sp, -16
+; RV64-BOTH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-BOTH-NEXT: li a2, 1
+; RV64-BOTH-NEXT: slli a2, a2, 31
+; RV64-BOTH-NEXT: call memcpy
+; RV64-BOTH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-BOTH-NEXT: addi sp, sp, 16
+; RV64-BOTH-NEXT: ret
+entry:
+ call void @llvm.memcpy.p0.p0.i32(ptr %dest, ptr %src, i32 -2147483648, i1 false)
+ ret void
+}
+
+define void @memcpy_i64_var(ptr %dest, ptr %src, i64 %n) nounwind {
+; RV32-BOTH-LABEL: memcpy_i64_var:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: call memcpy
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-BOTH-LABEL: memcpy_i64_var:
+; RV64-BOTH: # %bb.0: # %entry
+; RV64-BOTH-NEXT: addi sp, sp, -16
+; RV64-BOTH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-BOTH-NEXT: call memcpy
+; RV64-BOTH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-BOTH-NEXT: addi sp, sp, 16
+; RV64-BOTH-NEXT: ret
+entry:
+ call void @llvm.memcpy.p0.p0.i64(ptr %dest, ptr %src, i64 %n, i1 false)
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/memmove.ll b/llvm/test/CodeGen/RISCV/memmove.ll
index 3e3184bf4cb49..091676f46d201 100644
--- a/llvm/test/CodeGen/RISCV/memmove.ll
+++ b/llvm/test/CodeGen/RISCV/memmove.ll
@@ -853,3 +853,77 @@ entry:
tail call void @llvm.memmove.p0.p0.i64(ptr align 4 %dest, ptr align 4 %src, i64 7, i1 true)
ret void
}
+
+define void @memmove_i32_var(ptr %dest, ptr %src, i32 %n) nounwind {
+; RV32-BOTH-LABEL: memmove_i32_var:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: call memmove
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-BOTH-LABEL: memmove_i32_var:
+; RV64-BOTH: # %bb.0: # %entry
+; RV64-BOTH-NEXT: addi sp, sp, -16
+; RV64-BOTH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-BOTH-NEXT: slli a2, a2, 32
+; RV64-BOTH-NEXT: srli a2, a2, 32
+; RV64-BOTH-NEXT: call memmove
+; RV64-BOTH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-BOTH-NEXT: addi sp, sp, 16
+; RV64-BOTH-NEXT: ret
+entry:
+ call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 %n, i1 false)
+ ret void
+}
+
+define void @memmove_i32_2147483648(ptr %dest, ptr %src) nounwind {
+; RV32-BOTH-LABEL: memmove_i32_2147483648:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: lui a2, 524288
+; RV32-BOTH-NEXT: call memmove
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-BOTH-LABEL: memmove_i32_2147483648:
+; RV64-BOTH: # %bb.0: # %entry
+; RV64-BOTH-NEXT: addi sp, sp, -16
+; RV64-BOTH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-BOTH-NEXT: li a2, 1
+; RV64-BOTH-NEXT: slli a2, a2, 31
+; RV64-BOTH-NEXT: call memmove
+; RV64-BOTH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-BOTH-NEXT: addi sp, sp, 16
+; RV64-BOTH-NEXT: ret
+entry:
+ call void @llvm.memmove.p0.p0.i32(ptr %dest, ptr %src, i32 -2147483648, i1 false)
+ ret void
+}
+
+define void @memmove_i64_var(ptr %dest, ptr %src, i64 %n) nounwind {
+; RV32-BOTH-LABEL: memmove_i64_var:
+; RV32-BOTH: # %bb.0: # %entry
+; RV32-BOTH-NEXT: addi sp, sp, -16
+; RV32-BOTH-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-BOTH-NEXT: call memmove
+; RV32-BOTH-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-BOTH-NEXT: addi sp, sp, 16
+; RV32-BOTH-NEXT: ret
+;
+; RV64-BOTH-LABEL: memmove_i64_var:
+; RV64-BOTH: # %bb.0: # %entry
+; RV64-BOTH-NEXT: addi sp, sp, -16
+; RV64-BOTH-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-BOTH-NEXT: call memmove
+; RV64-BOTH-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-BOTH-NEXT: addi sp, sp, 16
+; RV64-BOTH-NEXT: ret
+entry:
+ call void @llvm.memmove.p0.p0.i64(ptr %dest, ptr %src, i64 %n, i1 false)
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/memset.ll b/llvm/test/CodeGen/RISCV/memset.ll
new file mode 100644
index 0000000000000..359b7d8ac3a43
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/memset.ll
@@ -0,0 +1,125 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -mtriple=riscv32 | FileCheck %s --check-prefix=RV32
+; RUN: llc < %s -mtriple=riscv64 | FileCheck %s --check-prefix=RV64
+
+define void @memset_i32_var(ptr %dest, i8 %val, i32 %n) nounwind {
+; RV32-LABEL: memset_i32_var:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: call memset
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: memset_i32_var:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: slli a2, a2, 32
+; RV64-NEXT: srli a2, a2, 32
+; RV64-NEXT: call memset
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 %n, i1 false)
+ ret void
+}
+
+define void @memset_i32_2147483648(ptr %dest, i8 %val) nounwind {
+; RV32-LABEL: memset_i32_2147483648:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: lui a2, 524288
+; RV32-NEXT: call memset
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: memset_i32_2147483648:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: li a2, 1
+; RV64-NEXT: slli a2, a2, 31
+; RV64-NEXT: call memset
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ call void @llvm.memset.p0.i32(ptr %dest, i8 %val, i32 -2147483648, i1 false)
+ ret void
+}
+
+define void @memset_zero_i32_2147483648(ptr %dest) nounwind {
+; RV32-LABEL: memset_zero_i32_2147483648:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: lui a2, 524288
+; RV32-NEXT: li a1, 0
+; RV32-NEXT: call memset
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: memset_zero_i32_2147483648:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: li a2, 1
+; RV64-NEXT: slli a2, a2, 31
+; RV64-NEXT: li a1, 0
+; RV64-NEXT: call memset
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ call void @llvm.memset.p0.i32(ptr %dest, i8 0, i32 -2147483648, i1 false)
+ ret void
+}
+
+define void @memset_i64_var(ptr %dest, i8 %val, i64 %n) nounwind {
+; RV32-LABEL: memset_i64_var:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: call memset
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: ret
+;
+; RV64-LABEL: memset_i64_var:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: call memset
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 %n, i1 false)
+ ret void
+}
+
+define void @memset_i64_4294967296(ptr %dest, i8 %val) nounwind {
+; RV32-LABEL: memset_i64_4294967296:
+; RV32: # %bb.0: # %entry
+; RV32-NEXT: ret
+;
+; RV64-LABEL: memset_i64_4294967296:
+; RV64: # %bb.0: # %entry
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: li a2, 1
+; RV64-NEXT: slli a2, a2, 32
+; RV64-NEXT: call memset
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: ret
+entry:
+ call void @llvm.memset.p0.i64(ptr %dest, i8 %val, i64 4294967296, i1 false)
+ ret void
+}
More information about the llvm-commits
mailing list