1; This is a basic test of the alloca instruction. 2 3; RUN: %if --need=target_X8632 --command %p2i --filetype=obj --disassemble \ 4; RUN: --target x8632 -i %s --args -O2 -allow-externally-defined-symbols \ 5; RUN: | %if --need=target_X8632 --command FileCheck %s 6 7; RUN: %if --need=target_MIPS32 --need=allow_dump \ 8; RUN: --command %p2i --filetype=asm --assemble --disassemble --target \ 9; RUN: mips32 -i %s --args -O2 -allow-externally-defined-symbols \ 10; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 11; RUN: --command FileCheck --check-prefix MIPS32 %s 12 13; Test that a sequence of allocas with less than stack alignment get fused. 14define internal void @fused_small_align(i32 %arg) { 15entry: 16 %a1 = alloca i8, i32 8, align 4 17 %a2 = alloca i8, i32 12, align 4 18 %a3 = alloca i8, i32 16, align 8 19 %p1 = bitcast i8* %a1 to i32* 20 %p2 = bitcast i8* %a2 to i32* 21 %p3 = bitcast i8* %a3 to i32* 22 store i32 %arg, i32* %p1, align 1 23 store i32 %arg, i32* %p2, align 1 24 store i32 %arg, i32* %p3, align 1 25 ret void 26} 27; CHECK-LABEL: fused_small_align 28; CHECK-NEXT: sub esp,0x3c 29; CHECK-NEXT: mov eax,DWORD PTR [esp+0x40] 30; CHECK-NEXT: mov DWORD PTR [esp+0x10],eax 31; CHECK-NEXT: mov DWORD PTR [esp+0x18],eax 32; CHECK-NEXT: mov DWORD PTR [esp],eax 33; CHECK-NEXT: add esp,0x3c 34; MIPS32-LABEL: fused_small_align 35; MIPS32: addiu sp,sp,{{.*}} 36; MIPS32: move v0,a0 37; MIPS32: sw v0,{{.*}}(sp) 38; MIPS32: move v0,a0 39; MIPS32: sw v0,{{.*}}(sp) 40; MIPS32: sw a0,{{.*}}(sp) 41; MIPS32: addiu sp,sp,{{.*}} 42 43; Test that a sequence of allocas with greater than stack alignment get fused. 44define internal void @fused_large_align(i32 %arg) { 45entry: 46 %a1 = alloca i8, i32 8, align 32 47 %a2 = alloca i8, i32 12, align 64 48 %a3 = alloca i8, i32 16, align 32 49 %p1 = bitcast i8* %a1 to i32* 50 %p2 = bitcast i8* %a2 to i32* 51 %p3 = bitcast i8* %a3 to i32* 52 store i32 %arg, i32* %p1, align 1 53 store i32 %arg, i32* %p2, align 1 54 store i32 %arg, i32* %p3, align 1 55 ret void 56} 57; CHECK-LABEL: fused_large_align 58; CHECK-NEXT: push ebp 59; CHECK-NEXT: mov ebp,esp 60; CHECK-NEXT: sub esp,0xb8 61; CHECK-NEXT: and esp,0xffffffc0 62; CHECK-NEXT: mov eax,DWORD PTR [ebp+0x8] 63; CHECK-NEXT: mov DWORD PTR [esp+0x40],eax 64; CHECK-NEXT: mov DWORD PTR [esp],eax 65; CHECK-NEXT: mov DWORD PTR [esp+0x60],eax 66; CHECK-NEXT: mov esp,ebp 67; CHECK-NEXT: pop ebp 68; MIPS32-LABEL: fused_large_align 69; MIPS32: addiu sp,sp,{{.*}} 70; MIPS32: sw s8,{{.*}}(sp) 71; MIPS32: move s8,sp 72; MIPS32: move v0,a0 73; MIPS32: sw v0,{{.*}}(sp) 74; MIPS32: move v0,a0 75; MIPS32: sw v0,{{.*}}(sp) 76; MIPS32: sw a0,{{.*}}(sp) 77; MIPS32: move sp,s8 78; MIPS32: lw s8,{{.*}}(sp) 79; MIPS32: addiu sp,sp,{{.*}} 80 81; Test that an interior pointer into a rematerializable variable is also 82; rematerializable, and test that it is detected even when the use appears 83; syntactically before the definition. Test that it is folded into mem 84; operands, and also rematerializable through an lea instruction for direct use. 85define internal i32 @fused_derived(i32 %arg) { 86entry: 87 %a1 = alloca i8, i32 128, align 4 88 %a2 = alloca i8, i32 128, align 4 89 %a3 = alloca i8, i32 128, align 4 90 br label %block2 91block1: 92 %a2_i32 = bitcast i8* %a2 to i32* 93 store i32 %arg, i32* %a2_i32, align 1 94 store i32 %arg, i32* %derived, align 1 95 ret i32 %retval 96block2: 97; The following are all rematerializable variables deriving from %a2. 98 %p2 = ptrtoint i8* %a2 to i32 99 %d = add i32 %p2, 12 100 %retval = add i32 %p2, 1 101 %derived = inttoptr i32 %d to i32* 102 br label %block1 103} 104; CHECK-LABEL: fused_derived 105; CHECK-NEXT: sub esp,0x18c 106; CHECK-NEXT: mov [[ARG:e..]],DWORD PTR [esp+0x190] 107; CHECK-NEXT: jmp 108; CHECK-NEXT: mov DWORD PTR [esp+0x80],[[ARG]] 109; CHECK-NEXT: mov DWORD PTR [esp+0x8c],[[ARG]] 110; CHECK-NEXT: lea eax,[esp+0x81] 111; CHECK-NEXT: add esp,0x18c 112; CHECK-NEXT: ret 113; MIPS32-LABEL: fused_derived 114; MIPS32: addiu sp,sp,{{.*}} 115; MIPS32: b 116; MIPS32: move v0,a0 117; MIPS32: sw v0,{{.*}}(sp) 118; MIPS32: sw a0,{{.*}}(sp) 119; MIPS32: addiu v0,sp,129 120; MIPS32: addiu sp,sp,{{.*}} 121 122; Test that a fixed alloca gets referenced by the frame pointer. 123define internal void @fused_small_align_with_dynamic(i32 %arg) { 124entry: 125 %a1 = alloca i8, i32 8, align 16 126 br label %next 127next: 128 %a2 = alloca i8, i32 12, align 1 129 %a3 = alloca i8, i32 16, align 1 130 %p1 = bitcast i8* %a1 to i32* 131 %p2 = bitcast i8* %a2 to i32* 132 %p3 = bitcast i8* %a3 to i32* 133 store i32 %arg, i32* %p1, align 1 134 store i32 %arg, i32* %p2, align 1 135 store i32 %arg, i32* %p3, align 1 136 ret void 137} 138; CHECK-LABEL: fused_small_align_with_dynamic 139; CHECK-NEXT: push ebp 140; CHECK-NEXT: mov ebp,esp 141; CHECK-NEXT: sub esp,0x18 142; CHECK-NEXT: mov eax,DWORD PTR [ebp+0x8] 143; CHECK-NEXT: sub esp,0x10 144; CHECK-NEXT: mov ecx,esp 145; CHECK-NEXT: sub esp,0x10 146; CHECK-NEXT: mov edx,esp 147; CHECK-NEXT: mov DWORD PTR [ebp-0x18],eax 148; CHECK-NEXT: mov DWORD PTR [ecx],eax 149; CHECK-NEXT: mov DWORD PTR [edx],eax 150; CHECK-NEXT: mov esp,ebp 151; CHECK-NEXT: pop ebp 152; MIPS32-LABEL: fused_small_align_with_dynamic 153; MIPS32: addiu sp,sp,{{.*}} 154; MIPS32: sw s8,{{.*}}(sp) 155; MIPS32: move s8,sp 156; MIPS32: addiu v0,sp,0 157; MIPS32: addiu v1,sp,16 158; MIPS32: move a1,a0 159; MIPS32: sw a1,32(s8) 160; MIPS32: move a1,a0 161; MIPS32: sw a1,0(v0) 162; MIPS32: sw a0,0(v1) 163; MIPS32: move sp,s8 164; MIPS32: lw s8,{{.*}}(sp) 165; MIPS32: addiu sp,sp,{{.*}} 166 167; Test that a sequence with greater than stack alignment and dynamic size 168; get folded and referenced correctly; 169 170define internal void @fused_large_align_with_dynamic(i32 %arg) { 171entry: 172 %a1 = alloca i8, i32 8, align 32 173 %a2 = alloca i8, i32 12, align 32 174 %a3 = alloca i8, i32 16, align 1 175 %a4 = alloca i8, i32 16, align 1 176 br label %next 177next: 178 %a5 = alloca i8, i32 16, align 1 179 %p1 = bitcast i8* %a1 to i32* 180 %p2 = bitcast i8* %a2 to i32* 181 %p3 = bitcast i8* %a3 to i32* 182 %p4 = bitcast i8* %a4 to i32* 183 %p5 = bitcast i8* %a5 to i32* 184 store i32 %arg, i32* %p1, align 1 185 store i32 %arg, i32* %p2, align 1 186 store i32 %arg, i32* %p3, align 1 187 store i32 %arg, i32* %p4, align 1 188 store i32 %arg, i32* %p5, align 1 189 ret void 190} 191; CHECK-LABEL: fused_large_align_with_dynamic 192; CHECK-NEXT: push ebx 193; CHECK-NEXT: push ebp 194; CHECK-NEXT: mov ebp,esp 195; CHECK-NEXT: sub esp,0x24 196; CHECK-NEXT: mov eax,DWORD PTR [ebp+0xc] 197; CHECK-NEXT: and esp,0xffffffe0 198; CHECK-NEXT: sub esp,0x40 199; CHECK-NEXT: mov ecx,esp 200; CHECK-NEXT: mov edx,ecx 201; CHECK-NEXT: add ecx,0x20 202; CHECK-NEXT: add edx,0x0 203; CHECK-NEXT: sub esp,0x10 204; CHECK-NEXT: mov ebx,esp 205; CHECK-NEXT: mov DWORD PTR [edx],eax 206; CHECK-NEXT: mov DWORD PTR [ecx],eax 207; CHECK-NEXT: mov DWORD PTR [ebp-0x14],eax 208; CHECK-NEXT: mov DWORD PTR [ebp-0x24],eax 209; CHECK-NEXT: mov DWORD PTR [ebx],eax 210; CHECK-NEXT: mov esp,ebp 211; CHECK-NEXT: pop ebp 212; MIPS32-LABEL: fused_large_align_with_dynamic 213; MIPS32: addiu sp,sp,{{.*}} 214; MIPS32: sw s8,{{.*}}(sp) 215; MIPS32: move s8,sp 216; MIPS32: addiu v0,sp,0 217; MIPS32: addiu v1,sp,64 218; MIPS32: move a1,v0 219; MIPS32: move a2,a0 220; MIPS32: sw a2,0(a1) 221; MIPS32: move a1,a0 222; MIPS32: sw a1,32(v0) 223; MIPS32: move v0,a0 224; MIPS32: sw v0,80(s8) 225; MIPS32: move v0,a0 226; MIPS32: sw v0,96(s8) 227; MIPS32: sw a0,0(v1) 228; MIPS32: move sp,s8 229; MIPS32: lw s8,{{.*}}(sp) 230; MIPS32: addiu sp,sp,{{.*}} 231