Memset with a constant length was implemented with a single store followed by a series of MVC:s. This patch changes this so that one store of the byte is emitted for each MVC, which avoids data dependencies between the MVCs. An MVI/STC + MVC(len-1) is done for each block. In addition, memset with a variable length is now also handled without a libcall. Since the byte is first stored and then MVC is used from that address, a length of two must now be subtracted instead of one for the loop and EXRL. This requires an extra check for the one-byte case, which is handled in a special block with just a single MVI/STC (like GCC). Review: Ulrich Weigand Differential Revision: https://reviews.llvm.org/D112004
24 lines
771 B
LLVM
24 lines
771 B
LLVM
; RUN: llc -mtriple=s390x-linux-gnu < %s | FileCheck %s
|
|
|
|
; CHECK-LABEL: tail_memmove:
|
|
; CHECK: jg memmove
|
|
define void @tail_memmove(i8* nocapture %p, i8* nocapture readonly %q, i32 %n) #0 {
|
|
entry:
|
|
tail call void @llvm.memmove.p0i8.p0i8.i32(i8* %p, i8* %q, i32 %n, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: tail_memset:
|
|
; CHECK: jg memset
|
|
define void @tail_memset(i8* nocapture %p, i8 %c, i32 %n) #0 {
|
|
entry:
|
|
tail call void @llvm.memset.p0i8.i32(i8* %p, i8 %c, i32 %n, i1 true)
|
|
ret void
|
|
}
|
|
|
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) #0
|
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i1) #0
|
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i1) #0
|
|
|
|
attributes #0 = { nounwind }
|