blob: ede2301f2560abb1a59a5718ed8638c379218d24 [file]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=arm64_32-apple-ios7.0 -mcpu=cyclone %s -o - | FileCheck %s
define <2 x double> @test_insert_elt(<2 x double> %vec, double %val) {
; CHECK-LABEL: test_insert_elt:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $d1 killed $d1 def $q1
; CHECK-NEXT: mov.d v0[0], v1[0]
; CHECK-NEXT: ret
%res = insertelement <2 x double> %vec, double %val, i32 0
ret <2 x double> %res
}
define void @test_split_16B(<4 x float> %val, ptr %addr) {
; CHECK-LABEL: test_split_16B:
; CHECK: ; %bb.0:
; CHECK-NEXT: str q0, [x0]
; CHECK-NEXT: ret
store <4 x float> %val, ptr %addr, align 8
ret void
}
define void @test_split_16B_splat(<4 x i32>, ptr %addr) {
; CHECK-LABEL: test_split_16B_splat:
; CHECK: ; %bb.0:
; CHECK-NEXT: movi.4s v0, #42
; CHECK-NEXT: str q0, [x0]
; CHECK-NEXT: ret
%vec.tmp0 = insertelement <4 x i32> undef, i32 42, i32 0
%vec.tmp1 = insertelement <4 x i32> %vec.tmp0, i32 42, i32 1
%vec.tmp2 = insertelement <4 x i32> %vec.tmp1, i32 42, i32 2
%vec = insertelement <4 x i32> %vec.tmp2, i32 42, i32 3
store <4 x i32> %vec, ptr %addr, align 8
ret void
}
%vec = type <2 x double>
declare {%vec, %vec} @llvm.aarch64.neon.ld2r.v2f64.p0(ptr)
define {%vec, %vec} @test_neon_load(ptr %addr) {
; CHECK-LABEL: test_neon_load:
; CHECK: ; %bb.0:
; CHECK-NEXT: ld2r.2d { v0, v1 }, [x0]
; CHECK-NEXT: ret
%res = call {%vec, %vec} @llvm.aarch64.neon.ld2r.v2f64.p0(ptr %addr)
ret {%vec, %vec} %res
}
declare {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0(%vec, %vec, i64, ptr)
define {%vec, %vec} @test_neon_load_lane(ptr %addr, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_load_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ld2.d { v0, v1 }[0], [x0]
; CHECK-NEXT: ret
%res = call {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0(%vec %in1, %vec %in2, i64 0, ptr %addr)
ret {%vec, %vec} %res
}
declare void @llvm.aarch64.neon.st2.v2f64.p0(%vec, %vec, ptr)
define void @test_neon_store(ptr %addr, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_store:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: st2.2d { v0, v1 }, [x0]
; CHECK-NEXT: ret
call void @llvm.aarch64.neon.st2.v2f64.p0(%vec %in1, %vec %in2, ptr %addr)
ret void
}
declare void @llvm.aarch64.neon.st2lane.v2f64.p0(%vec, %vec, i64, ptr)
define void @test_neon_store_lane(ptr %addr, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_store_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: st2.d { v0, v1 }[1], [x0]
; CHECK-NEXT: ret
call void @llvm.aarch64.neon.st2lane.v2f64.p0(%vec %in1, %vec %in2, i64 1, ptr %addr)
ret void
}
declare {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0(ptr)
define {{%vec, %vec}, ptr} @test_neon_load_post(ptr %addr, i32 %offset) {
; CHECK-LABEL: test_neon_load_post:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: sxtw x8, w1
; CHECK-NEXT: ld2.2d { v0, v1 }, [x0], x8
; CHECK-NEXT: ret
%vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0(ptr %addr)
%addr.new = getelementptr inbounds i8, ptr %addr, i32 %offset
%res.tmp = insertvalue {{%vec, %vec}, ptr} undef, {%vec, %vec} %vecs, 0
%res = insertvalue {{%vec, %vec}, ptr} %res.tmp, ptr %addr.new, 1
ret {{%vec, %vec}, ptr} %res
}
define {{%vec, %vec}, ptr} @test_neon_load_post_lane(ptr %addr, i32 %offset, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_load_post_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: sxtw x8, w1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ld2.d { v0, v1 }[1], [x0], x8
; CHECK-NEXT: ret
%vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2lane.v2f64.p0(%vec %in1, %vec %in2, i64 1, ptr %addr)
%addr.new = getelementptr inbounds i8, ptr %addr, i32 %offset
%res.tmp = insertvalue {{%vec, %vec}, ptr} undef, {%vec, %vec} %vecs, 0
%res = insertvalue {{%vec, %vec}, ptr} %res.tmp, ptr %addr.new, 1
ret {{%vec, %vec}, ptr} %res
}
define ptr @test_neon_store_post(ptr %addr, i32 %offset, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_store_post:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: sxtw x8, w1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: st2.2d { v0, v1 }, [x0], x8
; CHECK-NEXT: ret
call void @llvm.aarch64.neon.st2.v2f64.p0(%vec %in1, %vec %in2, ptr %addr)
%addr.new = getelementptr inbounds i8, ptr %addr, i32 %offset
ret ptr %addr.new
}
define ptr @test_neon_store_post_lane(ptr %addr, i32 %offset, %vec %in1, %vec %in2) {
; CHECK-LABEL: test_neon_store_post_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
; CHECK-NEXT: ; kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: sxtw x8, w1
; CHECK-NEXT: ; kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
; CHECK-NEXT: st2.d { v0, v1 }[0], [x0], x8
; CHECK-NEXT: ret
call void @llvm.aarch64.neon.st2lane.v2f64.p0(%vec %in1, %vec %in2, i64 0, ptr %addr)
%addr.new = getelementptr inbounds i8, ptr %addr, i32 %offset
ret ptr %addr.new
}
; ld1 is slightly different because it goes via ISelLowering of normal IR ops
; rather than an intrinsic.
define {%vec, ptr} @test_neon_ld1_post_lane(ptr %addr, i32 %offset, %vec %in) {
; CHECK-LABEL: test_neon_ld1_post_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ; kill: def $w1 killed $w1 def $x1
; CHECK-NEXT: sbfiz x8, x1, #3, #32
; CHECK-NEXT: ld1.d { v0 }[0], [x0], x8
; CHECK-NEXT: ret
%loaded = load double, ptr %addr, align 8
%newvec = insertelement %vec %in, double %loaded, i32 0
%addr.new = getelementptr inbounds double, ptr %addr, i32 %offset
%res.tmp = insertvalue {%vec, ptr} undef, %vec %newvec, 0
%res = insertvalue {%vec, ptr} %res.tmp, ptr %addr.new, 1
ret {%vec, ptr} %res
}
define {{%vec, %vec}, ptr} @test_neon_load_post_exact(ptr %addr) {
; CHECK-LABEL: test_neon_load_post_exact:
; CHECK: ; %bb.0:
; CHECK-NEXT: ld2.2d { v0, v1 }, [x0], #32
; CHECK-NEXT: ret
%vecs = call {%vec, %vec} @llvm.aarch64.neon.ld2.v2f64.p0(ptr %addr)
%addr.new = getelementptr inbounds i8, ptr %addr, i32 32
%res.tmp = insertvalue {{%vec, %vec}, ptr} undef, {%vec, %vec} %vecs, 0
%res = insertvalue {{%vec, %vec}, ptr} %res.tmp, ptr %addr.new, 1
ret {{%vec, %vec}, ptr} %res
}
define {%vec, ptr} @test_neon_ld1_post_lane_exact(ptr %addr, %vec %in) {
; CHECK-LABEL: test_neon_ld1_post_lane_exact:
; CHECK: ; %bb.0:
; CHECK-NEXT: ld1.d { v0 }[0], [x0], #8
; CHECK-NEXT: ret
%loaded = load double, ptr %addr, align 8
%newvec = insertelement %vec %in, double %loaded, i32 0
%addr.new = getelementptr inbounds double, ptr %addr, i32 1
%res.tmp = insertvalue {%vec, ptr} undef, %vec %newvec, 0
%res = insertvalue {%vec, ptr} %res.tmp, ptr %addr.new, 1
ret {%vec, ptr} %res
}
; As in the general load/store case, this GEP has defined semantics when the
; address wraps. We cannot use post-indexed addressing.
define {%vec, ptr} @test_neon_ld1_notpost_lane_exact(ptr %addr, %vec %in) {
; CHECK-LABEL: test_neon_ld1_notpost_lane_exact:
; CHECK: ; %bb.0:
; CHECK-NEXT: ld1.d { v0 }[0], [x0]
; CHECK-NEXT: add w0, w0, #8
; CHECK-NEXT: ret
%loaded = load double, ptr %addr, align 8
%newvec = insertelement %vec %in, double %loaded, i32 0
%addr.new = getelementptr double, ptr %addr, i32 1
%res.tmp = insertvalue {%vec, ptr} undef, %vec %newvec, 0
%res = insertvalue {%vec, ptr} %res.tmp, ptr %addr.new, 1
ret {%vec, ptr} %res
}
define {%vec, ptr} @test_neon_ld1_notpost_lane(ptr %addr, i32 %offset, %vec %in) {
; CHECK-LABEL: test_neon_ld1_notpost_lane:
; CHECK: ; %bb.0:
; CHECK-NEXT: ld1.d { v0 }[0], [x0]
; CHECK-NEXT: add w0, w0, w1, lsl #3
; CHECK-NEXT: ret
%loaded = load double, ptr %addr, align 8
%newvec = insertelement %vec %in, double %loaded, i32 0
%addr.new = getelementptr double, ptr %addr, i32 %offset
%res.tmp = insertvalue {%vec, ptr} undef, %vec %newvec, 0
%res = insertvalue {%vec, ptr} %res.tmp, ptr %addr.new, 1
ret {%vec, ptr} %res
}