brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.0 KiB · 07a6b6d Raw
492 lines · plain
1; RUN: llc -mtriple=thumbv6m-eabi -frame-pointer=none %s -o - --verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-NOFP,CHECK-ATPCS2; RUN: llc -mtriple=thumbv6m-eabi -frame-pointer=all %s -o - --verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-FP-ATPCS,CHECK-ATPCS3; RUN: llc -mtriple=thumbv6m-eabi -frame-pointer=none -mattr=+aapcs-frame-chain %s -o - --verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-NOFP,CHECK-AAPCS4; RUN: llc -mtriple=thumbv6m-eabi -frame-pointer=all -mattr=+aapcs-frame-chain %s -o - --verify-machineinstrs | FileCheck %s --check-prefixes=CHECK,CHECK-FP-AAPCS,CHECK-AAPCS5 6; struct S { int x[128]; } s;7; int f(int *, int, int, int, struct S);8; int g(int *, int, int, int, int, int);9; int h(int *, int *, int *);10; int u(int *, int *, int *, struct S, struct S);11 12%struct.S = type { [128 x i32] }13%struct.__va_list = type { ptr }14 15@s = common dso_local global %struct.S zeroinitializer, align 416 17declare void @llvm.va_start(ptr)18declare dso_local i32 @i(i32) local_unnamed_addr19declare dso_local i32 @g(ptr, i32, i32, i32, i32, i32) local_unnamed_addr20declare dso_local i32 @f(ptr, i32, i32, i32, ptr byval(%struct.S) align 4) local_unnamed_addr21declare dso_local i32 @h(ptr, ptr, ptr) local_unnamed_addr22declare dso_local i32 @u(ptr, ptr, ptr, ptr byval(%struct.S) align 4, ptr byval(%struct.S) align 4) local_unnamed_addr23 24;25; Test access to arguments, passed on stack (including varargs)26;27 28; Usual case, access via SP if FP is not available29; int test_args_sp(int a, int b, int c, int d, int e) {30;   int v[4];31;   return g(v, a, b, c, d, e);32; }33define dso_local i32 @test_args_sp(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) local_unnamed_addr {34entry:35  %v = alloca [4 x i32], align 436  %call = call i32 @g(ptr nonnull %v, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)37  ret i32 %call38}39; CHECK-LABEL: test_args_sp40; Load `e`41; CHECK-NOFP: ldr    r0, [sp, #32]42; CHECK-FP-ATPCS: ldr  r0, [r7, #8]43; CHECK-FP-AAPCS: mov    r0, r1144; CHECK-FP-AAPCS: ldr    r0, [r0, #8]45; CHECK-NEXT:  str    r3, [sp]46; Pass `e` on stack47; CHECK-NEXT:  str    r0, [sp, #4]48; CHECK:       bl    g49 50; int test_varargs_sp(int a, ...) {51;   int v[4];52;   __builtin_va_list ap;53;   __builtin_va_start(ap, a);54;   return g(v, a, 0, 0, 0, 0);55; }56define dso_local i32 @test_varargs_sp(i32 %a, ...) local_unnamed_addr  {57entry:58  %v = alloca [4 x i32], align 459  %ap = alloca %struct.__va_list, align 460  call void @llvm.va_start(ptr nonnull %ap)61  %call = call i32 @g(ptr nonnull %v, i32 %a, i32 0, i32 0, i32 0, i32 0)62  ret i32 %call63}64; CHECK-LABEL: test_varargs_sp65; Three incoming varargs in registers66; CHECK:       sub sp, #1267; CHECK:       sub sp, #2868; Incoming arguments area is accessed via SP if FP is not available69; CHECK-NOFP:  add r0, sp, #3670; CHECK-NOFP:  stm r0!, {r1, r2, r3}71; CHECK-FP-ATPCS: mov r0, r772; CHECK-FP-ATPCS: adds r0, #873; CHECK-FP-ATPCS: stm r0!, {r1, r2, r3}74; CHECK-FP-AAPCS: mov r0, r1175; CHECK-FP-AAPCS: mov r7, r076; CHECK-FP-AAPCS: adds r7, #877; CHECK-FP-AAPCS: stm r7!, {r1, r2, r3}78; Re-aligned stack, access via FP79; int test_args_realign(int a, int b, int c, int d, int e) {80;   __attribute__((aligned(16))) int v[4];81;   return g(v, a, b, c, d, e);82; }83; Function Attrs: nounwind84define dso_local i32 @test_args_realign(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) local_unnamed_addr  {85entry:86  %v = alloca [4 x i32], align 1687  %call = call i32 @g(ptr nonnull %v, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)88  ret i32 %call89}90; CHECK-LABEL: test_args_realign91; Setup frame pointer92; CHECK-ATPCS: add r7, sp, #893; CHECK-AAPCS: mov r11, sp94; Align stack95; CHECK:       mov  r4, sp96; CHECK-NEXT:  lsrs r4, r4, #497; CHECK-NEXT:  lsls r4, r4, #498; CHECK-NEXT:  mov  sp, r499; Load `e` via FP100; CHECK-ATPCS: ldr r0, [r7, #8]101; CHECK-AAPCS: mov r0, r11102; CHECK-AAPCS: ldr r0, [r0, #8]103; CHECK-NEXT:  str r3, [sp]104; Pass `e` as argument105; CHECK-NEXT:  str r0, [sp, #4]106; CHECK:       bl    g107 108; int test_varargs_realign(int a, ...) {109;   __attribute__((aligned(16))) int v[4];110;   __builtin_va_list ap;111;   __builtin_va_start(ap, a);112;   return g(v, a, 0, 0, 0, 0);113; }114define dso_local i32 @test_varargs_realign(i32 %a, ...) local_unnamed_addr  {115entry:116  %v = alloca [4 x i32], align 16117  %ap = alloca %struct.__va_list, align 4118  call void @llvm.va_start(ptr nonnull %ap)119  %call = call i32 @g(ptr nonnull %v, i32 %a, i32 0, i32 0, i32 0, i32 0)120  ret i32 %call121}122; CHECK-LABEL: test_varargs_realign123; Three incoming register varargs124; CHECK:       sub sp, #12125; Setup frame pointer126; CHECK-ATPCS: add r7, sp, #8127; CHECK-AAPCS: mov r11, sp128; Align stack129; CHECK:       mov  r4, sp130; CHECK-NEXT:  lsrs r4, r4, #4131; CHECK-NEXT:  lsls r4, r4, #4132; CHECK-NEXT:  mov  sp, r4133; Incoming register varargs stored via FP134; CHECK-ATPCS: mov r0, r7135; CHECK-ATPCS-NEXT: adds r0, #8136; CHECK-ATPCS-NEXT: stm r0!, {r1, r2, r3}137; CHECK-AAPCS: mov r0, r11138; CHECK-AAPCS: mov r7, r0139; CHECK-AAPCS: adds r7, #8140; CHECK-AAPCS: stm r7!, {r1, r2, r3}141; VLAs present, access via FP142; int test_args_vla(int a, int b, int c, int d, int e) {143;   int v[a];144;   return g(v, a, b, c, d, e);145; }146define dso_local i32 @test_args_vla(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) local_unnamed_addr  {147entry:148  %vla = alloca i32, i32 %a, align 4149  %call = call i32 @g(ptr nonnull %vla, i32 %a, i32 %b, i32 %c, i32 %d, i32 %e)150  ret i32 %call151}152; CHECK-LABEL: test_args_vla153; Setup frame pointer154; CHECK-ATPCS: add r7, sp, #12155; CHECK-AAPCS: mov r11, sp156; Allocate outgoing stack arguments space157; CHECK:       sub sp, #8158; Load `e` via FP159; CHECK-ATPCS: ldr r5, [r7, #8]160; CHECK-AAPCS: mov r5, r11161; CHECK-AAPCS: ldr r5, [r5, #8]162; Pass `d` and `e` as arguments163; CHECK-NEXT:  str r3, [sp]164; CHECK-NEXT:  str r5, [sp, #4]165; CHECK:       bl  g166 167; int test_varargs_vla(int a, ...) {168;   int v[a];169;   __builtin_va_list ap;170;   __builtin_va_start(ap, a);171;   return g(v, a, 0, 0, 0, 0);172; }173define dso_local i32 @test_varargs_vla(i32 %a, ...) local_unnamed_addr  {174entry:175  %ap = alloca %struct.__va_list, align 4176  %vla = alloca i32, i32 %a, align 4177  call void @llvm.va_start(ptr nonnull %ap)178  %call = call i32 @g(ptr nonnull %vla, i32 %a, i32 0, i32 0, i32 0, i32 0)179  ret i32 %call180}181; CHECK-LABEL: test_varargs_vla182; Three incoming register varargs183; CHECK:       sub sp, #12184; Setup frame pointer185; CHECK-ATPCS: add r7, sp, #8186; CHECK-AAPCS: mov r11, sp187; Register varargs stored via FP188; CHECK-ATPCS-DAG:  str r3, [r7, #16]189; CHECK-ATPCS-DAG:  str r2, [r7, #12]190; CHECK-ATPCS-DAG:  str r1, [r7, #8]191; CHECK-AAPCS-DAG:  mov r5, r11192; CHECK-AAPCS-DAG:  str r1, [r5, #8]193; CHECK-AAPCS-DAG:  mov r1, r11194; CHECK-AAPCS-DAG:  str r3, [r1, #16]195; CHECK-AAPCS-DAG:  mov r1, r11196; CHECK-AAPCS-DAG:  str r2, [r1, #12]197 198; Moving SP, access via SP199; int test_args_moving_sp(int a, int b, int c, int d, int e) {200;   int v[4];201;   return f(v, a, b + c + d, e, s) + h(v, v+1, v+2);202; }203define dso_local i32 @test_args_moving_sp(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) local_unnamed_addr  {204entry:205  %v = alloca [4 x i32], align 4206  %add = add nsw i32 %c, %b207  %add1 = add nsw i32 %add, %d208  %call = call i32 @f(ptr nonnull %v, i32 %a, i32 %add1, i32 %e, ptr byval(%struct.S) nonnull align 4 @s)209  %add.ptr = getelementptr inbounds [4 x i32], ptr %v, i32 0, i32 1210  %add.ptr5 = getelementptr inbounds [4 x i32], ptr %v, i32 0, i32 2211  %call6 = call i32 @h(ptr nonnull %v, ptr nonnull %add.ptr, ptr nonnull %add.ptr5)212  %add7 = add nsw i32 %call6, %call213  ret i32 %add7214}215; CHECK-LABEL: test_args_moving_sp216; 20 bytes callee-saved area without FP217; CHECK-NOFP: push {r4, r5, r6, r7, lr}218; 20 bytes callee-saved area for ATPCS219; CHECK-FP-ATPCS: push {r4, r5, r6, r7, lr}220; 24 bytes callee-saved area for AAPCS as codegen prefers an even number of GPRs spilled221; CHECK-FP-AAPCS: push {lr}222; CHECK-FP-AAPCS: mov lr, r11223; CHECK-FP-AAPCS: push {lr}224; CHECK-FP-AAPCS: push {r4, r5, r6, r7}225; 20 bytes locals without FP226; CHECK-NOFP:       sub sp, #20227; 28 bytes locals with FP for ATPCS228; CHECK-FP-ATPCS:       sub sp, #28229; 24 bytes locals with FP for AAPCS230; CHECK-FP-AAPCS:       sub sp, #24231; Setup base pointer232; CHECK:       mov r6, sp233; Allocate outgoing arguments space234; CHECK:       sub sp, #508235; CHECK:       sub sp, #4236; Load `e` via BP if FP is not present (40 = 20 + 20)237; CHECK-NOFP:  ldr r3, [r6, #40]238; Load `e` via FP otherwise239; CHECK-FP-ATPCS: ldr r3, [r7, #8]240; CHECK-FP-AAPCS: mov r0, r11241; CHECK-FP-AAPCS: ldr r3, [r0, #8]242; CHECK:       bl  f243; Stack restored before next call244; CHECK-NEXT:  add sp, #508245; CHECK-NEXT:  add sp, #4246; CHECK:       bl  h247 248; int test_varargs_moving_sp(int a, ...) {249;   int v[4];250;   __builtin_va_list ap;251;   __builtin_va_start(ap, a);252;   return f(v, a, 0, 0, s) + h(v, v+1, v+2);253; }254define dso_local i32 @test_varargs_moving_sp(i32 %a, ...) local_unnamed_addr  {255entry:256  %v = alloca [4 x i32], align 4257  %ap = alloca %struct.__va_list, align 4258  call void @llvm.va_start(ptr nonnull %ap)259  %call = call i32 @f(ptr nonnull %v, i32 %a, i32 0, i32 0, ptr byval(%struct.S) nonnull align 4 @s)260  %add.ptr = getelementptr inbounds [4 x i32], ptr %v, i32 0, i32 1261  %add.ptr5 = getelementptr inbounds [4 x i32], ptr %v, i32 0, i32 2262  %call6 = call i32 @h(ptr nonnull %v, ptr nonnull %add.ptr, ptr nonnull %add.ptr5)263  %add = add nsw i32 %call6, %call264  ret i32 %add265}266; CHECK-LABEL: test_varargs_moving_sp267; Three incoming register varargs268; CHECK:       sub sp, #12269; 16 bytes callee-saves without FP270; CHECK-NOFP: push {r4, r5, r6, lr}271; 24 bytes callee-saves with FP272; CHECK-FP-ATPCS: push {r4, r5, r6, r7, lr}273; CHECK-FP-AAPCS: push {lr}274; CHECK-FP-AAPCS: mov lr, r11275; CHECK-FP-AAPCS: push {lr}276; CHECK-FP-AAPCS: push {r4, r5, r6, r7}277; Locals area278; CHECK-NOFP:       sub sp, #20279; CHECK-FP-ATPCS:   sub sp, #24280; CHECK-FP-AAPCS:   sub sp, #20281; Incoming varargs stored via BP if FP is not present (36 = 20 + 16)282; CHECK-NOFP:      mov r0, r6283; CHECK-NOFP-NEXT: adds r0, #36284; CHECK-NOFP-NEXT: stm r0!, {r1, r2, r3}285; Incoming varargs stored via FP otherwise286; CHECK-FP-ATPCS:      mov r0, r7287; CHECK-FP-ATPCS-NEXT: adds r0, #8288; CHECK-FP-ATPCS-NEXT: stm r0!, {r1, r2, r3}289; CHECK-FP-AAPCS:      mov r0, r11290; CHECK-FP-AAPCS-NEXT: mov r5, r0291; CHECK-FP-AAPCS-NEXT: adds r5, #8292; CHECK-FP-AAPCS-NEXT: stm r5!, {r1, r2, r3}293 294; struct S { int x[128]; } s;295; int test(S a, int b) {296;   return i(b);297; }298define dso_local i32 @test_args_large_offset(ptr byval(%struct.S) align 4 %0, i32 %1) local_unnamed_addr {299  %3 = alloca i32, align 4300  store i32 %1, ptr %3, align 4301  %4 = load i32, ptr %3, align 4302  %5 = call i32 @i(i32 %4)303  ret i32 %5304}305; CHECK-LABEL: test_args_large_offset306; Without FP: Access to large offset is made using SP307; CHECK-NOFP:     ldr r0, [sp, #520]308; With FP: Access to large offset is made through a const pool using FP309; CHECK-FP:       ldr r0, .LCPI0_0310; CHECK-FP-ATPCS: ldr r0, [r0, r7]311; CHECK-FP-AAPCS: add r0, r11312; CHECK-FP-AAPCS: ldr r0, [r0]313; CHECK: bl i314 315;316; Access to locals317;318 319; Usual case, access via SP.320; int test_local(int n) {321;   int v[4];322;   int x, y, z;323;   h(&x, &y, &z);324;   return g(v, x, y, z, 0, 0);325; }326define dso_local i32 @test_local(i32 %n) local_unnamed_addr  {327entry:328  %v = alloca [4 x i32], align 4329  %x = alloca i32, align 4330  %y = alloca i32, align 4331  %z = alloca i32, align 4332  %call = call i32 @h(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z)333  %0 = load i32, ptr %x, align 4334  %1 = load i32, ptr %y, align 4335  %2 = load i32, ptr %z, align 4336  %call1 = call i32 @g(ptr nonnull %v, i32 %0, i32 %1, i32 %2, i32 0, i32 0)337  ret i32 %call1338}339; CHECK-LABEL: test_local340; Arguments to `h` relative to SP341; CHECK:       add r0, sp, #20342; CHECK-NEXT:  add r1, sp, #16343; CHECK-NEXT:  add r2, sp, #12344; CHECK-NEXT:  bl  h345; Load `x`, `y`, and `z` via SP346; CHECK:       ldr r1, [sp, #20]347; CHECK-NEXT:  ldr r2, [sp, #16]348; CHECK-NEXT:  ldr r3, [sp, #12]349; CHECK:       bl  g350 351; Re-aligned stack, access via SP.352; int test_local_realign(int n) {353;   __attribute__((aligned(16))) int v[4];354;   int x, y, z;355;   h(&x, &y, &z);356;   return g(v, x, y, z, 0, 0);357; }358define dso_local i32 @test_local_realign(i32 %n) local_unnamed_addr  {359entry:360  %v = alloca [4 x i32], align 16361  %x = alloca i32, align 4362  %y = alloca i32, align 4363  %z = alloca i32, align 4364  %call = call i32 @h(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z)365  %0 = load i32, ptr %x, align 4366  %1 = load i32, ptr %y, align 4367  %2 = load i32, ptr %z, align 4368  %call1 = call i32 @g(ptr nonnull %v, i32 %0, i32 %1, i32 %2, i32 0, i32 0)369  ret i32 %call1370}371; CHECK-LABEL: test_local_realign372; Setup frame pointer373; CHECK-ATPCS: add r7, sp, #8374; CHECK-AAPCS: mov r11, sp375; Re-align stack376; CHECK:       mov r4, sp377; CHECK-NEXT:  lsrs r4, r4, #4378; CHECK-NEXT:  lsls r4, r4, #4379; CHECK-NEXT:  mov  sp, r4380; Arguments to `h` computed relative to SP381; CHECK:       add r0, sp, #28382; CHECK-NEXT:  add r1, sp, #24383; CHECK-NEXT:  add r2, sp, #20384; CHECK-NEXT:  bl  h385; Load `x`, `y`, and `z` via SP for passing to `g`386; CHECK:       ldr r1, [sp, #28]387; CHECK-NEXT:  ldr r2, [sp, #24]388; CHECK-NEXT:  ldr r3, [sp, #20]389; CHECK:       bl  g390 391; VLAs, access via BP.392; int test_local_vla(int n) {393;   int v[n];394;   int x, y, z;395;   h(&x, &y, &z);396;   return g(v, x, y, z, 0, 0);397; }398define dso_local i32 @test_local_vla(i32 %n) local_unnamed_addr  {399entry:400  %x = alloca i32, align 4401  %y = alloca i32, align 4402  %z = alloca i32, align 4403  %vla = alloca i32, i32 %n, align 4404  %call = call i32 @h(ptr nonnull %x, ptr nonnull %y, ptr nonnull %z)405  %0 = load i32, ptr %x, align 4406  %1 = load i32, ptr %y, align 4407  %2 = load i32, ptr %z, align 4408  %call1 = call i32 @g(ptr nonnull %vla, i32 %0, i32 %1, i32 %2, i32 0, i32 0)409  ret i32 %call1410}411; CHECK-LABEL: test_local_vla412; Setup frame pointer413; CHECK-ATPCS: add r7, sp, #12414; CHECK-AAPCS: mov r11, sp415; Locas area416; CHECK-ATPCS: sub sp, #12417; CHECK-AAPCS: sub sp, #16418; Setup base pointer419; CHECK:       mov  r6, sp420; CHECK-ATPCS: mov  r5, r6421; CHECK-AAPCS: adds  r5, r6, #4422; Arguments to `h` compute relative to BP423; CHECK:       adds r0, r6, #7424; CHECK-ATPCS-NEXT:  adds r0, #1425; CHECK-ATPCS-NEXT:  adds r1, r6, #4426; CHECK-ATPCS-NEXT:  mov  r2, r6427; CHECK-AAPCS-NEXT:  adds r0, #5428; CHECK-AAPCS-NEXT:  adds r1, r6, #7429; CHECK-AAPCS-NEXT:  adds r1, #1430; CHECK-AAPCS-NEXT:  adds r2, r6, #4431; CHECK-NEXT:  bl   h432; Load `x`, `y`, `z` via BP (r5 should still have the value of r6 from the move433; above)434; CHECK:       ldr r3, [r5]435; CHECK-NEXT:  ldr r2, [r5, #4]436; CHECK-NEXT:  ldr r1, [r5, #8]437; CHECK:       bl  g438 439;  Moving SP, access via SP.440; int test_local_moving_sp(int n) {441;   int v[4];442;   int x, y, z;443;   return u(v, &x, &y, s, s) + u(v, &y, &z, s, s);444; }445define dso_local i32 @test_local_moving_sp(i32 %n) local_unnamed_addr {446entry:447  %v = alloca [4 x i32], align 4448  %x = alloca i32, align 4449  %y = alloca i32, align 4450  %z = alloca i32, align 4451  %call = call i32 @u(ptr nonnull %v, ptr nonnull %x, ptr nonnull %y, ptr byval(%struct.S) nonnull align 4 @s, ptr byval(%struct.S) nonnull align 4 @s)452  %call2 = call i32 @u(ptr nonnull %v, ptr nonnull %y, ptr nonnull %z, ptr byval(%struct.S) nonnull align 4 @s, ptr byval(%struct.S) nonnull align 4 @s)453  %add = add nsw i32 %call2, %call454  ret i32 %add455}456; CHECK-LABEL: test_local_moving_sp457; Locals area458; CHECK-NOFP: sub sp, #36459; CHECK-FP-ATPCS: sub sp, #44460; CHECK-FP-AAPCS: sub sp, #40461; Setup BP462; CHECK:      mov r6, sp463; Outoging arguments464; CHECK:      sub sp, #508465; CHECK-NEXT: sub sp, #508466; CHECK-NEXT: sub sp, #8467; Argument addresses computed relative to BP468; CHECK-NOFP:      adds r4, r6, #7469; CHECK-NOFP-NEXT: adds r4, #13470; CHECK-NOFP:      adds r1, r6, #7471; CHECK-NOFP-NEXT: adds r1, #9472; CHECK-NOFP:      adds r5, r6, #7473; CHECK-NOFP-NEXT: adds r5, #5474; CHECK-FP-ATPCS:      adds r0, r6, #7475; CHECK-FP-ATPCS-NEXT: adds r0, #21476; CHECK-FP-ATPCS:      adds r1, r6, #7477; CHECK-FP-ATPCS-NEXT: adds r1, #17478; CHECK-FP-ATPCS:      adds r5, r6, #7479; CHECK-FP-ATPCS-NEXT: adds r5, #13480; CHECK-FP-AAPCS:      adds r4, r6, #7481; CHECK-FP-AAPCS-NEXT: adds r4, #17482; CHECK-FP-AAPCS:      adds r1, r6, #7483; CHECK-FP-AAPCS-NEXT: adds r1, #13484; CHECK-FP-AAPCS:      adds r5, r6, #7485; CHECK-FP-AAPCS-NEXT: adds r5, #9486; CHECK:      bl   u487; Stack restored before next call488; CHECK:      add  sp, #508489; CHECK-NEXT: add  sp, #508490; CHECK-NEXT: add  sp, #8491; CHECK:      bl   u492