blob: 2c6992aef563cd207ed50a69981f726a79041842 [file] [log] [blame]
; This is a basic test of the alloca instruction.
; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \
; RUN: --target x8632 -i %s --args -O2 -allow-externally-defined-symbols \
; RUN: | %if --need=target_X8632 --command FileCheck %s
; RUN: %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command %p2i --filetype=asm --assemble --disassemble --target \
; RUN: mips32 -i %s --args -O2 -allow-externally-defined-symbols \
; RUN: | %if --need=target_MIPS32 --need=allow_dump \
; RUN: --command FileCheck --check-prefix MIPS32 %s
; Test that a sequence of allocas with less than stack alignment get fused.
define internal void @fused_small_align(i32 %arg) {
entry:
%a1 = alloca i8, i32 8, align 4
%a2 = alloca i8, i32 12, align 4
%a3 = alloca i8, i32 16, align 8
%p1 = bitcast i8* %a1 to i32*
%p2 = bitcast i8* %a2 to i32*
%p3 = bitcast i8* %a3 to i32*
store i32 %arg, i32* %p1, align 1
store i32 %arg, i32* %p2, align 1
store i32 %arg, i32* %p3, align 1
ret void
}
; CHECK-LABEL: fused_small_align
; CHECK-NEXT: sub esp,0x3c
; CHECK-NEXT: mov eax,DWORD PTR [esp+0x40]
; CHECK-NEXT: mov DWORD PTR [esp+0x10],eax
; CHECK-NEXT: mov DWORD PTR [esp+0x18],eax
; CHECK-NEXT: mov DWORD PTR [esp],eax
; CHECK-NEXT: add esp,0x3c
; MIPS32-LABEL: fused_small_align
; MIPS32: addiu sp,sp,{{.*}}
; MIPS32: move v0,a0
; MIPS32: sw v0,{{.*}}(sp)
; MIPS32: move v0,a0
; MIPS32: sw v0,{{.*}}(sp)
; MIPS32: sw a0,{{.*}}(sp)
; MIPS32: addiu sp,sp,{{.*}}
; Test that a sequence of allocas with greater than stack alignment get fused.
define internal void @fused_large_align(i32 %arg) {
entry:
%a1 = alloca i8, i32 8, align 32
%a2 = alloca i8, i32 12, align 64
%a3 = alloca i8, i32 16, align 32
%p1 = bitcast i8* %a1 to i32*
%p2 = bitcast i8* %a2 to i32*
%p3 = bitcast i8* %a3 to i32*
store i32 %arg, i32* %p1, align 1
store i32 %arg, i32* %p2, align 1
store i32 %arg, i32* %p3, align 1
ret void
}
; CHECK-LABEL: fused_large_align
; CHECK-NEXT: push ebp
; CHECK-NEXT: mov ebp,esp
; CHECK-NEXT: sub esp,0xb8
; CHECK-NEXT: and esp,0xffffffc0
; CHECK-NEXT: mov eax,DWORD PTR [ebp+0x8]
; CHECK-NEXT: mov DWORD PTR [esp+0x40],eax
; CHECK-NEXT: mov DWORD PTR [esp],eax
; CHECK-NEXT: mov DWORD PTR [esp+0x60],eax
; CHECK-NEXT: mov esp,ebp
; CHECK-NEXT: pop ebp
; MIPS32-LABEL: fused_large_align
; MIPS32: addiu sp,sp,{{.*}}
; MIPS32: sw s8,{{.*}}(sp)
; MIPS32: move s8,sp
; MIPS32: move v0,a0
; MIPS32: sw v0,{{.*}}(sp)
; MIPS32: move v0,a0
; MIPS32: sw v0,{{.*}}(sp)
; MIPS32: sw a0,{{.*}}(sp)
; MIPS32: move sp,s8
; MIPS32: lw s8,{{.*}}(sp)
; MIPS32: addiu sp,sp,{{.*}}
; Test that an interior pointer into a rematerializable variable is also
; rematerializable, and test that it is detected even when the use appears
; syntactically before the definition. Test that it is folded into mem
; operands, and also rematerializable through an lea instruction for direct use.
define internal i32 @fused_derived(i32 %arg) {
entry:
%a1 = alloca i8, i32 128, align 4
%a2 = alloca i8, i32 128, align 4
%a3 = alloca i8, i32 128, align 4
br label %block2
block1:
%a2_i32 = bitcast i8* %a2 to i32*
store i32 %arg, i32* %a2_i32, align 1
store i32 %arg, i32* %derived, align 1
ret i32 %retval
block2:
; The following are all rematerializable variables deriving from %a2.
%p2 = ptrtoint i8* %a2 to i32
%d = add i32 %p2, 12
%retval = add i32 %p2, 1
%derived = inttoptr i32 %d to i32*
br label %block1
}
; CHECK-LABEL: fused_derived
; CHECK-NEXT: sub esp,0x18c
; CHECK-NEXT: mov [[ARG:e..]],DWORD PTR [esp+0x190]
; CHECK-NEXT: jmp
; CHECK-NEXT: mov DWORD PTR [esp+0x80],[[ARG]]
; CHECK-NEXT: mov DWORD PTR [esp+0x8c],[[ARG]]
; CHECK-NEXT: lea eax,[esp+0x81]
; CHECK-NEXT: add esp,0x18c
; CHECK-NEXT: ret
; MIPS32-LABEL: fused_derived
; MIPS32: addiu sp,sp,{{.*}}
; MIPS32: b
; MIPS32: move v0,a0
; MIPS32: sw v0,{{.*}}(sp)
; MIPS32: sw a0,{{.*}}(sp)
; MIPS32: addiu v0,sp,129
; MIPS32: addiu sp,sp,{{.*}}
; Test that a fixed alloca gets referenced by the frame pointer.
define internal void @fused_small_align_with_dynamic(i32 %arg) {
entry:
%a1 = alloca i8, i32 8, align 16
br label %next
next:
%a2 = alloca i8, i32 12, align 1
%a3 = alloca i8, i32 16, align 1
%p1 = bitcast i8* %a1 to i32*
%p2 = bitcast i8* %a2 to i32*
%p3 = bitcast i8* %a3 to i32*
store i32 %arg, i32* %p1, align 1
store i32 %arg, i32* %p2, align 1
store i32 %arg, i32* %p3, align 1
ret void
}
; CHECK-LABEL: fused_small_align_with_dynamic
; CHECK-NEXT: push ebp
; CHECK-NEXT: mov ebp,esp
; CHECK-NEXT: sub esp,0x18
; CHECK-NEXT: mov eax,DWORD PTR [ebp+0x8]
; CHECK-NEXT: sub esp,0x10
; CHECK-NEXT: mov ecx,esp
; CHECK-NEXT: sub esp,0x10
; CHECK-NEXT: mov edx,esp
; CHECK-NEXT: mov DWORD PTR [ebp-0x18],eax
; CHECK-NEXT: mov DWORD PTR [ecx],eax
; CHECK-NEXT: mov DWORD PTR [edx],eax
; CHECK-NEXT: mov esp,ebp
; CHECK-NEXT: pop ebp
; MIPS32-LABEL: fused_small_align_with_dynamic
; MIPS32: addiu sp,sp,{{.*}}
; MIPS32: sw s8,{{.*}}(sp)
; MIPS32: move s8,sp
; MIPS32: addiu v0,sp,0
; MIPS32: addiu v1,sp,16
; MIPS32: move a1,a0
; MIPS32: sw a1,32(s8)
; MIPS32: move a1,a0
; MIPS32: sw a1,0(v0)
; MIPS32: sw a0,0(v1)
; MIPS32: move sp,s8
; MIPS32: lw s8,{{.*}}(sp)
; MIPS32: addiu sp,sp,{{.*}}
; Test that a sequence with greater than stack alignment and dynamic size
; get folded and referenced correctly;
define internal void @fused_large_align_with_dynamic(i32 %arg) {
entry:
%a1 = alloca i8, i32 8, align 32
%a2 = alloca i8, i32 12, align 32
%a3 = alloca i8, i32 16, align 1
%a4 = alloca i8, i32 16, align 1
br label %next
next:
%a5 = alloca i8, i32 16, align 1
%p1 = bitcast i8* %a1 to i32*
%p2 = bitcast i8* %a2 to i32*
%p3 = bitcast i8* %a3 to i32*
%p4 = bitcast i8* %a4 to i32*
%p5 = bitcast i8* %a5 to i32*
store i32 %arg, i32* %p1, align 1
store i32 %arg, i32* %p2, align 1
store i32 %arg, i32* %p3, align 1
store i32 %arg, i32* %p4, align 1
store i32 %arg, i32* %p5, align 1
ret void
}
; CHECK-LABEL: fused_large_align_with_dynamic
; CHECK-NEXT: push ebx
; CHECK-NEXT: push ebp
; CHECK-NEXT: mov ebp,esp
; CHECK-NEXT: sub esp,0x24
; CHECK-NEXT: mov eax,DWORD PTR [ebp+0xc]
; CHECK-NEXT: and esp,0xffffffe0
; CHECK-NEXT: sub esp,0x40
; CHECK-NEXT: mov ecx,esp
; CHECK-NEXT: mov edx,ecx
; CHECK-NEXT: add ecx,0x20
; CHECK-NEXT: add edx,0x0
; CHECK-NEXT: sub esp,0x10
; CHECK-NEXT: mov ebx,esp
; CHECK-NEXT: mov DWORD PTR [edx],eax
; CHECK-NEXT: mov DWORD PTR [ecx],eax
; CHECK-NEXT: mov DWORD PTR [ebp-0x14],eax
; CHECK-NEXT: mov DWORD PTR [ebp-0x24],eax
; CHECK-NEXT: mov DWORD PTR [ebx],eax
; CHECK-NEXT: mov esp,ebp
; CHECK-NEXT: pop ebp
; MIPS32-LABEL: fused_large_align_with_dynamic
; MIPS32: addiu sp,sp,{{.*}}
; MIPS32: sw s8,{{.*}}(sp)
; MIPS32: move s8,sp
; MIPS32: addiu v0,sp,0
; MIPS32: addiu v1,sp,64
; MIPS32: move a1,v0
; MIPS32: move a2,a0
; MIPS32: sw a2,0(a1)
; MIPS32: move a1,a0
; MIPS32: sw a1,32(v0)
; MIPS32: move v0,a0
; MIPS32: sw v0,80(s8)
; MIPS32: move v0,a0
; MIPS32: sw v0,96(s8)
; MIPS32: sw a0,0(v1)
; MIPS32: move sp,s8
; MIPS32: lw s8,{{.*}}(sp)
; MIPS32: addiu sp,sp,{{.*}}