1 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios | FileCheck %s --check-prefix=ARM 2 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi | FileCheck %s --check-prefix=ARM 3 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios | FileCheck %s --check-prefix=THUMB 4 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=ARM-LONG 5 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=armv7-linux-gnueabi -arm-long-calls | FileCheck %s --check-prefix=ARM-LONG 6 ; RUN: llc < %s -O0 -fast-isel-abort -relocation-model=dynamic-no-pic -mtriple=thumbv7-apple-ios -arm-long-calls | FileCheck %s --check-prefix=THUMB-LONG 7 8 ; Note that some of these tests assume that relocations are either 9 ; movw/movt or constant pool loads. Different platforms will select 10 ; different approaches. 11 12 @message1 = global [60 x i8] c"The LLVM Compiler Infrastructure\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00", align 1 13 @temp = common global [60 x i8] zeroinitializer, align 1 14 15 define void @t1() nounwind ssp { 16 ; ARM: t1 17 ; ARM: {{(movw r0, :lower16:_?message1)|(ldr r0, .LCPI)}} 18 ; ARM: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}} 19 ; ARM: add r0, r0, #5 20 ; ARM: movw r1, #64 21 ; ARM: movw r2, #10 22 ; ARM: and r1, r1, #255 23 ; ARM: bl {{_?}}memset 24 ; ARM-LONG: t1 25 ; ARM-LONG: {{(movw r3, :lower16:L_memset\$non_lazy_ptr)|(ldr r3, .LCPI)}} 26 ; ARM-LONG: {{(movt r3, :upper16:L_memset\$non_lazy_ptr)?}} 27 ; ARM-LONG: ldr r3, [r3] 28 ; ARM-LONG: blx r3 29 ; THUMB: t1 30 ; THUMB: {{(movw r0, :lower16:_?message1)|(ldr.n r0, .LCPI)}} 31 ; THUMB: {{(movt r0, :upper16:_?message1)|(ldr r0, \[r0\])}} 32 ; THUMB: adds r0, #5 33 ; THUMB: movs r1, #64 34 ; THUMB: movt r1, #0 35 ; THUMB: movs r2, #10 36 ; THUMB: movt r2, #0 37 ; THUMB: and r1, r1, #255 38 ; THUMB: bl {{_?}}memset 39 ; THUMB-LONG: t1 40 ; THUMB-LONG: movw r3, :lower16:L_memset$non_lazy_ptr 41 ; THUMB-LONG: movt r3, :upper16:L_memset$non_lazy_ptr 42 ; THUMB-LONG: ldr r3, [r3] 43 ; THUMB-LONG: blx r3 44 call void @llvm.memset.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @message1, i32 0, i32 5), i8 64, i32 10, i32 4, i1 false) 45 ret void 46 } 47 48 declare void @llvm.memset.p0i8.i32(i8* nocapture, i8, i32, i32, i1) nounwind 49 50 define void @t2() nounwind ssp { 51 ; ARM: t2 52 ; ARM: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}} 53 ; ARM: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 54 ; ARM: ldr r0, [r0] 55 ; ARM: add r1, r0, #4 56 ; ARM: add r0, r0, #16 57 ; ARM: movw r2, #17 58 ; ARM: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill 59 ; ARM: mov r0, r1 60 ; ARM: ldr r1, [sp[[SLOT]]] @ 4-byte Reload 61 ; ARM: bl {{_?}}memcpy 62 ; ARM-LONG: t2 63 ; ARM-LONG: {{(movw r3, :lower16:L_memcpy\$non_lazy_ptr)|(ldr r3, .LCPI)}} 64 ; ARM-LONG: {{(movt r3, :upper16:L_memcpy\$non_lazy_ptr)?}} 65 ; ARM-LONG: ldr r3, [r3] 66 ; ARM-LONG: blx r3 67 ; THUMB: t2 68 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}} 69 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 70 ; THUMB: ldr r0, [r0] 71 ; THUMB: adds r1, r0, #4 72 ; THUMB: adds r0, #16 73 ; THUMB: movs r2, #17 74 ; THUMB: movt r2, #0 75 ; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill 76 ; THUMB: mov r0, r1 77 ; THUMB: ldr r1, [sp[[SLOT]]] @ 4-byte Reload 78 ; THUMB: bl {{_?}}memcpy 79 ; THUMB-LONG: t2 80 ; THUMB-LONG: movw r3, :lower16:L_memcpy$non_lazy_ptr 81 ; THUMB-LONG: movt r3, :upper16:L_memcpy$non_lazy_ptr 82 ; THUMB-LONG: ldr r3, [r3] 83 ; THUMB-LONG: blx r3 84 call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 17, i32 4, i1 false) 85 ret void 86 } 87 88 declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind 89 90 define void @t3() nounwind ssp { 91 ; ARM: t3 92 ; ARM: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}} 93 ; ARM: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 94 ; ARM: ldr r0, [r0] 95 ; ARM: add r1, r0, #4 96 ; ARM: add r0, r0, #16 97 ; ARM: movw r2, #10 98 ; ARM: mov r0, r1 99 ; ARM: bl {{_?}}memmove 100 ; ARM-LONG: t3 101 ; ARM-LONG: {{(movw r3, :lower16:L_memmove\$non_lazy_ptr)|(ldr r3, .LCPI)}} 102 ; ARM-LONG: {{(movt r3, :upper16:L_memmove\$non_lazy_ptr)?}} 103 ; ARM-LONG: ldr r3, [r3] 104 ; ARM-LONG: blx r3 105 ; THUMB: t3 106 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}} 107 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 108 ; THUMB: ldr r0, [r0] 109 ; THUMB: adds r1, r0, #4 110 ; THUMB: adds r0, #16 111 ; THUMB: movs r2, #10 112 ; THUMB: movt r2, #0 113 ; THUMB: str r0, [sp[[SLOT:[, #0-9]*]]] @ 4-byte Spill 114 ; THUMB: mov r0, r1 115 ; THUMB: ldr r1, [sp[[SLOT]]] @ 4-byte Reload 116 ; THUMB: bl {{_?}}memmove 117 ; THUMB-LONG: t3 118 ; THUMB-LONG: movw r3, :lower16:L_memmove$non_lazy_ptr 119 ; THUMB-LONG: movt r3, :upper16:L_memmove$non_lazy_ptr 120 ; THUMB-LONG: ldr r3, [r3] 121 ; THUMB-LONG: blx r3 122 call void @llvm.memmove.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 10, i32 1, i1 false) 123 ret void 124 } 125 126 define void @t4() nounwind ssp { 127 ; ARM: t4 128 ; ARM: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}} 129 ; ARM: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 130 ; ARM: ldr r0, [r0] 131 ; ARM: ldr r1, [r0, #16] 132 ; ARM: str r1, [r0, #4] 133 ; ARM: ldr r1, [r0, #20] 134 ; ARM: str r1, [r0, #8] 135 ; ARM: ldrh r1, [r0, #24] 136 ; ARM: strh r1, [r0, #12] 137 ; ARM: bx lr 138 ; THUMB: t4 139 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}} 140 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 141 ; THUMB: ldr r0, [r0] 142 ; THUMB: ldr r1, [r0, #16] 143 ; THUMB: str r1, [r0, #4] 144 ; THUMB: ldr r1, [r0, #20] 145 ; THUMB: str r1, [r0, #8] 146 ; THUMB: ldrh r1, [r0, #24] 147 ; THUMB: strh r1, [r0, #12] 148 ; THUMB: bx lr 149 call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 10, i32 4, i1 false) 150 ret void 151 } 152 153 declare void @llvm.memmove.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind 154 155 define void @t5() nounwind ssp { 156 ; ARM: t5 157 ; ARM: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}} 158 ; ARM: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 159 ; ARM: ldr r0, [r0] 160 ; ARM: ldrh r1, [r0, #16] 161 ; ARM: strh r1, [r0, #4] 162 ; ARM: ldrh r1, [r0, #18] 163 ; ARM: strh r1, [r0, #6] 164 ; ARM: ldrh r1, [r0, #20] 165 ; ARM: strh r1, [r0, #8] 166 ; ARM: ldrh r1, [r0, #22] 167 ; ARM: strh r1, [r0, #10] 168 ; ARM: ldrh r1, [r0, #24] 169 ; ARM: strh r1, [r0, #12] 170 ; ARM: bx lr 171 ; THUMB: t5 172 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}} 173 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 174 ; THUMB: ldr r0, [r0] 175 ; THUMB: ldrh r1, [r0, #16] 176 ; THUMB: strh r1, [r0, #4] 177 ; THUMB: ldrh r1, [r0, #18] 178 ; THUMB: strh r1, [r0, #6] 179 ; THUMB: ldrh r1, [r0, #20] 180 ; THUMB: strh r1, [r0, #8] 181 ; THUMB: ldrh r1, [r0, #22] 182 ; THUMB: strh r1, [r0, #10] 183 ; THUMB: ldrh r1, [r0, #24] 184 ; THUMB: strh r1, [r0, #12] 185 ; THUMB: bx lr 186 call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 10, i32 2, i1 false) 187 ret void 188 } 189 190 define void @t6() nounwind ssp { 191 ; ARM: t6 192 ; ARM: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr r0, .LCPI)}} 193 ; ARM: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 194 ; ARM: ldr r0, [r0] 195 ; ARM: ldrb r1, [r0, #16] 196 ; ARM: strb r1, [r0, #4] 197 ; ARM: ldrb r1, [r0, #17] 198 ; ARM: strb r1, [r0, #5] 199 ; ARM: ldrb r1, [r0, #18] 200 ; ARM: strb r1, [r0, #6] 201 ; ARM: ldrb r1, [r0, #19] 202 ; ARM: strb r1, [r0, #7] 203 ; ARM: ldrb r1, [r0, #20] 204 ; ARM: strb r1, [r0, #8] 205 ; ARM: ldrb r1, [r0, #21] 206 ; ARM: strb r1, [r0, #9] 207 ; ARM: ldrb r1, [r0, #22] 208 ; ARM: strb r1, [r0, #10] 209 ; ARM: ldrb r1, [r0, #23] 210 ; ARM: strb r1, [r0, #11] 211 ; ARM: ldrb r1, [r0, #24] 212 ; ARM: strb r1, [r0, #12] 213 ; ARM: ldrb r1, [r0, #25] 214 ; ARM: strb r1, [r0, #13] 215 ; ARM: bx lr 216 ; THUMB: t6 217 ; THUMB: {{(movw r0, :lower16:L_temp\$non_lazy_ptr)|(ldr.n r0, .LCPI)}} 218 ; THUMB: {{(movt r0, :upper16:L_temp\$non_lazy_ptr)?}} 219 ; THUMB: ldr r0, [r0] 220 ; THUMB: ldrb r1, [r0, #16] 221 ; THUMB: strb r1, [r0, #4] 222 ; THUMB: ldrb r1, [r0, #17] 223 ; THUMB: strb r1, [r0, #5] 224 ; THUMB: ldrb r1, [r0, #18] 225 ; THUMB: strb r1, [r0, #6] 226 ; THUMB: ldrb r1, [r0, #19] 227 ; THUMB: strb r1, [r0, #7] 228 ; THUMB: ldrb r1, [r0, #20] 229 ; THUMB: strb r1, [r0, #8] 230 ; THUMB: ldrb r1, [r0, #21] 231 ; THUMB: strb r1, [r0, #9] 232 ; THUMB: ldrb r1, [r0, #22] 233 ; THUMB: strb r1, [r0, #10] 234 ; THUMB: ldrb r1, [r0, #23] 235 ; THUMB: strb r1, [r0, #11] 236 ; THUMB: ldrb r1, [r0, #24] 237 ; THUMB: strb r1, [r0, #12] 238 ; THUMB: ldrb r1, [r0, #25] 239 ; THUMB: strb r1, [r0, #13] 240 ; THUMB: bx lr 241 call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 10, i32 1, i1 false) 242 ret void 243 } 244 245 ; rdar://13202135 246 define void @t7() nounwind ssp { 247 ; Just make sure this doesn't assert when we have an odd length and an alignment of 2. 248 call void @llvm.memcpy.p0i8.p0i8.i32(i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 4), i8* getelementptr inbounds ([60 x i8]* @temp, i32 0, i32 16), i32 3, i32 2, i1 false) 249 ret void 250 } 251 252 define i32 @t8(i32 %x) nounwind { 253 entry: 254 ; ARM: t8 255 ; ARM-NOT: FastISel missed call: %expval = call i32 @llvm.expect.i32(i32 %x, i32 1) 256 ; THUMB: t8 257 ; THUMB-NOT: FastISel missed call: %expval = call i32 @llvm.expect.i32(i32 %x, i32 1) 258 %expval = call i32 @llvm.expect.i32(i32 %x, i32 1) 259 ret i32 %expval 260 } 261 262 declare i32 @llvm.expect.i32(i32, i32) nounwind readnone 263