142 lines · plain
1; RUN: llc -mtriple=thumbv8m.base-eabi -mattr=+execute-only %s -o - | FileCheck --check-prefixes=CHECK,CHECK-MOVW %s2; RUN: llc -mtriple=thumbv6m-eabi -mattr=+execute-only %s -o - | FileCheck --check-prefixes=CHECK,CHECK-NOMOVW %s3 4; Largest offset that fits into sp-relative ldr5; CHECK-LABEL: ldr_range_end:6; CHECK: ldr {{r[0-9]+}}, [sp, #1020]7define i32 @ldr_range_end() {8entry:9 %var = alloca i32, align 410 %arr = alloca [1020 x i8], align 411 %0 = load i32, ptr %var, align 412 ret i32 %013}14 15; Smallest offset that fits into add+ldr16; CHECK-LABEL: add_ldr_range_start:17; CHECK: add [[REG:r[0-9]+]], sp, #90018; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]19define i32 @add_ldr_range_start() {20entry:21 %var = alloca i32, align 422 %arr = alloca [1024 x i8], align 423 %0 = load i32, ptr %var, align 424 ret i32 %025}26 27; Largest offset that fits into add+ldr28; CHECK-LABEL: add_ldr_range_end:29; CHECK: add [[REG:r[0-9]+]], sp, #102030; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]31define i32 @add_ldr_range_end() {32entry:33 %var = alloca i32, align 434 %arr = alloca [1144 x i8], align 435 %0 = load i32, ptr %var, align 436 ret i32 %037}38 39; Smallest offset where we start using mov32. If we don't have movw then using40; an ldr offset means we save an add.41; CHECK-LABEL: mov32_range_start:42; CHECK-MOVW: movw [[REG:r[0-9]+]], #114843; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #444; CHECK-NOMOVW-NEXT: lsls [[REG]], [[REG]], #845; CHECK-NEXT: add [[REG]], sp46; CHECK-MOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]]]47; CHECK-NOMOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]48define i32 @mov32_range_start() {49entry:50 %var = alloca i32, align 451 %arr = alloca [1148 x i8], align 452 %0 = load i32, ptr %var, align 453 ret i32 %054}55 56; Here using an ldr offset doesn't save an add so we shouldn't do it.57; CHECK-LABEL: mov32_range_next:58; CHECK-MOVW: movw [[REG:r[0-9]+]], #115259; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #460; CHECK-NOMOVW-NEXT: lsls [[REG]], [[REG]], #861; CHECK-NOMOVW-NEXT: adds [[REG]], #12862; CHECK-NEXT: add [[REG]], sp63; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]]]64define i32 @mov32_range_next() {65entry:66 %var = alloca i32, align 467 %arr = alloca [1152 x i8], align 468 %0 = load i32, ptr %var, align 469 ret i32 %070}71 72; Smallest offset where using an ldr offset prevents needing a movt or lsl+add73; CHECK-LABEL: can_clear_top_byte_start:74; CHECK: add sp, {{r[0-9]+}}75; CHECK-MOVW: movw [[REG:r[0-9]+]], #6541276; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #25577; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #878; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #13279; CHECK-NEXT: add [[REG]], sp80; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]81define i32 @can_clear_top_byte_start() {82entry:83 %var = alloca i32, align 484 %arr = alloca [65536 x i8], align 485 %0 = load i32, ptr %var, align 486 ret i32 %087}88 89; Largest offset where using an ldr offset prevents needing a movt or lsl+add90; CHECK-LABEL: can_clear_top_byte_end:91; CHECK: add sp, {{r[0-9]+}}92; CHECK-MOVW: movw [[REG:r[0-9]+]], #6553293; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #25594; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #895; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #25296; CHECK-NEXT: add [[REG]], sp97; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]98define i32 @can_clear_top_byte_end() {99entry:100 %var = alloca i32, align 4101 %arr = alloca [65656 x i8], align 4102 %0 = load i32, ptr %var, align 4103 ret i32 %0104}105 106; Smallest offset where using an ldr offset doesn't clear the top byte, though107; we can use an ldr offset if not using movt to save an add of the low byte.108; CHECK-LABEL: cant_clear_top_byte_start:109; CHECK: add sp, {{r[0-9]+}}110; CHECK-MOVW: movw [[REG:r[0-9]+]], #124111; CHECK-MOVW-NEXT: movt [[REG:r[0-9]+]], #1112; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #1113; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #16114; CHECK-NEXT: add [[REG]], sp115; CHECK-MOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]]]116; CHECK-NOMOVW-NEXT: ldr {{r[0-9]+}}, [[[REG]], #124]117define i32 @cant_clear_top_byte_start() {118entry:119 %var = alloca i32, align 4120 %arr = alloca [65660 x i8], align 4121 %0 = load i32, ptr %var, align 4122 ret i32 %0123}124 125; An ldr offset doesn't help for anything, so we shouldn't do it.126; CHECK-LABEL: cant_clear_top_byte_next:127; CHECK: add sp, {{r[0-9]+}}128; CHECK-MOVW: movw [[REG:r[0-9]+]], #128129; CHECK-MOVW: movt [[REG:r[0-9]+]], #1130; CHECK-NOMOVW: movs [[REG:r[0-9]+]], #1131; CHECK-NOMOVW-NEXT: lsls [[REG:r[0-9]+]], [[REG:r[0-9]+]], #16132; CHECK-NOMOVW-NEXT: adds [[REG:r[0-9]+]], #128133; CHECK-NEXT: add [[REG]], sp134; CHECK-NEXT: ldr {{r[0-9]+}}, [[[REG]]]135define i32 @cant_clear_top_byte_next() {136entry:137 %var = alloca i32, align 4138 %arr = alloca [65664 x i8], align 4139 %0 = load i32, ptr %var, align 4140 ret i32 %0141}142