121 lines · plain
1; RUN: llc -verify-machineinstrs -mtriple=armv7-none-linux-gnueabi -mcpu=cortex-a9 -mattr=+neon,+neonfp -float-abi=hard < %s | FileCheck %s2 3define <2 x float> @test_vmovs_via_vext_lane0to0(float %arg, <2 x float> %in) {4; CHECK-LABEL: test_vmovs_via_vext_lane0to0:5 %vec = insertelement <2 x float> %in, float %arg, i32 06 %res = fadd <2 x float> %vec, %vec7 8; CHECK: vext.32 d1, d1, d0, #19; CHECK: vext.32 d1, d1, d1, #110; CHECK: vadd.f32 {{d[0-9]+}}, d1, d111 12 ret <2 x float> %res13}14 15define <2 x float> @test_vmovs_via_vext_lane0to1(float %arg, <2 x float> %in) {16; CHECK-LABEL: test_vmovs_via_vext_lane0to1:17 %vec = insertelement <2 x float> %in, float %arg, i32 118 %res = fadd <2 x float> %vec, %vec19 20; CHECK: vext.32 d1, d1, d1, #121; CHECK: vext.32 d1, d1, d0, #122; CHECK: vadd.f32 {{d[0-9]+}}, d1, d123 24 ret <2 x float> %res25}26 27define <2 x float> @test_vmovs_via_vext_lane1to0(float, float %arg, <2 x float> %in) {28; CHECK-LABEL: test_vmovs_via_vext_lane1to0:29 %vec = insertelement <2 x float> %in, float %arg, i32 030 %res = fadd <2 x float> %vec, %vec31 32; CHECK: vext.32 d1, d1, d1, #133; CHECK: vext.32 d1, d0, d1, #134; CHECK: vadd.f32 {{d[0-9]+}}, d1, d135 36 ret <2 x float> %res37}38 39define <2 x float> @test_vmovs_via_vext_lane1to1(float, float %arg, <2 x float> %in) {40; CHECK-LABEL: test_vmovs_via_vext_lane1to1:41 %vec = insertelement <2 x float> %in, float %arg, i32 142 %res = fadd <2 x float> %vec, %vec43 44; CHECK: vext.32 d1, d0, d1, #145; CHECK: vext.32 d1, d1, d1, #146; CHECK: vadd.f32 {{d[0-9]+}}, d1, d147 48 ret <2 x float> %res49}50 51 52define float @test_vmovs_via_vdup(float, float %ret, float %lhs, float %rhs) {53; CHECK-LABEL: test_vmovs_via_vdup:54 55 ; Do an operation (which will end up NEON because of +neonfp) to convince the56 ; execution-domain pass that NEON is a good thing to use.57 %res = fadd float %ret, %ret58 ; It makes sense for LLVM to do the addition in d0 here, because it's going59 ; to be returned. This means it will want a "vmov s0, s1":60; CHECK: vdup.32 d0, d0[1]61 62 ret float %res63}64 65declare float @llvm.sqrt.f32(float)66 67declare void @bar()68 69; This is a comp70define float @test_ineligible(float, float %in) {71; CHECK-LABEL: test_ineligible:72 73 %sqrt = call float @llvm.sqrt.f32(float %in)74 %val = fadd float %sqrt, %sqrt75 76 ; This call forces a move from a callee-saved register to the return-reg. That77 ; move is not eligible for conversion to a d-register instructions because the78 ; use-def chains would be messed up. Primarily a compile-test (we used to79 ; internal fault).80 call void @bar()81; CHECK: bl bar82; CHECK: vext.3283; CHECK: vext.3284 ret float %val85}86 87define i32 @test_vmovs_no_sreg(i32 %in) {88; CHECK-LABEL: test_vmovs_no_sreg:89 90 ; Check that the movement to and from GPRs takes place in the NEON domain.91; CHECK: vmov.32 d92 %x = bitcast i32 %in to float93 94 %res = fadd float %x, %x95 96; CHECK: vmov.32 r{{[0-9]+}}, d97 %resi = bitcast float %res to i3298 99 ret i32 %resi100}101 102 103; The point of this test is:104; + Make sure s1 is live before the BL105; + Make sure s1 is clobbered by the BL106; + Convince LLVM to emit a VMOV to S0107; + Convince LLVM to domain-convert this.108 109; When all of those are satisfied, LLVM should *not* mark s1 as an implicit-use110; because it's dead.111 112declare float @clobbers_s1(float, float)113 114define <2 x float> @test_clobbers_recognised(<2 x float> %invec, float %val) {115 %elt = call float @clobbers_s1(float %val, float %val)116 117 %vec = insertelement <2 x float> %invec, float %elt, i32 0118 %res = fadd <2 x float> %vec, %vec119 ret <2 x float> %res120}121