brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · 4bad4ba Raw
242 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc %s -o - -mtriple=thumbv8m.base | FileCheck %s3 4declare i32 @g(...)5 6declare i32 @h0(i32, i32, i32, i32)7define hidden i32 @f0() {8; CHECK-LABEL: f0:9; CHECK:       @ %bb.0:10; CHECK-NEXT:    push {r7, lr}11; CHECK-NEXT:    bl g12; CHECK-NEXT:    movs r1, #113; CHECK-NEXT:    movs r2, #214; CHECK-NEXT:    movs r3, #315; CHECK-NEXT:    ldr r7, [sp, #4]16; CHECK-NEXT:    mov lr, r717; CHECK-NEXT:    pop {r7}18; CHECK-NEXT:    add sp, #419; CHECK-NEXT:    b h020  %1 = tail call i32 @g()21  %2 = tail call i32 @h0(i32 %1, i32 1, i32 2, i32 3)22  ret i32 %223}24 25declare i32 @h1(i32)26define hidden i32 @f1() {27; CHECK-LABEL: f1:28; CHECK:       @ %bb.0:29; CHECK-NEXT:    push {r7, lr}30; CHECK-NEXT:    bl g31; CHECK-NEXT:    pop {r7}32; CHECK-NEXT:    pop {r1}33; CHECK-NEXT:    mov lr, r134; CHECK-NEXT:    b h135  %1 = tail call i32 @g()36  %2 = tail call i32 @h1(i32 %1)37  ret i32 %238}39 40declare i32 @h2(i32, i32, i32, i32, i32)41define hidden i32 @f2(i32, i32, i32, i32, i32) {42; CHECK-LABEL: f2:43; CHECK:       @ %bb.0:44; CHECK-NEXT:    push {r4, r5, r6, r7, lr}45; CHECK-NEXT:    sub sp, #446; CHECK-NEXT:    mov r4, r347; CHECK-NEXT:    mov r5, r248; CHECK-NEXT:    mov r6, r149; CHECK-NEXT:    ldr r7, [sp, #24]50; CHECK-NEXT:    bl g51; CHECK-NEXT:    cbz r0, .LBB2_252; CHECK-NEXT:  @ %bb.1:53; CHECK-NEXT:    str r7, [sp, #24]54; CHECK-NEXT:    mov r1, r655; CHECK-NEXT:    mov r2, r556; CHECK-NEXT:    mov r3, r457; CHECK-NEXT:    add sp, #458; CHECK-NEXT:    ldr r4, [sp, #16]59; CHECK-NEXT:    mov lr, r460; CHECK-NEXT:    pop {r4, r5, r6, r7}61; CHECK-NEXT:    add sp, #462; CHECK-NEXT:    b h263; CHECK-NEXT:  .LBB2_2:64; CHECK-NEXT:    movs r0, #065; CHECK-NEXT:    mvns r0, r066; CHECK-NEXT:    add sp, #467; CHECK-NEXT:    pop {r4, r5, r6, r7, pc}68  %6 = tail call i32 @g()69  %7 = icmp eq i32 %6, 070  br i1 %7, label %10, label %871 72  %9 = tail call i32 @h2(i32 %6, i32 %1, i32 %2, i32 %3, i32 %4)73  br label %1074 75  %11 = phi i32 [ %9, %8 ], [ -1, %5 ]76  ret i32 %1177}78 79; Make sure that tail calls to function pointers that require r0-r3 for argument80; passing do not break the compiler.81@fnptr = global ptr null82define i32 @test3() {83; CHECK-LABEL: test3:84; CHECK:       @ %bb.0:85; CHECK-NEXT:    push {r4, lr}86; CHECK-NEXT:    movw r0, :lower16:fnptr87; CHECK-NEXT:    movt r0, :upper16:fnptr88; CHECK-NEXT:    ldr r4, [r0]89; CHECK-NEXT:    movs r0, #190; CHECK-NEXT:    movs r1, #291; CHECK-NEXT:    movs r2, #392; CHECK-NEXT:    movs r3, #493; CHECK-NEXT:    blx r494; CHECK-NEXT:    pop {r4, pc}95  %1 = load ptr, ptr @fnptr96  %2 = tail call i32 %1(i32 1, i32 2, i32 3, i32 4)97  ret i32 %298}99 100@fnptr2 = global ptr null101define i32 @test4() {102; CHECK-LABEL: test4:103; CHECK:       @ %bb.0:104; CHECK-NEXT:    push {r4, lr}105; CHECK-NEXT:    movw r0, :lower16:fnptr2106; CHECK-NEXT:    movt r0, :upper16:fnptr2107; CHECK-NEXT:    ldr r4, [r0]108; CHECK-NEXT:    movs r0, #1109; CHECK-NEXT:    movs r1, #2110; CHECK-NEXT:    movs r2, #3111; CHECK-NEXT:    movs r3, #0112; CHECK-NEXT:    blx r4113; CHECK-NEXT:    pop {r4, pc}114  %1 = load ptr, ptr @fnptr2115  %2 = tail call i32 %1(i32 1, i32 2, i64 3)116  ret i32 %2117}118 119; Check that tail calls to function pointers where not all of r0-r3 are used for120; parameter passing are tail-call optimized.121; test5: params in r0, r1. r2 & r3 are free.122@fnptr3 = global ptr null123define i32 @test5() {124; CHECK-LABEL: test5:125; CHECK:       @ %bb.0:126; CHECK-NEXT:    movw r0, :lower16:fnptr3127; CHECK-NEXT:    movt r0, :upper16:fnptr3128; CHECK-NEXT:    ldr r2, [r0]129; CHECK-NEXT:    movs r0, #1130; CHECK-NEXT:    movs r1, #2131; CHECK-NEXT:    bx r2132  %1 = load ptr, ptr @fnptr3133  %2 = tail call i32 %1(i32 1, i32 2)134  ret i32 %2135}136 137; test6: params in r0 and r2-r3. r1 is free.138@fnptr4 = global ptr null139define i32 @test6() {140; CHECK-LABEL: test6:141; CHECK:       @ %bb.0:142; CHECK-NEXT:    movw r0, :lower16:fnptr4143; CHECK-NEXT:    movt r0, :upper16:fnptr4144; CHECK-NEXT:    ldr r1, [r0]145; CHECK-NEXT:    movs r0, #1146; CHECK-NEXT:    movs r2, #2147; CHECK-NEXT:    movs r3, #0148; CHECK-NEXT:    bx r1149  %1 = load ptr, ptr @fnptr4150  %2 = tail call i32 %1(i32 1, i64 2)151  ret i32 %2152}153 154; Check that tail calls to functions other than function pointers are155; tail-call optimized.156define i32 @test7() {157; CHECK-LABEL: test7:158; CHECK:       @ %bb.0:159; CHECK-NEXT:    movs r0, #1160; CHECK-NEXT:    movs r1, #2161; CHECK-NEXT:    movs r2, #3162; CHECK-NEXT:    movs r3, #4163; CHECK-NEXT:    b bar164  %tail = tail call i32 @bar(i32 1, i32 2, i32 3, i32 4)165  ret i32 %tail166}167 168declare i32 @bar(i32, i32, i32, i32)169 170; Regression test for failure to load indirect branch target (class tcGPR) from171; a stack slot.172%struct.S = type { i32 }173 174define void @test8(ptr nocapture %fn, i32 %x) local_unnamed_addr {175; CHECK-LABEL: test8:176; CHECK:       @ %bb.0: @ %entry177; CHECK-NEXT:    push {r4, r5, r6, r7, lr}178; CHECK-NEXT:    sub sp, #4179; CHECK-NEXT:    mov r4, r1180; CHECK-NEXT:    str r0, [sp] @ 4-byte Spill181; CHECK-NEXT:    bl test8_u182; CHECK-NEXT:    mov r5, r0183; CHECK-NEXT:    ldr r6, [r0]184; CHECK-NEXT:    movs r7, #0185; CHECK-NEXT:    mov r0, r7186; CHECK-NEXT:    bl test8_h187; CHECK-NEXT:    mov r1, r0188; CHECK-NEXT:    mov r0, r6189; CHECK-NEXT:    mov r2, r7190; CHECK-NEXT:    bl test8_g191; CHECK-NEXT:    str r4, [r5]192; CHECK-NEXT:    movs r0, #1193; CHECK-NEXT:    movs r1, #2194; CHECK-NEXT:    movs r2, #3195; CHECK-NEXT:    ldr r3, [sp] @ 4-byte Reload196; CHECK-NEXT:    add sp, #4197; CHECK-NEXT:    ldr r4, [sp, #16]198; CHECK-NEXT:    mov lr, r4199; CHECK-NEXT:    pop {r4, r5, r6, r7}200; CHECK-NEXT:    add sp, #4201; CHECK-NEXT:    bx r3202entry:203  %call = tail call ptr @test8_u()204  %0 = load i32, ptr %call, align 4205  %call1 = tail call i32 @test8_h(i32 0)206  %call2 = tail call i32 @test8_g(i32 %0, i32 %call1, i32 0)207  store i32 %x, ptr %call, align 4208  %call4 = tail call i32 %fn(i32 1, i32 2, i32 3)209  ret void210}211 212declare ptr @test8_u(...)213 214declare i32 @test8_g(i32, i32, i32)215 216declare i32 @test8_h(i32)217 218; Check that we don't introduce an unnecessary spill of lr.219declare i32 @h9(i32, i32, i32, i32)220define i32 @test9(ptr %x, ptr %y, ptr %z, ptr %a) {221; CHECK-LABEL: test9:222; CHECK:       @ %bb.0:223; CHECK-NEXT:    push {r4, r7}224; CHECK-NEXT:    ldr r4, [r3]225; CHECK-NEXT:    ldr r3, [r3, #4]226; CHECK-NEXT:    adds r3, r4, r3227; CHECK-NEXT:    ldr r1, [r1]228; CHECK-NEXT:    ldr r0, [r0]229; CHECK-NEXT:    ldr r2, [r2]230; CHECK-NEXT:    pop {r4, r7}231; CHECK-NEXT:    b h9232  %zz = load i32, ptr %z233  %xx = load i32, ptr %x234  %yy = load i32, ptr %y235  %aa1 = load i32, ptr %a236  %a2 = getelementptr i32, ptr %a, i32 1237  %aa2 = load i32, ptr %a2238  %aa = add i32 %aa1, %aa2239  %r = tail call i32 @h9(i32 %xx, i32 %yy, i32 %zz, i32 %aa)240  ret i32 %r241}242