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