
If parts of a physical register for a given liverange, as assigned by the register allocator, can be used to store other values not represented by this liverange, then `LiveIntervals::addKillFlags` normally avoids adding a kill flag on the use of this register when the value's liverange ends. However, if all the other regunits are artificial, then we can still safely add the kill flag, since those parts of the register can never be accessed independently.
542 lines
15 KiB
LLVM
542 lines
15 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
|
; RUN: llc -aarch64-enable-subreg-liveness-tracking -mtriple=arm64-eabi < %s | FileCheck %s
|
|
; rdar://10232252
|
|
|
|
@object = external hidden global i64, section "__DATA, __objc_ivar", align 8
|
|
|
|
; base + offset (imm9)
|
|
define void @t1(ptr %object) {
|
|
; CHECK-LABEL: t1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ldr xzr, [x0, #8]
|
|
; CHECK-NEXT: ret
|
|
%incdec.ptr = getelementptr inbounds i64, ptr %object, i64 1
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; base + offset (> imm9)
|
|
define void @t2(ptr %object) {
|
|
; CHECK-LABEL: t2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub x8, x0, #264
|
|
; CHECK-NEXT: ldr xzr, [x8]
|
|
; CHECK-NEXT: ret
|
|
%incdec.ptr = getelementptr inbounds i64, ptr %object, i64 -33
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; base + unsigned offset (> imm9 and <= imm12 * size of type in bytes)
|
|
define void @t3(ptr %object) {
|
|
; CHECK-LABEL: t3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ldr xzr, [x0, #32760]
|
|
; CHECK-NEXT: ret
|
|
%incdec.ptr = getelementptr inbounds i64, ptr %object, i64 4095
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; base + unsigned offset (> imm12 * size of type in bytes)
|
|
define void @t4(ptr %object) {
|
|
; CHECK-LABEL: t4:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #32768 // =0x8000
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%incdec.ptr = getelementptr inbounds i64, ptr %object, i64 4096
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; base + reg
|
|
define void @t5(i64 %a) {
|
|
; CHECK-LABEL: t5:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: adrp x8, object
|
|
; CHECK-NEXT: add x8, x8, :lo12:object
|
|
; CHECK-NEXT: ldr xzr, [x8, x0, lsl #3]
|
|
; CHECK-NEXT: ret
|
|
%incdec.ptr = getelementptr inbounds i64, ptr @object, i64 %a
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; base + reg + imm
|
|
define void @t6(i64 %a, ptr %object) {
|
|
; CHECK-LABEL: t6:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x1, x0, lsl #3
|
|
; CHECK-NEXT: mov w9, #32768 // =0x8000
|
|
; CHECK-NEXT: ldr xzr, [x8, x9]
|
|
; CHECK-NEXT: ret
|
|
%tmp1 = getelementptr inbounds i64, ptr %object, i64 %a
|
|
%incdec.ptr = getelementptr inbounds i64, ptr %tmp1, i64 4096
|
|
%tmp = load volatile i64, ptr %incdec.ptr, align 8
|
|
ret void
|
|
}
|
|
|
|
; Test base + wide immediate
|
|
define void @t7(i64 %a) {
|
|
; CHECK-LABEL: t7:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #65535 // =0xffff
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 65535 ;0xffff
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t8(i64 %a) {
|
|
; CHECK-LABEL: t8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #-4662 // =0xffffffffffffedca
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = sub i64 %a, 4662 ;-4662 is 0xffffffffffffedca
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t9(i64 %a) {
|
|
; CHECK-LABEL: t9:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #-305463297 // =0xffffffffedcaffff
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 -305463297, %a ;-305463297 is 0xffffffffedcaffff
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t10(i64 %a) {
|
|
; CHECK-LABEL: t10:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov x8, #81909218222800896 // =0x123000000000000
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 81909218222800896 ;0x123000000000000
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t11(i64 %a) {
|
|
; CHECK-LABEL: t11:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #17767 // =0x4567
|
|
; CHECK-NEXT: movk w8, #291, lsl #16
|
|
; CHECK-NEXT: ldr xzr, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 19088743 ;0x1234567
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
; Test some boundaries that should not use movz/movn/orr
|
|
define void @t12(i64 %a) {
|
|
; CHECK-LABEL: t12:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #4095
|
|
; CHECK-NEXT: ldr xzr, [x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 4095 ;0xfff
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t13(i64 %a) {
|
|
; CHECK-LABEL: t13:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub x8, x0, #4095
|
|
; CHECK-NEXT: ldr xzr, [x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, -4095 ;-0xfff
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t14(i64 %a) {
|
|
; CHECK-LABEL: t14:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #291, lsl #12 // =1191936
|
|
; CHECK-NEXT: ldr xzr, [x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 1191936 ;0x123000
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t15(i64 %a) {
|
|
; CHECK-LABEL: t15:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: sub x8, x0, #291, lsl #12 // =1191936
|
|
; CHECK-NEXT: ldr xzr, [x8]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, -1191936 ;0xFFFFFFFFFFEDD000
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t16(i64 %a) {
|
|
; CHECK-LABEL: t16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ldr xzr, [x0, #28672]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, 28672 ;0x7000
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
define void @t17(i64 %a) {
|
|
; CHECK-LABEL: t17:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: ldur xzr, [x0, #-256]
|
|
; CHECK-NEXT: ret
|
|
%1 = add i64 %a, -256 ;-0x100
|
|
%2 = inttoptr i64 %1 to ptr
|
|
%3 = load volatile i64, ptr %2, align 8
|
|
ret void
|
|
}
|
|
|
|
; LDRBBroX
|
|
define i8 @LdOffset_i8(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrb w0, [x8, #3704]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
ret i8 %val
|
|
}
|
|
|
|
; LDRBBroX
|
|
define i32 @LdOffset_i8_zext32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_zext32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrb w0, [x8, #3704]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
%conv = zext i8 %val to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; LDRSBWroX
|
|
define i32 @LdOffset_i8_sext32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_sext32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrsb w0, [x8, #3704]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
%conv = sext i8 %val to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; LDRBBroX
|
|
define i64 @LdOffset_i8_zext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_zext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrb w0, [x8, #3704]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
%conv = zext i8 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRSBXroX
|
|
define i64 @LdOffset_i8_sext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_sext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrsb x0, [x8, #3704]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
%conv = sext i8 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRHHroX
|
|
define i16 @LdOffset_i16(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrh w0, [x8, #7408]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
ret i16 %val
|
|
}
|
|
|
|
; LDRHHroX
|
|
define i32 @LdOffset_i16_zext32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16_zext32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrh w0, [x8, #7408]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = zext i16 %val to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; LDRSHWroX
|
|
define i32 @LdOffset_i16_sext32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16_sext32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrsh w0, [x8, #7408]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = sext i16 %val to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; LDRHHroX
|
|
define i64 @LdOffset_i16_zext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16_zext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrh w0, [x8, #7408]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = zext i16 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRSHXroX
|
|
define i64 @LdOffset_i16_sext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16_sext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrsh x0, [x8, #7408]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = sext i16 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRWroX
|
|
define i32 @LdOffset_i32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152
|
|
; CHECK-NEXT: ldr w0, [x8, #14816]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992
|
|
%val = load i32, ptr %arrayidx, align 4
|
|
ret i32 %val
|
|
}
|
|
|
|
; LDRWroX
|
|
define i64 @LdOffset_i32_zext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i32_zext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152
|
|
; CHECK-NEXT: ldr w0, [x8, #14816]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992
|
|
%val = load i32, ptr %arrayidx, align 2
|
|
%conv = zext i32 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRSWroX
|
|
define i64 @LdOffset_i32_sext64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i32_sext64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152
|
|
; CHECK-NEXT: ldrsw x0, [x8, #14816]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992
|
|
%val = load i32, ptr %arrayidx, align 2
|
|
%conv = sext i32 %val to i64
|
|
ret i64 %conv
|
|
}
|
|
|
|
; LDRXroX
|
|
define i64 @LdOffset_i64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304
|
|
; CHECK-NEXT: ldr x0, [x8, #29632]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992
|
|
%val = load i64, ptr %arrayidx, align 4
|
|
ret i64 %val
|
|
}
|
|
|
|
; LDRDroX
|
|
define <2 x i32> @LdOffset_v2i32(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_v2i32:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304
|
|
; CHECK-NEXT: ldr d0, [x8, #29632]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds <2 x i32>, ptr %a, i64 1039992
|
|
%val = load <2 x i32>, ptr %arrayidx, align 4
|
|
ret <2 x i32> %val
|
|
}
|
|
|
|
; LDRQroX
|
|
define <2 x i64> @LdOffset_v2i64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_v2i64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #4048, lsl #12 // =16580608
|
|
; CHECK-NEXT: ldr q0, [x8, #59264]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds <2 x i64>, ptr %a, i64 1039992
|
|
%val = load <2 x i64>, ptr %arrayidx, align 4
|
|
ret <2 x i64> %val
|
|
}
|
|
|
|
; LDRSBWroX
|
|
define double @LdOffset_i8_f64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288
|
|
; CHECK-NEXT: ldrsb w8, [x8, #3704]
|
|
; CHECK-NEXT: scvtf d0, w8
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
%conv = sitofp i8 %val to double
|
|
ret double %conv
|
|
}
|
|
|
|
; LDRSHWroX
|
|
define double @LdOffset_i16_f64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i16_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576
|
|
; CHECK-NEXT: ldrsh w8, [x8, #7408]
|
|
; CHECK-NEXT: scvtf d0, w8
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = sitofp i16 %val to double
|
|
ret double %conv
|
|
}
|
|
|
|
; LDRSroX
|
|
define double @LdOffset_i32_f64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i32_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152
|
|
; CHECK-NEXT: ldr s0, [x8, #14816]
|
|
; CHECK-NEXT: ucvtf d0, d0
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992
|
|
%val = load i32, ptr %arrayidx, align 4
|
|
%conv = uitofp i32 %val to double
|
|
ret double %conv
|
|
}
|
|
|
|
; LDRDroX
|
|
define double @LdOffset_i64_f64(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i64_f64:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304
|
|
; CHECK-NEXT: ldr d0, [x8, #29632]
|
|
; CHECK-NEXT: scvtf d0, d0
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992
|
|
%val = load i64, ptr %arrayidx, align 8
|
|
%conv = sitofp i64 %val to double
|
|
ret double %conv
|
|
}
|
|
|
|
define i64 @LdOffset_i64_multi_offset(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i64_multi_offset:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #2031, lsl #12 // =8318976
|
|
; CHECK-NEXT: ldr x9, [x8, #960]
|
|
; CHECK-NEXT: ldr x8, [x8, #3016]
|
|
; CHECK-NEXT: add x0, x8, x9
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992
|
|
%val0 = load i64, ptr %arrayidx, align 8
|
|
%arrayidx1 = getelementptr inbounds i64, ptr %a, i64 1040249
|
|
%val1 = load i64, ptr %arrayidx1, align 8
|
|
%add = add nsw i64 %val1, %val0
|
|
ret i64 %add
|
|
}
|
|
|
|
define i64 @LdOffset_i64_multi_offset_with_commmon_base(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i64_multi_offset_with_commmon_base:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: add x8, x0, #507, lsl #12 // =2076672
|
|
; CHECK-NEXT: ldr x9, [x8, #26464]
|
|
; CHECK-NEXT: ldr x8, [x8, #26496]
|
|
; CHECK-NEXT: add x0, x8, x9
|
|
; CHECK-NEXT: ret
|
|
%b = getelementptr inbounds i16, ptr %a, i64 1038336
|
|
%arrayidx = getelementptr inbounds i64, ptr %b, i64 3308
|
|
%val0 = load i64, ptr %arrayidx, align 8
|
|
%arrayidx1 = getelementptr inbounds i64, ptr %b, i64 3312
|
|
%val1 = load i64, ptr %arrayidx1, align 8
|
|
%add = add nsw i64 %val1, %val0
|
|
ret i64 %add
|
|
}
|
|
|
|
; Negative test: the offset is odd
|
|
define i32 @LdOffset_i16_odd_offset(ptr nocapture noundef readonly %a) {
|
|
; CHECK-LABEL: LdOffset_i16_odd_offset:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #56953 // =0xde79
|
|
; CHECK-NEXT: movk w8, #15, lsl #16
|
|
; CHECK-NEXT: ldrsh w0, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 1039993
|
|
%val = load i16, ptr %arrayidx, align 2
|
|
%conv = sext i16 %val to i32
|
|
ret i32 %conv
|
|
}
|
|
|
|
; Already encoded with a single mov MOVNWi
|
|
define i8 @LdOffset_i8_movnwi(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_movnwi:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #16777215 // =0xffffff
|
|
; CHECK-NEXT: ldrb w0, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 16777215
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
ret i8 %val
|
|
}
|
|
|
|
; Negative test: the offset is too large to encoded with a add
|
|
define i8 @LdOffset_i8_too_large(ptr %a) {
|
|
; CHECK-LABEL: LdOffset_i8_too_large:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: mov w8, #1 // =0x1
|
|
; CHECK-NEXT: movk w8, #256, lsl #16
|
|
; CHECK-NEXT: ldrb w0, [x0, x8]
|
|
; CHECK-NEXT: ret
|
|
%arrayidx = getelementptr inbounds i8, ptr %a, i64 16777217
|
|
%val = load i8, ptr %arrayidx, align 1
|
|
ret i8 %val
|
|
}
|