1; RUN: llc < %s -mtriple=thumbv6-apple-darwin | FileCheck %s 2; RUN: llc < %s -mtriple=thumbv6-apple-darwin -regalloc=basic | FileCheck %s 3; RUN: llc < %s -o %t -filetype=obj -mtriple=thumbv6-apple-darwin 4; RUN: llvm-objdump -triple=thumbv6-apple-darwin -d %t | FileCheck %s 5 6@__bar = external hidden global i8* 7@__baz = external hidden global i8* 8 9; rdar://8819685 10define i8* @_foo() { 11entry: 12; CHECK-LABEL: foo: 13 14 %size = alloca i32, align 4 15 %0 = load i8** @__bar, align 4 16 %1 = icmp eq i8* %0, null 17 br i1 %1, label %bb1, label %bb3 18; CHECK: bne 19 20bb1: 21 store i32 1026, i32* %size, align 4 22 %2 = alloca [1026 x i8], align 1 23; CHECK: mov [[R0:r[0-9]+]], sp 24; CHECK: adds {{r[0-9]+}}, [[R0]], {{r[0-9]+}} 25 %3 = getelementptr inbounds [1026 x i8]* %2, i32 0, i32 0 26 %4 = call i32 @_called_func(i8* %3, i32* %size) nounwind 27 %5 = icmp eq i32 %4, 0 28 br i1 %5, label %bb2, label %bb3 29 30bb2: 31 %6 = call i8* @strdup(i8* %3) nounwind 32 store i8* %6, i8** @__baz, align 4 33 br label %bb3 34 35bb3: 36 %.0 = phi i8* [ %0, %entry ], [ %6, %bb2 ], [ %3, %bb1 ] 37; CHECK: subs r4, #5 38; CHECK-NEXT: mov sp, r4 39; CHECK-NEXT: pop {r4, r5, r6, r7, pc} 40 ret i8* %.0 41} 42 43declare noalias i8* @strdup(i8* nocapture) nounwind 44declare i32 @_called_func(i8*, i32*) nounwind 45 46; Variable ending up at unaligned offset from sp (i.e. not a multiple of 4) 47define void @test_local_var_addr() { 48; CHECK-LABEL: test_local_var_addr: 49 50 %addr1 = alloca i8 51 %addr2 = alloca i8 52 53; CHECK: mov r0, sp 54; CHECK: adds r0, #{{[0-9]+}} 55; CHECK: blx 56 call void @take_ptr(i8* %addr1) 57 58; CHECK: mov r0, sp 59; CHECK: adds r0, #{{[0-9]+}} 60; CHECK: blx 61 call void @take_ptr(i8* %addr2) 62 63 ret void 64} 65 66; Simple variable ending up *at* sp. 67define void @test_simple_var() { 68; CHECK-LABEL: test_simple_var: 69 70 %addr32 = alloca i32 71 %addr8 = bitcast i32* %addr32 to i8* 72 73; CHECK: mov r0, sp 74; CHECK-NOT: adds r0 75; CHECK: blx 76 call void @take_ptr(i8* %addr8) 77 ret void 78} 79 80; Simple variable ending up at aligned offset from sp. 81define void @test_local_var_addr_aligned() { 82; CHECK-LABEL: test_local_var_addr_aligned: 83 84 %addr1.32 = alloca i32 85 %addr1 = bitcast i32* %addr1.32 to i8* 86 %addr2.32 = alloca i32 87 %addr2 = bitcast i32* %addr2.32 to i8* 88 89; CHECK: add r0, sp, #{{[0-9]+}} 90; CHECK: blx 91 call void @take_ptr(i8* %addr1) 92 93; CHECK: mov r0, sp 94; CHECK-NOT: add r0 95; CHECK: blx 96 call void @take_ptr(i8* %addr2) 97 98 ret void 99} 100 101; Simple variable ending up at aligned offset from sp. 102define void @test_local_var_big_offset() { 103; CHECK-LABEL: test_local_var_big_offset: 104 %addr1.32 = alloca i32, i32 257 105 %addr1 = bitcast i32* %addr1.32 to i8* 106 %addr2.32 = alloca i32, i32 257 107 108; CHECK: add [[RTMP:r[0-9]+]], sp, #1020 109; CHECK: adds [[RTMP]], #8 110; CHECK: blx 111 call void @take_ptr(i8* %addr1) 112 113 ret void 114} 115 116; Max range addressable with tADDrSPi 117define void @test_local_var_offset_1020() { 118; CHECK-LABEL: test_local_var_offset_1020 119 %addr1 = alloca i8, i32 4 120 %addr2 = alloca i8, i32 1020 121 122; CHECK: add r0, sp, #1020 123; CHECK-NEXT: blx 124 call void @take_ptr(i8* %addr1) 125 126 ret void 127} 128 129; Max range addressable with tADDrSPi + tADDi8 130define void @test_local_var_offset_1275() { 131; CHECK-LABEL: test_local_var_offset_1275 132 %addr1 = alloca i8, i32 1 133 %addr2 = alloca i8, i32 1275 134 135; CHECK: add r0, sp, #1020 136; CHECK: adds r0, #255 137; CHECK-NEXT: blx 138 call void @take_ptr(i8* %addr1) 139 140 ret void 141} 142 143declare void @take_ptr(i8*) 144