
Summary: MRI::eliminateFrameIndex can emit several instructions to do address calculations; these can usually be stackified. Because instructions with FI operands can have subsequent operands which may be expression trees, find the top of the leftmost tree and insert the code before it, to keep the LIFO property. Also use stackified registers when writing back the SP value to memory in the epilog; it's unnecessary because SP will not be used after the epilog, and it results in better code. Differential Revision: http://reviews.llvm.org/D18234 llvm-svn: 263725
108 lines
3.4 KiB
LLVM
108 lines
3.4 KiB
LLVM
; RUN: llc < %s -asm-verbose=false | FileCheck %s
|
|
|
|
; Test memcpy, memmove, and memset intrinsics.
|
|
|
|
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
|
|
target triple = "wasm32-unknown-unknown"
|
|
|
|
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1)
|
|
declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture readonly, i32, i32, i1)
|
|
declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1)
|
|
|
|
; Test that return values are optimized.
|
|
|
|
; CHECK-LABEL: copy_yes:
|
|
; CHECK: i32.call $push0=, memcpy@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return $pop0{{$}}
|
|
define i8* @copy_yes(i8* %dst, i8* %src, i32 %len) {
|
|
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i32 1, i1 false)
|
|
ret i8* %dst
|
|
}
|
|
|
|
; CHECK-LABEL: copy_no:
|
|
; CHECK: i32.call $discard=, memcpy@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return{{$}}
|
|
define void @copy_no(i8* %dst, i8* %src, i32 %len) {
|
|
call void @llvm.memcpy.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i32 1, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: move_yes:
|
|
; CHECK: i32.call $push0=, memmove@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return $pop0{{$}}
|
|
define i8* @move_yes(i8* %dst, i8* %src, i32 %len) {
|
|
call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i32 1, i1 false)
|
|
ret i8* %dst
|
|
}
|
|
|
|
; CHECK-LABEL: move_no:
|
|
; CHECK: i32.call $discard=, memmove@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return{{$}}
|
|
define void @move_no(i8* %dst, i8* %src, i32 %len) {
|
|
call void @llvm.memmove.p0i8.p0i8.i32(i8* %dst, i8* %src, i32 %len, i32 1, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; CHECK-LABEL: set_yes:
|
|
; CHECK: i32.call $push0=, memset@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return $pop0{{$}}
|
|
define i8* @set_yes(i8* %dst, i8 %src, i32 %len) {
|
|
call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i32 1, i1 false)
|
|
ret i8* %dst
|
|
}
|
|
|
|
; CHECK-LABEL: set_no:
|
|
; CHECK: i32.call $discard=, memset@FUNCTION, $0, $1, $2{{$}}
|
|
; CHECK-NEXT: return{{$}}
|
|
define void @set_no(i8* %dst, i8 %src, i32 %len) {
|
|
call void @llvm.memset.p0i8.i32(i8* %dst, i8 %src, i32 %len, i32 1, i1 false)
|
|
ret void
|
|
}
|
|
|
|
|
|
; CHECK-LABEL: frame_index:
|
|
; CHECK: i32.call $discard=, memset@FUNCTION, $pop12, $pop1, $pop0{{$}}
|
|
; CHECK: i32.call $discard=, memset@FUNCTION, $0, $pop3, $pop2{{$}}
|
|
; CHECK: return{{$}}
|
|
define void @frame_index() {
|
|
entry:
|
|
%a = alloca [2048 x i8], align 16
|
|
%b = alloca [2048 x i8], align 16
|
|
%0 = getelementptr inbounds [2048 x i8], [2048 x i8]* %a, i32 0, i32 0
|
|
%1 = getelementptr inbounds [2048 x i8], [2048 x i8]* %b, i32 0, i32 0
|
|
call void @llvm.memset.p0i8.i32(i8* %0, i8 256, i32 1024, i32 16, i1 false)
|
|
call void @llvm.memset.p0i8.i32(i8* %1, i8 256, i32 1024, i32 16, i1 false)
|
|
ret void
|
|
}
|
|
|
|
; If the result value of memset doesn't get stackified, it should be marked
|
|
; $discard.
|
|
|
|
; CHECK-LABEL: discard_result:
|
|
; CHECK: i32.call $discard=, memset@FUNCTION, $0, $1, $2
|
|
declare i8* @def()
|
|
define i8* @discard_result(i8* %arg, i8 %arg1, i32 %arg2, i32 %arg3, i32 %arg4) {
|
|
bb:
|
|
%tmp = icmp eq i32 %arg3, 0
|
|
br i1 %tmp, label %bb5, label %bb9
|
|
|
|
bb5:
|
|
%tmp6 = icmp eq i32 %arg4, 0
|
|
br i1 %tmp6, label %bb7, label %bb8
|
|
|
|
bb7:
|
|
call void @llvm.memset.p0i8.i32(i8* %arg, i8 %arg1, i32 %arg2, i32 1, i1 false)
|
|
br label %bb11
|
|
|
|
bb8:
|
|
br label %bb11
|
|
|
|
bb9:
|
|
%tmp10 = call i8* @def()
|
|
br label %bb11
|
|
|
|
bb11:
|
|
%tmp12 = phi i8* [ %arg, %bb7 ], [ %arg, %bb8 ], [ %tmp10, %bb9 ]
|
|
ret i8* %tmp12
|
|
}
|