brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.9 KiB · 550542c Raw
323 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -mtriple=thumbv6m-none-eabi < %s | FileCheck %s3 4declare ptr @llvm.returnaddress(i32)5 6; We don't allocate high registers, so any function not using inline asm will7; only need to save the low registers.8define void @low_regs_only() {9; CHECK-LABEL: low_regs_only:10; CHECK:       @ %bb.0: @ %entry11; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}12; CHECK-NEXT:    push {r4, r5, r6, r7, lr}13; CHECK-NEXT:    @APP14; CHECK-NEXT:    @NO_APP15; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}16entry:17  tail call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7}"()18  ret void19}20 21; One high reg clobbered, but no low regs, args or returns. We can use an22; argument/return register to help save/restore it.23define void @one_high() {24; CHECK-LABEL: one_high:25; CHECK:       @ %bb.0: @ %entry26; CHECK-NEXT:    mov r3, r827; CHECK-NEXT:    .save {r8}28; CHECK-NEXT:    push {r3}29; CHECK-NEXT:    @APP30; CHECK-NEXT:    @NO_APP31; CHECK-NEXT:    pop {r0}32; CHECK-NEXT:    mov r8, r033; CHECK-NEXT:    bx lr34entry:35  tail call void asm sideeffect "", "~{r8}"()36  ret void37}38 39; 4 high regs clobbered, but still no low regs, args or returns. We can use all40; 4 arg/return regs for the save/restore.41define void @four_high() {42; CHECK-LABEL: four_high:43; CHECK:       @ %bb.0: @ %entry44; CHECK-NEXT:    mov r3, r1145; CHECK-NEXT:    mov r2, r1046; CHECK-NEXT:    mov r1, r947; CHECK-NEXT:    mov r0, r848; CHECK-NEXT:    .save {r8, r9, r10, r11}49; CHECK-NEXT:    push {r0, r1, r2, r3}50; CHECK-NEXT:    @APP51; CHECK-NEXT:    @NO_APP52; CHECK-NEXT:    pop {r0, r1, r2, r3}53; CHECK-NEXT:    mov r8, r054; CHECK-NEXT:    mov r9, r155; CHECK-NEXT:    mov r10, r256; CHECK-NEXT:    mov r11, r357; CHECK-NEXT:    bx lr58entry:59  tail call void asm sideeffect "", "~{r8},~{r9},~{r10},~{r11}"()60  ret void61}62 63; One high and one low register clobbered. lr also gets pushed to simplify the64; return, and r7 to keep the stack aligned. Here, we could use r0-r3, r4, r7 or65; lr to save/restore r8.66define void @one_high_one_low() {67; CHECK-LABEL: one_high_one_low:68; CHECK:       @ %bb.0: @ %entry69; CHECK-NEXT:    .save {r4, r7, lr}70; CHECK-NEXT:    push {r4, r7, lr}71; CHECK-NEXT:    mov lr, r872; CHECK-NEXT:    .save {r8}73; CHECK-NEXT:    push {lr}74; CHECK-NEXT:    @APP75; CHECK-NEXT:    @NO_APP76; CHECK-NEXT:    pop {r0}77; CHECK-NEXT:    mov r8, r078; CHECK-NEXT:    pop {r4, r7, pc}79entry:80  tail call void asm sideeffect "", "~{r4},~{r8}"()81  ret void82}83 84; All callee-saved registers clobbered, r4-r7 and lr are not live after the85; first push so can be used for pushing the high registers.86define void @four_high_four_low() {87; CHECK-LABEL: four_high_four_low:88; CHECK:       @ %bb.0: @ %entry89; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}90; CHECK-NEXT:    push {r4, r5, r6, r7, lr}91; CHECK-NEXT:    mov lr, r1192; CHECK-NEXT:    mov r7, r1093; CHECK-NEXT:    mov r6, r994; CHECK-NEXT:    mov r5, r895; CHECK-NEXT:    .save {r8, r9, r10, r11}96; CHECK-NEXT:    push {r5, r6, r7, lr}97; CHECK-NEXT:    @APP98; CHECK-NEXT:    @NO_APP99; CHECK-NEXT:    pop {r0, r1, r2, r3}100; CHECK-NEXT:    mov r8, r0101; CHECK-NEXT:    mov r9, r1102; CHECK-NEXT:    mov r10, r2103; CHECK-NEXT:    mov r11, r3104; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}105entry:106  tail call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11}"()107  ret void108}109 110 111; All callee-saved registers clobbered, and frame pointer is requested. r7 now112; cannot be used while saving/restoring the high regs.113define void @four_high_four_low_frame_ptr() "frame-pointer"="all" {114; CHECK-LABEL: four_high_four_low_frame_ptr:115; CHECK:       @ %bb.0: @ %entry116; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}117; CHECK-NEXT:    push {r4, r5, r6, r7, lr}118; CHECK-NEXT:    .setfp r7, sp, #12119; CHECK-NEXT:    add r7, sp, #12120; CHECK-NEXT:    mov lr, r11121; CHECK-NEXT:    mov r6, r10122; CHECK-NEXT:    mov r5, r9123; CHECK-NEXT:    mov r4, r8124; CHECK-NEXT:    .save {r8, r9, r10, r11}125; CHECK-NEXT:    push {r4, r5, r6, lr}126; CHECK-NEXT:    @APP127; CHECK-NEXT:    @NO_APP128; CHECK-NEXT:    pop {r0, r1, r2, r3}129; CHECK-NEXT:    mov r8, r0130; CHECK-NEXT:    mov r9, r1131; CHECK-NEXT:    mov r10, r2132; CHECK-NEXT:    mov r11, r3133; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}134entry:135  tail call void asm sideeffect "", "~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11}"()136  ret void137}138 139; All callee-saved registers clobbered, frame pointer is requested and140; llvm.returnaddress used. r7 and lr now cannot be used while saving/restoring141; the high regs.142define void @four_high_four_low_frame_ptr_ret_addr() "frame-pointer"="all" {143; CHECK-LABEL: four_high_four_low_frame_ptr_ret_addr:144; CHECK:       @ %bb.0: @ %entry145; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}146; CHECK-NEXT:    push {r4, r5, r6, r7, lr}147; CHECK-NEXT:    .setfp r7, sp, #12148; CHECK-NEXT:    add r7, sp, #12149; CHECK-NEXT:    mov r6, r11150; CHECK-NEXT:    mov r5, r10151; CHECK-NEXT:    mov r4, r9152; CHECK-NEXT:    mov r3, r8153; CHECK-NEXT:    .save {r8, r9, r10, r11}154; CHECK-NEXT:    push {r3, r4, r5, r6}155; CHECK-NEXT:    mov r0, lr156; CHECK-NEXT:    @APP157; CHECK-NEXT:    @NO_APP158; CHECK-NEXT:    pop {r0, r1, r2, r3}159; CHECK-NEXT:    mov r8, r0160; CHECK-NEXT:    mov r9, r1161; CHECK-NEXT:    mov r10, r2162; CHECK-NEXT:    mov r11, r3163; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}164entry:165  %a = tail call ptr @llvm.returnaddress(i32 0)166  tail call void asm sideeffect "", "r,~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11}"(ptr %a)167  ret void168}169 170; 4 high regs clobbered, all 4 argument registers used. We push an extra 4 low171; registers, so that we can use them for saving the high regs.172define void @four_high_four_arg(i32 %a, i32 %b, i32 %c, i32 %d) {173; CHECK-LABEL: four_high_four_arg:174; CHECK:       @ %bb.0: @ %entry175; CHECK-NEXT:    .save {r5, r6, r7, lr}176; CHECK-NEXT:    push {r5, r6, r7, lr}177; CHECK-NEXT:    mov lr, r11178; CHECK-NEXT:    mov r7, r10179; CHECK-NEXT:    mov r6, r9180; CHECK-NEXT:    mov r5, r8181; CHECK-NEXT:    .save {r8, r9, r10, r11}182; CHECK-NEXT:    push {r5, r6, r7, lr}183; CHECK-NEXT:    @APP184; CHECK-NEXT:    @NO_APP185; CHECK-NEXT:    pop {r0, r1, r2, r3}186; CHECK-NEXT:    mov r8, r0187; CHECK-NEXT:    mov r9, r1188; CHECK-NEXT:    mov r10, r2189; CHECK-NEXT:    mov r11, r3190; CHECK-NEXT:    pop {r5, r6, r7, pc}191entry:192  tail call void asm sideeffect "", "r,r,r,r,~{r8},~{r9},~{r10},~{r11}"(i32 %a, i32 %b, i32 %c, i32 %d)193  ret void194}195 196; 4 high regs clobbered, all 4 return registers used. We push an extra 4 low197; registers, so that we can use them for restoring the high regs.198define <4 x i32> @four_high_four_return() {199; CHECK-LABEL: four_high_four_return:200; CHECK:       @ %bb.0: @ %entry201; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}202; CHECK-NEXT:    push {r4, r5, r6, r7, lr}203; CHECK-NEXT:    mov lr, r11204; CHECK-NEXT:    mov r7, r10205; CHECK-NEXT:    mov r6, r9206; CHECK-NEXT:    mov r5, r8207; CHECK-NEXT:    .save {r8, r9, r10, r11}208; CHECK-NEXT:    push {r5, r6, r7, lr}209; CHECK-NEXT:    @APP210; CHECK-NEXT:    @NO_APP211; CHECK-NEXT:    movs r0, #1212; CHECK-NEXT:    movs r1, #2213; CHECK-NEXT:    movs r2, #3214; CHECK-NEXT:    movs r3, #4215; CHECK-NEXT:    pop {r4, r5, r6, r7}216; CHECK-NEXT:    mov r8, r4217; CHECK-NEXT:    mov r9, r5218; CHECK-NEXT:    mov r10, r6219; CHECK-NEXT:    mov r11, r7220; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}221entry:222  tail call void asm sideeffect "", "~{r8},~{r9},~{r10},~{r11}"()223  %vecinit = insertelement <4 x i32> undef, i32 1, i32 0224  %vecinit11 = insertelement <4 x i32> %vecinit, i32 2, i32 1225  %vecinit12 = insertelement <4 x i32> %vecinit11, i32 3, i32 2226  %vecinit13 = insertelement <4 x i32> %vecinit12, i32 4, i32 3227  ret <4 x i32> %vecinit13228}229 230; 4 high regs clobbered, all args & returns used, frame pointer requested and231; llvm.returnaddress called. This leaves us with 3 low registers available (r4,232; r5, r6), with which to save 4 high registers, so we have to use two pushes233; and pops.234define <4 x i32> @all_of_the_above(i32 %a, i32 %b, i32 %c, i32 %d) "frame-pointer"="all" {235; CHECK-LABEL: all_of_the_above:236; CHECK:       @ %bb.0: @ %entry237; CHECK-NEXT:    .save {r4, r5, r6, r7, lr}238; CHECK-NEXT:    push {r4, r5, r6, r7, lr}239; CHECK-NEXT:    .setfp r7, sp, #12240; CHECK-NEXT:    add r7, sp, #12241; CHECK-NEXT:    mov r6, r11242; CHECK-NEXT:    mov r5, r10243; CHECK-NEXT:    mov r4, r9244; CHECK-NEXT:    .save {r9, r10, r11}245; CHECK-NEXT:    push {r4, r5, r6}246; CHECK-NEXT:    mov r6, r8247; CHECK-NEXT:    .save {r8}248; CHECK-NEXT:    push {r6}249; CHECK-NEXT:    .pad #4250; CHECK-NEXT:    sub sp, #4251; CHECK-NEXT:    mov r4, lr252; CHECK-NEXT:    str r4, [sp] @ 4-byte Spill253; CHECK-NEXT:    @APP254; CHECK-NEXT:    @NO_APP255; CHECK-NEXT:    movs r1, #2256; CHECK-NEXT:    movs r2, #3257; CHECK-NEXT:    movs r3, #4258; CHECK-NEXT:    ldr r0, [sp] @ 4-byte Reload259; CHECK-NEXT:    add sp, #4260; CHECK-NEXT:    pop {r4, r5, r6}261; CHECK-NEXT:    mov r8, r4262; CHECK-NEXT:    mov r9, r5263; CHECK-NEXT:    mov r10, r6264; CHECK-NEXT:    pop {r4}265; CHECK-NEXT:    mov r11, r4266; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}267entry:268  tail call void asm sideeffect "", "r,r,r,r,~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11}"(i32 %a, i32 %b, i32 %c, i32 %d)269  %e = tail call ptr @llvm.returnaddress(i32 0)270  %f = ptrtoint ptr %e to i32271  %vecinit = insertelement <4 x i32> undef, i32 %f, i32 0272  %vecinit11 = insertelement <4 x i32> %vecinit, i32 2, i32 1273  %vecinit12 = insertelement <4 x i32> %vecinit11, i32 3, i32 2274  %vecinit13 = insertelement <4 x i32> %vecinit12, i32 4, i32 3275  ret <4 x i32> %vecinit13276}277 278; When a base pointer is being used, we can safely use it for saving/restoring279; the high regs because it is set after the last push, and not used at all in the280; epliogue. We can also use r4 for restoring the registers despite it also being281; used when restoring sp from fp, as that happens before the first pop.282define <4 x i32> @base_pointer(i32 %a) {283; CHECK-LABEL: base_pointer:284; CHECK:       @ %bb.0: @ %entry285; CHECK-NEXT:    .save {r4, r6, r7, lr}286; CHECK-NEXT:    push {r4, r6, r7, lr}287; CHECK-NEXT:    .setfp r7, sp, #8288; CHECK-NEXT:    add r7, sp, #8289; CHECK-NEXT:    mov lr, r9290; CHECK-NEXT:    mov r6, r8291; CHECK-NEXT:    .save {r8, r9}292; CHECK-NEXT:    push {r6, lr}293; CHECK-NEXT:    mov r6, sp294; CHECK-NEXT:    lsls r0, r0, #2295; CHECK-NEXT:    adds r0, r0, #7296; CHECK-NEXT:    movs r1, #7297; CHECK-NEXT:    bics r0, r1298; CHECK-NEXT:    mov r1, sp299; CHECK-NEXT:    subs r0, r1, r0300; CHECK-NEXT:    mov sp, r0301; CHECK-NEXT:    @APP302; CHECK-NEXT:    @NO_APP303; CHECK-NEXT:    movs r0, #1304; CHECK-NEXT:    movs r1, #2305; CHECK-NEXT:    movs r2, #3306; CHECK-NEXT:    movs r3, #4307; CHECK-NEXT:    subs r6, r7, #7308; CHECK-NEXT:    subs r6, #9309; CHECK-NEXT:    mov sp, r6310; CHECK-NEXT:    pop {r4, r6}311; CHECK-NEXT:    mov r8, r4312; CHECK-NEXT:    mov r9, r6313; CHECK-NEXT:    pop {r4, r6, r7, pc}314entry:315  %b = alloca i32, i32 %a316  call void asm sideeffect "", "r,~{r8},~{r9}"(ptr %b)317  %vecinit = insertelement <4 x i32> undef, i32 1, i32 0318  %vecinit11 = insertelement <4 x i32> %vecinit, i32 2, i32 1319  %vecinit12 = insertelement <4 x i32> %vecinit11, i32 3, i32 2320  %vecinit13 = insertelement <4 x i32> %vecinit12, i32 4, i32 3321  ret <4 x i32> %vecinit13322}323