llvm-project/llvm/test/CodeGen/AArch64/fast-isel-addressing-modes.ll
Sander de Smalen 61510b51c3 Revert "[AArch64] Enable subreg liveness tracking by default."
This reverts commit 9c319d5bb40785c969d2af76535ca62448dfafa7.

Some issues were discovered with the bootstrap builds, which
seem like they were caused by this commit. I'm reverting to investigate.
2024-12-12 17:22:15 +00:00

825 lines
20 KiB
LLVM

; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG
; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST
; Load / Store Base Register only
define zeroext i1 @load_breg_i1(ptr %a) {
; SDAG-LABEL: load_breg_i1:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldrb w0, [x0]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_i1:
; FAST: ; %bb.0:
; FAST-NEXT: ldrb w8, [x0]
; FAST-NEXT: and w8, w8, #0x1
; FAST-NEXT: and w0, w8, #0x1
; FAST-NEXT: ret
%1 = load i1, ptr %a
ret i1 %1
}
define zeroext i8 @load_breg_i8(ptr %a) {
; SDAG-LABEL: load_breg_i8:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldrb w0, [x0]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_i8:
; FAST: ; %bb.0:
; FAST-NEXT: ldrb w8, [x0]
; FAST-NEXT: uxtb w0, w8
; FAST-NEXT: ret
%1 = load i8, ptr %a
ret i8 %1
}
define zeroext i16 @load_breg_i16(ptr %a) {
; SDAG-LABEL: load_breg_i16:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldrh w0, [x0]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_i16:
; FAST: ; %bb.0:
; FAST-NEXT: ldrh w8, [x0]
; FAST-NEXT: uxth w0, w8
; FAST-NEXT: ret
%1 = load i16, ptr %a
ret i16 %1
}
define i32 @load_breg_i32(ptr %a) {
; CHECK-LABEL: load_breg_i32:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x0]
; CHECK-NEXT: ret
%1 = load i32, ptr %a
ret i32 %1
}
define i64 @load_breg_i64(ptr %a) {
; CHECK-LABEL: load_breg_i64:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x0]
; CHECK-NEXT: ret
%1 = load i64, ptr %a
ret i64 %1
}
define float @load_breg_f32(ptr %a) {
; CHECK-LABEL: load_breg_f32:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr s0, [x0]
; CHECK-NEXT: ret
%1 = load float, ptr %a
ret float %1
}
define double @load_breg_f64(ptr %a) {
; CHECK-LABEL: load_breg_f64:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr d0, [x0]
; CHECK-NEXT: ret
%1 = load double, ptr %a
ret double %1
}
define void @store_breg_i1(ptr %a) {
; CHECK-LABEL: store_breg_i1:
; CHECK: ; %bb.0:
; CHECK-NEXT: strb wzr, [x0]
; CHECK-NEXT: ret
store i1 0, ptr %a
ret void
}
define void @store_breg_i1_2(ptr %a) {
; SDAG-LABEL: store_breg_i1_2:
; SDAG: ; %bb.0:
; SDAG-NEXT: mov w8, #1 ; =0x1
; SDAG-NEXT: strb w8, [x0]
; SDAG-NEXT: ret
;
; FAST-LABEL: store_breg_i1_2:
; FAST: ; %bb.0:
; FAST-NEXT: mov w8, #1 ; =0x1
; FAST-NEXT: and w8, w8, #0x1
; FAST-NEXT: strb w8, [x0]
; FAST-NEXT: ret
store i1 true, ptr %a
ret void
}
define void @store_breg_i8(ptr %a) {
; CHECK-LABEL: store_breg_i8:
; CHECK: ; %bb.0:
; CHECK-NEXT: strb wzr, [x0]
; CHECK-NEXT: ret
store i8 0, ptr %a
ret void
}
define void @store_breg_i16(ptr %a) {
; CHECK-LABEL: store_breg_i16:
; CHECK: ; %bb.0:
; CHECK-NEXT: strh wzr, [x0]
; CHECK-NEXT: ret
store i16 0, ptr %a
ret void
}
define void @store_breg_i32(ptr %a) {
; CHECK-LABEL: store_breg_i32:
; CHECK: ; %bb.0:
; CHECK-NEXT: str wzr, [x0]
; CHECK-NEXT: ret
store i32 0, ptr %a
ret void
}
define void @store_breg_i64(ptr %a) {
; CHECK-LABEL: store_breg_i64:
; CHECK: ; %bb.0:
; CHECK-NEXT: str xzr, [x0]
; CHECK-NEXT: ret
store i64 0, ptr %a
ret void
}
define void @store_breg_f32(ptr %a) {
; CHECK-LABEL: store_breg_f32:
; CHECK: ; %bb.0:
; CHECK-NEXT: str wzr, [x0]
; CHECK-NEXT: ret
store float 0.0, ptr %a
ret void
}
define void @store_breg_f64(ptr %a) {
; CHECK-LABEL: store_breg_f64:
; CHECK: ; %bb.0:
; CHECK-NEXT: str xzr, [x0]
; CHECK-NEXT: ret
store double 0.0, ptr %a
ret void
}
; Load Immediate
define i32 @load_immoff_1() {
; SDAG-LABEL: load_immoff_1:
; SDAG: ; %bb.0:
; SDAG-NEXT: mov w8, #128 ; =0x80
; SDAG-NEXT: ldr w0, [x8]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_immoff_1:
; FAST: ; %bb.0:
; FAST-NEXT: mov x8, #128 ; =0x80
; FAST-NEXT: ldr w0, [x8]
; FAST-NEXT: ret
%1 = inttoptr i64 128 to ptr
%2 = load i32, ptr %1
ret i32 %2
}
; Load / Store Base Register + Immediate Offset
; Max supported negative offset
define i32 @load_breg_immoff_1(i64 %a) {
; CHECK-LABEL: load_breg_immoff_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldur w0, [x0, #-256]
; CHECK-NEXT: ret
%1 = add i64 %a, -256
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Min not-supported negative offset
define i32 @load_breg_immoff_2(i64 %a) {
; CHECK-LABEL: load_breg_immoff_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub x8, x0, #257
; CHECK-NEXT: ldr w0, [x8]
; CHECK-NEXT: ret
%1 = add i64 %a, -257
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Max supported unscaled offset
define i32 @load_breg_immoff_3(i64 %a) {
; CHECK-LABEL: load_breg_immoff_3:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldur w0, [x0, #255]
; CHECK-NEXT: ret
%1 = add i64 %a, 255
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Min un-supported unscaled offset
define i32 @load_breg_immoff_4(i64 %a) {
; CHECK-LABEL: load_breg_immoff_4:
; CHECK: ; %bb.0:
; CHECK-NEXT: add x8, x0, #257
; CHECK-NEXT: ldr w0, [x8]
; CHECK-NEXT: ret
%1 = add i64 %a, 257
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Max supported scaled offset
define i32 @load_breg_immoff_5(i64 %a) {
; CHECK-LABEL: load_breg_immoff_5:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x0, #16380]
; CHECK-NEXT: ret
%1 = add i64 %a, 16380
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Min un-supported scaled offset
define i32 @load_breg_immoff_6(i64 %a) {
; SDAG-LABEL: load_breg_immoff_6:
; SDAG: ; %bb.0:
; SDAG-NEXT: mov w8, #16384 ; =0x4000
; SDAG-NEXT: ldr w0, [x0, x8]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_immoff_6:
; FAST: ; %bb.0:
; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384
; FAST-NEXT: ldr w0, [x8]
; FAST-NEXT: ret
%1 = add i64 %a, 16384
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Max supported negative offset
define void @store_breg_immoff_1(i64 %a) {
; CHECK-LABEL: store_breg_immoff_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: stur wzr, [x0, #-256]
; CHECK-NEXT: ret
%1 = add i64 %a, -256
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
; Min not-supported negative offset
define void @store_breg_immoff_2(i64 %a) {
; CHECK-LABEL: store_breg_immoff_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub x8, x0, #257
; CHECK-NEXT: str wzr, [x8]
; CHECK-NEXT: ret
%1 = add i64 %a, -257
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
; Max supported unscaled offset
define void @store_breg_immoff_3(i64 %a) {
; CHECK-LABEL: store_breg_immoff_3:
; CHECK: ; %bb.0:
; CHECK-NEXT: stur wzr, [x0, #255]
; CHECK-NEXT: ret
%1 = add i64 %a, 255
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
; Min un-supported unscaled offset
define void @store_breg_immoff_4(i64 %a) {
; CHECK-LABEL: store_breg_immoff_4:
; CHECK: ; %bb.0:
; CHECK-NEXT: add x8, x0, #257
; CHECK-NEXT: str wzr, [x8]
; CHECK-NEXT: ret
%1 = add i64 %a, 257
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
; Max supported scaled offset
define void @store_breg_immoff_5(i64 %a) {
; CHECK-LABEL: store_breg_immoff_5:
; CHECK: ; %bb.0:
; CHECK-NEXT: str wzr, [x0, #16380]
; CHECK-NEXT: ret
%1 = add i64 %a, 16380
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
; Min un-supported scaled offset
define void @store_breg_immoff_6(i64 %a) {
; SDAG-LABEL: store_breg_immoff_6:
; SDAG: ; %bb.0:
; SDAG-NEXT: mov w8, #16384 ; =0x4000
; SDAG-NEXT: str wzr, [x0, x8]
; SDAG-NEXT: ret
;
; FAST-LABEL: store_breg_immoff_6:
; FAST: ; %bb.0:
; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384
; FAST-NEXT: str wzr, [x8]
; FAST-NEXT: ret
%1 = add i64 %a, 16384
%2 = inttoptr i64 %1 to ptr
store i32 0, ptr %2
ret void
}
define i64 @load_breg_immoff_7(i64 %a) {
; CHECK-LABEL: load_breg_immoff_7:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x0, #48]
; CHECK-NEXT: ret
%1 = add i64 %a, 48
%2 = inttoptr i64 %1 to ptr
%3 = load i64, ptr %2
ret i64 %3
}
; Flip add operands
define i64 @load_breg_immoff_8(i64 %a) {
; CHECK-LABEL: load_breg_immoff_8:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x0, #48]
; CHECK-NEXT: ret
%1 = add i64 48, %a
%2 = inttoptr i64 %1 to ptr
%3 = load i64, ptr %2
ret i64 %3
}
; Load Base Register + Register Offset
define i64 @load_breg_offreg_1(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x0, x1]
; CHECK-NEXT: ret
%1 = add i64 %a, %b
%2 = inttoptr i64 %1 to ptr
%3 = load i64, ptr %2
ret i64 %3
}
; Flip add operands
define i64 @load_breg_offreg_2(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_offreg_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x1, x0]
; CHECK-NEXT: ret
%1 = add i64 %b, %a
%2 = inttoptr i64 %1 to ptr
%3 = load i64, ptr %2
ret i64 %3
}
; Load Base Register + Register Offset + Immediate Offset
define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_offreg_immoff_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: add x8, x0, x1
; CHECK-NEXT: ldr x0, [x8, #48]
; CHECK-NEXT: ret
%1 = add i64 %a, %b
%2 = add i64 %1, 48
%3 = inttoptr i64 %2 to ptr
%4 = load i64, ptr %3
ret i64 %4
}
define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) {
; SDAG-LABEL: load_breg_offreg_immoff_2:
; SDAG: ; %bb.0:
; SDAG-NEXT: mov w8, #61440 ; =0xf000
; SDAG-NEXT: add x9, x0, x1
; SDAG-NEXT: ldr x0, [x9, x8]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_offreg_immoff_2:
; FAST: ; %bb.0:
; FAST-NEXT: add x8, x0, #15, lsl #12 ; =61440
; FAST-NEXT: ldr x0, [x8, x1]
; FAST-NEXT: ret
%1 = add i64 %a, %b
%2 = add i64 %1, 61440
%3 = inttoptr i64 %2 to ptr
%4 = load i64, ptr %3
ret i64 %4
}
; Load Scaled Register Offset
define i32 @load_shift_offreg_1(i64 %a) {
; CHECK-LABEL: load_shift_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: lsl x8, x0, #2
; CHECK-NEXT: ldr w0, [x8]
; CHECK-NEXT: ret
%1 = shl i64 %a, 2
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
define i32 @load_mul_offreg_1(i64 %a) {
; CHECK-LABEL: load_mul_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: lsl x8, x0, #2
; CHECK-NEXT: ldr w0, [x8]
; CHECK-NEXT: ret
%1 = mul i64 %a, 4
%2 = inttoptr i64 %1 to ptr
%3 = load i32, ptr %2
ret i32 %3
}
; Load Base Register + Scaled Register Offset
define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_shift_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
; CHECK-NEXT: ret
%1 = shl i64 %a, 2
%2 = add i64 %1, %b
%3 = inttoptr i64 %2 to ptr
%4 = load i32, ptr %3
ret i32 %4
}
define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_shift_offreg_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
; CHECK-NEXT: ret
%1 = shl i64 %a, 2
%2 = add i64 %b, %1
%3 = inttoptr i64 %2 to ptr
%4 = load i32, ptr %3
ret i32 %4
}
define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) {
; SDAG-LABEL: load_breg_shift_offreg_3:
; SDAG: ; %bb.0:
; SDAG-NEXT: lsl x8, x0, #2
; SDAG-NEXT: ldr w0, [x8, x1, lsl #2]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_shift_offreg_3:
; FAST: ; %bb.0:
; FAST-NEXT: lsl x8, x1, #2
; FAST-NEXT: ldr w0, [x8, x0, lsl #2]
; FAST-NEXT: ret
%1 = shl i64 %a, 2
%2 = shl i64 %b, 2
%3 = add i64 %1, %2
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) {
; SDAG-LABEL: load_breg_shift_offreg_4:
; SDAG: ; %bb.0:
; SDAG-NEXT: lsl x8, x1, #2
; SDAG-NEXT: ldr w0, [x8, x0, lsl #2]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_shift_offreg_4:
; FAST: ; %bb.0:
; FAST-NEXT: lsl x8, x0, #2
; FAST-NEXT: ldr w0, [x8, x1, lsl #2]
; FAST-NEXT: ret
%1 = shl i64 %a, 2
%2 = shl i64 %b, 2
%3 = add i64 %2, %1
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_shift_offreg_5:
; CHECK: ; %bb.0:
; CHECK-NEXT: lsl x8, x1, #3
; CHECK-NEXT: ldr w0, [x8, x0, lsl #2]
; CHECK-NEXT: ret
%1 = shl i64 %a, 2
%2 = shl i64 %b, 3
%3 = add i64 %1, %2
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_mul_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, x0, lsl #2]
; CHECK-NEXT: ret
%1 = mul i64 %a, 4
%2 = add i64 %1, %b
%3 = inttoptr i64 %2 to ptr
%4 = load i32, ptr %3
ret i32 %4
}
define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) {
; SDAG-LABEL: load_breg_and_offreg_1:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldrb w0, [x1, w0, uxtw]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_and_offreg_1:
; FAST: ; %bb.0:
; FAST-NEXT: ldrb w8, [x1, w0, uxtw]
; FAST-NEXT: uxtb w0, w8
; FAST-NEXT: ret
%1 = and i64 %a, 4294967295
%2 = add i64 %1, %b
%3 = inttoptr i64 %2 to ptr
%4 = load i8, ptr %3
ret i8 %4
}
define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) {
; SDAG-LABEL: load_breg_and_offreg_2:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldrh w0, [x1, w0, uxtw #1]
; SDAG-NEXT: ret
;
; FAST-LABEL: load_breg_and_offreg_2:
; FAST: ; %bb.0:
; FAST-NEXT: ldrh w8, [x1, w0, uxtw #1]
; FAST-NEXT: uxth w0, w8
; FAST-NEXT: ret
%1 = and i64 %a, 4294967295
%2 = shl i64 %1, 1
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i16, ptr %4
ret i16 %5
}
define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_and_offreg_3:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
; CHECK-NEXT: ret
%1 = and i64 %a, 4294967295
%2 = shl i64 %1, 2
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) {
; CHECK-LABEL: load_breg_and_offreg_4:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr x0, [x1, w0, uxtw #3]
; CHECK-NEXT: ret
%1 = and i64 %a, 4294967295
%2 = shl i64 %1, 3
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i64, ptr %4
ret i64 %5
}
; Not all 'and' instructions have immediates.
define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: load_breg_and_offreg_5:
; CHECK: ; %bb.0:
; CHECK-NEXT: and x8, x0, x2
; CHECK-NEXT: ldr x0, [x8, x1]
; CHECK-NEXT: ret
%1 = and i64 %a, %c
%2 = add i64 %1, %b
%3 = inttoptr i64 %2 to ptr
%4 = load i64, ptr %3
ret i64 %4
}
define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) {
; CHECK-LABEL: load_breg_and_offreg_6:
; CHECK: ; %bb.0:
; CHECK-NEXT: and x8, x0, x2
; CHECK-NEXT: ldr x0, [x1, x8, lsl #3]
; CHECK-NEXT: ret
%1 = and i64 %a, %c
%2 = shl i64 %1, 3
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i64, ptr %4
ret i64 %5
}
; Load Base Register + Scaled Register Offset + Sign/Zero extension
define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_zext_shift_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
; CHECK-NEXT: ret
%1 = zext i32 %a to i64
%2 = shl i64 %1, 2
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_zext_shift_offreg_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
; CHECK-NEXT: ret
%1 = zext i32 %a to i64
%2 = shl i64 %1, 2
%3 = add i64 %b, %2
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_zext_mul_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2]
; CHECK-NEXT: ret
%1 = zext i32 %a to i64
%2 = mul i64 %1, 4
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_shift_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
; CHECK-NEXT: ret
%1 = sext i32 %a to i64
%2 = shl i64 %1, 2
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_shift_offreg_2:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
; CHECK-NEXT: ret
%1 = sext i32 %a to i64
%2 = shl i64 %1, 2
%3 = add i64 %b, %2
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
; Make sure that we don't drop the first 'add' instruction.
define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_shift_offreg_3:
; CHECK: ; %bb.0:
; CHECK-NEXT: add w8, w0, #4
; CHECK-NEXT: ldr w0, [x1, w8, sxtw #2]
; CHECK-NEXT: ret
%1 = add i32 %a, 4
%2 = sext i32 %1 to i64
%3 = shl i64 %2, 2
%4 = add i64 %b, %3
%5 = inttoptr i64 %4 to ptr
%6 = load i32, ptr %5
ret i32 %6
}
define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_mul_offreg_1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2]
; CHECK-NEXT: ret
%1 = sext i32 %a to i64
%2 = mul i64 %1, 4
%3 = add i64 %2, %b
%4 = inttoptr i64 %3 to ptr
%5 = load i32, ptr %4
ret i32 %5
}
; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension
define i64 @load_sext_shift_offreg_imm1(i32 %a) {
; CHECK-LABEL: load_sext_shift_offreg_imm1:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $w0 killed $w0 def $x0
; CHECK-NEXT: sbfiz x8, x0, #3, #32
; CHECK-NEXT: ldr x0, [x8, #8]
; CHECK-NEXT: ret
%1 = sext i32 %a to i64
%2 = shl i64 %1, 3
%3 = add i64 %2, 8
%4 = inttoptr i64 %3 to ptr
%5 = load i64, ptr %4
ret i64 %5
}
; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension
define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) {
; CHECK-LABEL: load_breg_sext_shift_offreg_imm1:
; CHECK: ; %bb.0:
; CHECK-NEXT: add x8, x1, w0, sxtw #3
; CHECK-NEXT: ldr x0, [x8, #8]
; CHECK-NEXT: ret
%1 = sext i32 %a to i64
%2 = shl i64 %1, 3
%3 = add i64 %b, %2
%4 = add i64 %3, 8
%5 = inttoptr i64 %4 to ptr
%6 = load i64, ptr %5
ret i64 %6
}
; Test that the kill flag is not set - the machine instruction verifier does that for us.
define i64 @kill_reg(i64 %a) {
; SDAG-LABEL: kill_reg:
; SDAG: ; %bb.0:
; SDAG-NEXT: ldr x8, [x0, #88]!
; SDAG-NEXT: add x0, x0, x8
; SDAG-NEXT: ret
;
; FAST-LABEL: kill_reg:
; FAST: ; %bb.0:
; FAST-NEXT: sub x8, x0, #8
; FAST-NEXT: ldr x9, [x0, #88]
; FAST-NEXT: add x8, x8, #96
; FAST-NEXT: add x0, x8, x9
; FAST-NEXT: ret
%1 = sub i64 %a, 8
%2 = add i64 %1, 96
%3 = inttoptr i64 %2 to ptr
%4 = load i64, ptr %3
%5 = add i64 %2, %4
ret i64 %5
}
define void @store_fi(i64 %i) {
; CHECK-LABEL: store_fi:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub sp, sp, #32
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: mov x8, sp
; CHECK-NEXT: mov w9, #47 ; =0x2f
; CHECK-NEXT: str w9, [x8, x0, lsl #2]
; CHECK-NEXT: add sp, sp, #32
; CHECK-NEXT: ret
%1 = alloca [8 x i32]
%2 = ptrtoint ptr %1 to i64
%3 = mul i64 %i, 4
%4 = add i64 %2, %3
%5 = inttoptr i64 %4 to ptr
store i32 47, ptr %5, align 4
ret void
}
define i32 @load_fi(i64 %i) {
; CHECK-LABEL: load_fi:
; CHECK: ; %bb.0:
; CHECK-NEXT: sub sp, sp, #32
; CHECK-NEXT: .cfi_def_cfa_offset 32
; CHECK-NEXT: mov x8, sp
; CHECK-NEXT: ldr w0, [x8, x0, lsl #2]
; CHECK-NEXT: add sp, sp, #32
; CHECK-NEXT: ret
%1 = alloca [8 x i32]
%2 = ptrtoint ptr %1 to i64
%3 = mul i64 %i, 4
%4 = add i64 %2, %3
%5 = inttoptr i64 %4 to ptr
%6 = load i32, ptr %5, align 4
ret i32 %6
}