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_X8632 --command %p2i --filetype=obj --disassemble \ 8; RUN: --target x8632 -i %s --args -Om1 -allow-externally-defined-symbols \ 9; RUN: | %if --need=target_X8632 --command FileCheck \ 10; RUN: --check-prefix CHECK-OPTM1 %s 11 12; RUN: %if --need=target_ARM32 \ 13; RUN: --command %p2i --filetype=obj \ 14; RUN: --disassemble --target arm32 -i %s --args -O2 \ 15; RUN: -allow-externally-defined-symbols \ 16; RUN: | %if --need=target_ARM32 \ 17; RUN: --command FileCheck --check-prefix ARM32 --check-prefix=ARM-OPT2 %s 18 19; RUN: %if --need=target_ARM32 \ 20; RUN: --command %p2i --filetype=obj \ 21; RUN: --disassemble --target arm32 -i %s --args -Om1 \ 22; RUN: -allow-externally-defined-symbols \ 23; RUN: | %if --need=target_ARM32 \ 24; RUN: --command FileCheck --check-prefix ARM32 --check-prefix=ARM-OPTM1 %s 25 26; RUN: %if --need=target_MIPS32 --need=allow_dump \ 27; RUN: --command %p2i --filetype=asm --assemble \ 28; RUN: --disassemble --target mips32 -i %s --args -O2 \ 29; RUN: -allow-externally-defined-symbols \ 30; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 31; RUN: --command FileCheck --check-prefix MIPS32 --check-prefix=MIPS32-OPT2 %s 32 33; RUN: %if --need=target_MIPS32 --need=allow_dump \ 34; RUN: --command %p2i --filetype=asm --assemble \ 35; RUN: --disassemble --target mips32 -i %s --args -Om1 \ 36; RUN: -allow-externally-defined-symbols \ 37; RUN: | %if --need=target_MIPS32 --need=allow_dump \ 38; RUN: --command FileCheck --check-prefix MIPS32 --check-prefix=MIPS32-OPTM1 %s 39 40define internal void @fixed_416_align_16(i32 %n) { 41entry: 42 %array = alloca i8, i32 416, align 16 43 %__2 = ptrtoint i8* %array to i32 44 call void @f1(i32 %__2) 45 ret void 46} 47; CHECK-LABEL: fixed_416_align_16 48; CHECK: sub esp,0x1bc 49; CHECK: lea eax,[esp+0x10] 50; CHECK: mov DWORD PTR [esp],eax 51; CHECK: call {{.*}} R_{{.*}} f1 52 53; CHECK-OPTM1-LABEL: fixed_416_align_16 54; CHECK-OPTM1: sub esp,0x18 55; CHECK-OPTM1: sub esp,0x1a0 56; CHECK-OPTM1: mov DWORD PTR [esp],eax 57; CHECK-OPTM1: call {{.*}} R_{{.*}} f1 58 59; ARM32-LABEL: fixed_416_align_16 60; ARM32-OPT2: sub sp, sp, #428 61; ARM32-OPTM1: sub sp, sp, #416 62; ARM32: bl {{.*}} R_{{.*}} f1 63 64; MIPS32-LABEL: fixed_416_align_16 65; MIPS32-OPT2: addiu sp,sp,-448 66; MIPS32-OPT2: addiu a0,sp,16 67; MIPS32-OPTM1: addiu sp,sp,-464 68; MIPS32-OPTM1: addiu [[REG:.*]],sp,16 69; MIPS32-OPTM1: sw [[REG]],{{.*}} 70; MIPS32-OPTM1: lw a0,{{.*}} 71; MIPS32: jal {{.*}} R_{{.*}} f1 72 73define internal void @fixed_416_align_32(i32 %n) { 74entry: 75 %array = alloca i8, i32 400, align 32 76 %__2 = ptrtoint i8* %array to i32 77 call void @f1(i32 %__2) 78 ret void 79} 80; CHECK-LABEL: fixed_416_align_32 81; CHECK: push ebp 82; CHECK-NEXT: mov ebp,esp 83; CHECK: sub esp,0x1d8 84; CHECK: and esp,0xffffffe0 85; CHECK: lea eax,[esp+0x10] 86; CHECK: mov DWORD PTR [esp],eax 87; CHECK: call {{.*}} R_{{.*}} f1 88 89; ARM32-LABEL: fixed_416_align_32 90; ARM32-OPT2: sub sp, sp, #424 91; ARM32-OPTM1: sub sp, sp, #416 92; ARM32: bic sp, sp, #31 93; ARM32: bl {{.*}} R_{{.*}} f1 94 95; MIPS32-LABEL: fixed_416_align_32 96; MIPS32-OPT2: addiu sp,sp,-448 97; MIPS32-OPT2: addiu a0,sp,16 98; MIPS32-OPTM1: addiu sp,sp,-464 99; MIPS32-OPTM1: addiu [[REG:.*]],sp,32 100; MIPS32-OPTM1: sw [[REG]],{{.*}} 101; MIPS32-OPTM1: lw a0,{{.*}} 102; MIPS32: jal {{.*}} R_{{.*}} f1 103 104; Show that the amount to allocate will be rounded up. 105define internal void @fixed_351_align_16(i32 %n) { 106entry: 107 %array = alloca i8, i32 351, align 16 108 %__2 = ptrtoint i8* %array to i32 109 call void @f1(i32 %__2) 110 ret void 111} 112; CHECK-LABEL: fixed_351_align_16 113; CHECK: sub esp,0x17c 114; CHECK: lea eax,[esp+0x10] 115; CHECK: mov DWORD PTR [esp],eax 116; CHECK: call {{.*}} R_{{.*}} f1 117 118; CHECK-OPTM1-LABEL: fixed_351_align_16 119; CHECK-OPTM1: sub esp,0x18 120; CHECK-OPTM1: sub esp,0x160 121; CHECK-OPTM1: mov DWORD PTR [esp],eax 122; CHECK-OPTM1: call {{.*}} R_{{.*}} f1 123 124; ARM32-LABEL: fixed_351_align_16 125; ARM32-OPT2: sub sp, sp, #364 126; ARM32-OPTM1: sub sp, sp, #352 127; ARM32: bl {{.*}} R_{{.*}} f1 128 129; MIPS32-LABEL: fixed_351_align_16 130; MIPS32-OPT2: addiu sp,sp,-384 131; MIPS32-OPT2: addiu a0,sp,16 132; MIPS32-OPTM1: addiu sp,sp,-400 133; MIPS32-OPTM1: addiu [[REG:.*]],sp,16 134; MIPS32-OPTM1: sw [[REG]],{{.*}} 135; MIPS32-OPTM1: lw a0,{{.*}} 136; MIPS32: jal {{.*}} R_{{.*}} f1 137 138define internal void @fixed_351_align_32(i32 %n) { 139entry: 140 %array = alloca i8, i32 351, align 32 141 %__2 = ptrtoint i8* %array to i32 142 call void @f1(i32 %__2) 143 ret void 144} 145; CHECK-LABEL: fixed_351_align_32 146; CHECK: push ebp 147; CHECK-NEXT: mov ebp,esp 148; CHECK: sub esp,0x198 149; CHECK: and esp,0xffffffe0 150; CHECK: lea eax,[esp+0x10] 151; CHECK: mov DWORD PTR [esp],eax 152; CHECK: call {{.*}} R_{{.*}} f1 153 154; ARM32-LABEL: fixed_351_align_32 155; ARM32-OPT2: sub sp, sp, #360 156; ARM32-OPTM1: sub sp, sp, #352 157; ARM32: bic sp, sp, #31 158; ARM32: bl {{.*}} R_{{.*}} f1 159 160; MIPS32-LABEL: fixed_351_align_32 161; MIPS32-OPT2: addiu sp,sp,-384 162; MIPS32-OPT2: addiu a0,sp,16 163; MIPS32-OPTM1: addiu sp,sp,-400 164; MIPS32-OPTM1: addiu [[REG:.*]],sp,32 165; MIPS32-OPTM1: sw [[REG]],{{.*}} 166; MIPS32-OPTM1: lw a0,{{.*}} 167; MIPS32: jal {{.*}} R_{{.*}} f1 168 169declare void @f1(i32 %ignored) 170 171declare void @f2(i32 %ignored) 172 173define internal void @variable_n_align_16(i32 %n) { 174entry: 175 %array = alloca i8, i32 %n, align 16 176 %__2 = ptrtoint i8* %array to i32 177 call void @f2(i32 %__2) 178 ret void 179} 180; CHECK-LABEL: variable_n_align_16 181; CHECK: sub esp,0x18 182; CHECK: mov eax,DWORD PTR [ebp+0x8] 183; CHECK: add eax,0xf 184; CHECK: and eax,0xfffffff0 185; CHECK: sub esp,eax 186; CHECK: lea eax,[esp+0x10] 187; CHECK: mov DWORD PTR [esp],eax 188; CHECK: call {{.*}} R_{{.*}} f2 189 190; ARM32-LABEL: variable_n_align_16 191; ARM32: add r0, r0, #15 192; ARM32: bic r0, r0, #15 193; ARM32: sub sp, sp, r0 194; ARM32: bl {{.*}} R_{{.*}} f2 195 196; MIPS32-LABEL: variable_n_align_16 197; MIPS32: addiu [[REG:.*]],{{.*}},15 198; MIPS32: li [[REG1:.*]],-16 199; MIPS32: and [[REG2:.*]],[[REG]],[[REG1]] 200; MIPS32: subu [[REG3:.*]],sp,[[REG2:.*]] 201; MIPS32: li [[REG4:.*]],-16 202; MIPS32: and {{.*}},[[REG3]],[[REG4]] 203; MIPS32: addiu sp,sp,-16 204; MIPS32: jal {{.*}} R_{{.*}} f2 205; MIPS32: addiu sp,sp,16 206 207define internal void @variable_n_align_32(i32 %n) { 208entry: 209 %array = alloca i8, i32 %n, align 32 210 %__2 = ptrtoint i8* %array to i32 211 call void @f2(i32 %__2) 212 ret void 213} 214; In -O2, the order of the CHECK-DAG lines in the output is switched. 215; CHECK-LABEL: variable_n_align_32 216; CHECK: push ebp 217; CHECK: mov ebp,esp 218; CHECK: sub esp,0x18 219; CHECK-DAG: and esp,0xffffffe0 220; CHECK-DAG: mov eax,DWORD PTR [ebp+0x8] 221; CHECK: add eax,0x1f 222; CHECK: and eax,0xffffffe0 223; CHECK: sub esp,eax 224; CHECK: lea eax,[esp+0x10] 225; CHECK: mov DWORD PTR [esp],eax 226; CHECK: call {{.*}} R_{{.*}} f2 227; CHECK: mov esp,ebp 228; CHECK: pop ebp 229 230; ARM32-LABEL: variable_n_align_32 231; ARM32: push {fp, lr} 232; ARM32: mov fp, sp 233; ARM32: bic sp, sp, #31 234; ARM32: add r0, r0, #31 235; ARM32: bic r0, r0, #31 236; ARM32: sub sp, sp, r0 237; ARM32: bl {{.*}} R_{{.*}} f2 238; ARM32: mov sp, fp 239; ARM32: pop {fp, lr} 240 241; MIPS32-LABEL: variable_n_align_32 242; MIPS32: addiu [[REG:.*]],{{.*}},15 243; MIPS32: li [[REG1:.*]],-16 244; MIPS32: and [[REG2:.*]],[[REG]],[[REG1]] 245; MIPS32: subu [[REG3:.*]],sp,[[REG2]] 246; MIPS32: li [[REG4:.*]],-32 247; MIPS32: and {{.*}},[[REG3]],[[REG4]] 248; MIPS32: addiu sp,sp,-16 249; MIPS32: jal {{.*}} R_{{.*}} f2 250; MIPS32: addiu sp,sp,16 251 252; Test alloca with default (0) alignment. 253define internal void @align0(i32 %n) { 254entry: 255 %array = alloca i8, i32 %n 256 %__2 = ptrtoint i8* %array to i32 257 call void @f2(i32 %__2) 258 ret void 259} 260; CHECK-LABEL: align0 261; CHECK: add [[REG:.*]],0xf 262; CHECK: and [[REG]],0xfffffff0 263; CHECK: sub esp,[[REG]] 264 265; ARM32-LABEL: align0 266; ARM32: add r0, r0, #15 267; ARM32: bic r0, r0, #15 268; ARM32: sub sp, sp, r0 269 270; MIPS32-LABEL: align0 271; MIPS32: addiu [[REG:.*]],{{.*}},15 272; MIPS32: li [[REG1:.*]],-16 273; MIPS32: and [[REG2:.*]],[[REG]],[[REG1]] 274; MIPS32: subu {{.*}},sp,[[REG2]] 275; MIPS32: addiu sp,sp,-16 276; MIPS32: jal {{.*}} R_{{.*}} f2 277; MIPS32: addiu sp,sp,16 278 279; Test a large alignment where a mask might not fit in an immediate 280; field of an instruction for some architectures. 281define internal void @align1MB(i32 %n) { 282entry: 283 %array = alloca i8, i32 %n, align 1048576 284 %__2 = ptrtoint i8* %array to i32 285 call void @f2(i32 %__2) 286 ret void 287} 288; CHECK-LABEL: align1MB 289; CHECK: push ebp 290; CHECK-NEXT: mov ebp,esp 291; CHECK: and esp,0xfff00000 292; CHECK: add [[REG:.*]],0xfffff 293; CHECK: and [[REG]],0xfff00000 294; CHECK: sub esp,[[REG]] 295 296; ARM32-LABEL: align1MB 297; ARM32: movw [[REG:.*]], #0 298; ARM32: movt [[REG]], #65520 ; 0xfff0 299; ARM32: and sp, sp, [[REG]] 300; ARM32: movw [[REG2:.*]], #65535 ; 0xffff 301; ARM32: movt [[REG2]], #15 302; ARM32: add r0, r0, [[REG2]] 303; ARM32: movw [[REG3:.*]], #0 304; ARM32: movt [[REG3]], #65520 ; 0xfff0 305; ARM32: and r0, r0, [[REG3]] 306; ARM32: sub sp, sp, r0 307 308; MIPS32-LABEL: align1MB 309; MIPS32: addiu [[REG:.*]],{{.*}},15 310; MIPS32: li [[REG1:.*]],-16 311; MIPS32: and [[REG2:.*]],[[REG]],[[REG1]] 312; MIPS32: subu [[REG3:.*]],sp,[[REG2]] 313; MIPS32: lui [[REG4:.*]],0xfff0 314; MIPS32: and {{.*}},[[REG3]],[[REG4]] 315; MIPS32: addiu sp,sp,-16 316; MIPS32: jal {{.*}} R_{{.*}} f2 317; MIPS32: addiu sp,sp,16 318 319; Test a large alignment where a mask might still fit in an immediate 320; field of an instruction for some architectures. 321define internal void @align512MB(i32 %n) { 322entry: 323 %array = alloca i8, i32 %n, align 536870912 324 %__2 = ptrtoint i8* %array to i32 325 call void @f2(i32 %__2) 326 ret void 327} 328; CHECK-LABEL: align512MB 329; CHECK: push ebp 330; CHECK-NEXT: mov ebp,esp 331; CHECK: and esp,0xe0000000 332; CHECK: add [[REG:.*]],0x1fffffff 333; CHECK: and [[REG]],0xe0000000 334; CHECK: sub esp,[[REG]] 335 336; ARM32-LABEL: align512MB 337; ARM32: and sp, sp, #-536870912 ; 0xe0000000 338; ARM32: mvn [[REG:.*]], #-536870912 ; 0xe0000000 339; ARM32: add r0, r0, [[REG]] 340; ARM32: and r0, r0, #-536870912 ; 0xe0000000 341; ARM32: sub sp, sp, r0 342 343; MIPS32-LABEL: align512MB 344; MIPS32: addiu [[REG:.*]],{{.*}},15 345; MIPS32: li [[REG2:.*]],-16 346; MIPS32: and [[REG3:.*]],[[REG]],[[REG2]] 347; MIPS32: subu [[REG4:.*]],sp,[[REG3]] 348; MIPS32: lui [[REG5:.*]],0xe000 349; MIPS32: and {{.*}},[[REG4]],[[REG5]] 350; MIPS32: addiu sp,sp,-16 351; MIPS32: jal {{.*}} R_{{.*}} f2 352; MIPS32: addiu sp,sp,16 353 354; Test that a simple alloca sequence doesn't trigger a frame pointer. 355define internal void @fixed_no_frameptr(i32 %arg) { 356entry: 357 %a1 = alloca i8, i32 8, align 4 358 %a2 = alloca i8, i32 12, align 4 359 %a3 = alloca i8, i32 16, align 4 360 %p1 = bitcast i8* %a1 to i32* 361 %p2 = bitcast i8* %a2 to i32* 362 %p3 = bitcast i8* %a3 to i32* 363 store i32 %arg, i32* %p1, align 1 364 store i32 %arg, i32* %p2, align 1 365 store i32 %arg, i32* %p3, align 1 366 ret void 367} 368; CHECK-LABEL: fixed_no_frameptr 369; CHECK-NOT: mov ebp,esp 370 371; Test that a simple alloca sequence with at least one large alignment does 372; trigger a frame pointer. 373define internal void @fixed_bigalign_with_frameptr(i32 %arg) { 374entry: 375 %a1 = alloca i8, i32 8, align 4 376 %a2 = alloca i8, i32 12, align 4 377 %a3 = alloca i8, i32 16, align 64 378 %p1 = bitcast i8* %a1 to i32* 379 %p2 = bitcast i8* %a2 to i32* 380 %p3 = bitcast i8* %a3 to i32* 381 store i32 %arg, i32* %p1, align 1 382 store i32 %arg, i32* %p2, align 1 383 store i32 %arg, i32* %p3, align 1 384 ret void 385} 386; CHECK-LABEL: fixed_bigalign_with_frameptr 387; CHECK: mov ebp,esp 388 389; Test that a more complex alloca sequence does trigger a frame pointer. 390define internal void @var_with_frameptr(i32 %arg) { 391entry: 392 %a1 = alloca i8, i32 8, align 4 393 %a2 = alloca i8, i32 12, align 4 394 %a3 = alloca i8, i32 %arg, align 4 395 %p1 = bitcast i8* %a1 to i32* 396 %p2 = bitcast i8* %a2 to i32* 397 %p3 = bitcast i8* %a3 to i32* 398 store i32 %arg, i32* %p1, align 1 399 store i32 %arg, i32* %p2, align 1 400 store i32 %arg, i32* %p3, align 1 401 ret void 402} 403; CHECK-LABEL: var_with_frameptr 404; CHECK: mov ebp,esp 405