| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 2 |
| ; RUN: llc < %s -verify-machineinstrs -mtriple=arm64-none-linux-gnu -mattr=+neon -fp-contract=fast | FileCheck %s |
| |
| define float @test_fmul_lane_ss2S_0(float %a, <2 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss2S_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 |
| ; CHECK-NEXT: fmul s0, s0, s1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x float> %v, i32 0 |
| %tmp2 = fmul float %a, %tmp1 |
| ret float %tmp2 |
| } |
| |
| define float @test_fmul_lane_ss2S_1(float %a, <2 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss2S_1: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 |
| ; CHECK-NEXT: fmul s0, s0, v1.s[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x float> %v, i32 1 |
| %tmp2 = fmul float %a, %tmp1; |
| ret float %tmp2; |
| } |
| |
| define float @test_fmul_lane_ss2S_1_swap(float %a, <2 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss2S_1_swap: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 |
| ; CHECK-NEXT: fmul s0, s0, v1.s[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x float> %v, i32 1 |
| %tmp2 = fmul float %tmp1, %a; |
| ret float %tmp2; |
| } |
| |
| define float @test_fmul_lane_ss4S_0(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss4S_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul s0, s0, s1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 0 |
| %tmp2 = fmul float %a, %tmp1 |
| ret float %tmp2 |
| } |
| |
| define float @test_fmul_lane_ss4S_3(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss4S_3: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul s0, s0, v1.s[3] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 3 |
| %tmp2 = fmul float %a, %tmp1; |
| ret float %tmp2; |
| } |
| |
| define float @test_fmul_lane_ss4S_3_swap(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ss4S_3_swap: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul s0, s0, v1.s[3] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 3 |
| %tmp2 = fmul float %tmp1, %a; |
| ret float %tmp2; |
| } |
| |
| |
| define double @test_fmul_lane_ddD(double %a, <1 x double> %v) { |
| ; CHECK-LABEL: test_fmul_lane_ddD: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul d0, d0, d1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <1 x double> %v, i32 0 |
| %tmp2 = fmul double %a, %tmp1; |
| ret double %tmp2; |
| } |
| |
| |
| define double @test_fmul_lane_dd2D_0(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmul_lane_dd2D_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul d0, d0, d1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 0 |
| %tmp2 = fmul double %a, %tmp1 |
| ret double %tmp2 |
| } |
| |
| define double @test_fmul_lane_dd2D_1(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmul_lane_dd2D_1: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul d0, d0, v1.d[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 1 |
| %tmp2 = fmul double %a, %tmp1; |
| ret double %tmp2; |
| } |
| |
| |
| define double @test_fmul_lane_dd2D_1_swap(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmul_lane_dd2D_1_swap: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmul d0, d0, v1.d[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 1 |
| %tmp2 = fmul double %tmp1, %a; |
| ret double %tmp2; |
| } |
| |
| declare float @llvm.aarch64.neon.fmulx.f32(float, float) |
| |
| define float @test_fmulx_lane_f32_0(float %a, <2 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_lane_f32_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 |
| ; CHECK-NEXT: fmulx s0, s0, s1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x float> %v, i32 0 |
| %tmp2 = call float @llvm.aarch64.neon.fmulx.f32(float %a, float %tmp1) |
| ret float %tmp2; |
| } |
| |
| define float @test_fmulx_lane_f32_1(float %a, <2 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_lane_f32_1: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1 |
| ; CHECK-NEXT: fmulx s0, s0, v1.s[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x float> %v, i32 1 |
| %tmp2 = call float @llvm.aarch64.neon.fmulx.f32(float %a, float %tmp1) |
| ret float %tmp2; |
| } |
| |
| define float @test_fmulx_laneq_f32_0(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f32_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx s0, s0, s1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 0 |
| %tmp2 = call float @llvm.aarch64.neon.fmulx.f32(float %a, float %tmp1) |
| ret float %tmp2; |
| } |
| |
| define float @test_fmulx_laneq_f32_3(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f32_3: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx s0, s0, v1.s[3] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 3 |
| %tmp2 = call float @llvm.aarch64.neon.fmulx.f32(float %a, float %tmp1) |
| ret float %tmp2; |
| } |
| |
| define float @test_fmulx_laneq_f32_3_swap(float %a, <4 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f32_3_swap: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx s0, s0, v1.s[3] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <4 x float> %v, i32 3 |
| %tmp2 = call float @llvm.aarch64.neon.fmulx.f32(float %tmp1, float %a) |
| ret float %tmp2; |
| } |
| |
| declare double @llvm.aarch64.neon.fmulx.f64(double, double) |
| |
| define double @test_fmulx_lane_f64(double %a, <1 x double> %v) { |
| ; CHECK-LABEL: test_fmulx_lane_f64: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx d0, d0, d1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <1 x double> %v, i32 0 |
| %tmp2 = call double @llvm.aarch64.neon.fmulx.f64(double %a, double %tmp1) |
| ret double %tmp2; |
| } |
| |
| define double @test_fmulx_laneq_f64_0(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f64_0: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx d0, d0, d1 |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 0 |
| %tmp2 = call double @llvm.aarch64.neon.fmulx.f64(double %a, double %tmp1) |
| ret double %tmp2; |
| } |
| |
| |
| define double @test_fmulx_laneq_f64_1(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f64_1: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx d0, d0, v1.d[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 1 |
| %tmp2 = call double @llvm.aarch64.neon.fmulx.f64(double %a, double %tmp1) |
| ret double %tmp2; |
| } |
| |
| define double @test_fmulx_laneq_f64_1_swap(double %a, <2 x double> %v) { |
| ; CHECK-LABEL: test_fmulx_laneq_f64_1_swap: |
| ; CHECK: // %bb.0: |
| ; CHECK-NEXT: fmulx d0, d0, v1.d[1] |
| ; CHECK-NEXT: ret |
| %tmp1 = extractelement <2 x double> %v, i32 1 |
| %tmp2 = call double @llvm.aarch64.neon.fmulx.f64(double %tmp1, double %a) |
| ret double %tmp2; |
| } |
| |
| define float @test_fmulx_horizontal_f32(<2 x float> %v) { |
| ; CHECK-LABEL: test_fmulx_horizontal_f32: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0 |
| ; CHECK-NEXT: fmulx s0, s0, v0.s[1] |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = extractelement <2 x float> %v, i32 0 |
| %1 = extractelement <2 x float> %v, i32 1 |
| %2 = call float @llvm.aarch64.neon.fmulx.f32(float %0, float %1) |
| ret float %2 |
| } |
| |
| define double @test_fmulx_horizontal_f64(<2 x double> %v) { |
| ; CHECK-LABEL: test_fmulx_horizontal_f64: |
| ; CHECK: // %bb.0: // %entry |
| ; CHECK-NEXT: fmulx d0, d0, v0.d[1] |
| ; CHECK-NEXT: ret |
| entry: |
| %0 = extractelement <2 x double> %v, i32 0 |
| %1 = extractelement <2 x double> %v, i32 1 |
| %2 = call double @llvm.aarch64.neon.fmulx.f64(double %0, double %1) |
| ret double %2 |
| } |