; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc < %s | FileCheck %s
target triple = "arm64-none-linux-gnu"

define <4 x half> @test_vsqrt_f16(<4 x half> %a) #0 {
; CHECK-LABEL: test_vsqrt_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fsqrt v0.4h, v0.4h
; CHECK-NEXT:    ret
entry:
  %vsqrt.i = call <4 x half> @llvm.experimental.constrained.sqrt.v4f16(<4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %vsqrt.i
}

define <8 x half> @test_vsqrtq_f16(<8 x half> %a) #0 {
; CHECK-LABEL: test_vsqrtq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fsqrt v0.8h, v0.8h
; CHECK-NEXT:    ret
entry:
  %vsqrt.i = call <8 x half> @llvm.experimental.constrained.sqrt.v8f16(<8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %vsqrt.i
}

define <4 x half> @test_vfma_f16(<4 x half> %a, <4 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfma_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmla v0.4h, v2.4h, v1.4h
; CHECK-NEXT:    ret
entry:
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %b, <4 x half> %c, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmaq_f16(<8 x half> %a, <8 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmaq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmla v0.8h, v2.8h, v1.8h
; CHECK-NEXT:    ret
entry:
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %b, <8 x half> %c, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define <4 x half> @test_vfms_f16(<4 x half> %a, <4 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfms_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmls v0.4h, v2.4h, v1.4h
; CHECK-NEXT:    ret
entry:
  %fneg.i = fneg <4 x half> %b
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %fneg.i, <4 x half> %c, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmsq_f16(<8 x half> %a, <8 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmsq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmls v0.8h, v2.8h, v1.8h
; CHECK-NEXT:    ret
entry:
  %fneg.i = fneg <8 x half> %b
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %fneg.i, <8 x half> %c, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define <4 x half> @test_vfma_lane_f16(<4 x half> %a, <4 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfma_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fmla v0.4h, v1.4h, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %lane = shufflevector <4 x half> %c, <4 x half> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
  %fmla2 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %b, <4 x half> %lane, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %fmla2
}

define <8 x half> @test_vfmaq_lane_f16(<8 x half> %a, <8 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfmaq_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fmla v0.8h, v1.8h, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %lane = shufflevector <4 x half> %c, <4 x half> poison, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
  %fmla2 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %b, <8 x half> %lane, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %fmla2
}

define <4 x half> @test_vfma_laneq_f16(<4 x half> %a, <4 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfma_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmla v0.4h, v1.4h, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %lane = shufflevector <8 x half> %c, <8 x half> poison, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %lane, <4 x half> %b, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmaq_laneq_f16(<8 x half> %a, <8 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmaq_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmla v0.8h, v1.8h, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %lane = shufflevector <8 x half> %c, <8 x half> poison, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %lane, <8 x half> %b, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define <4 x half> @test_vfma_n_f16(<4 x half> %a, <4 x half> %b, half %c) #0 {
; CHECK-LABEL: test_vfma_n_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $h2 killed $h2 def $q2
; CHECK-NEXT:    fmla v0.4h, v1.4h, v2.h[0]
; CHECK-NEXT:    ret
entry:
  %vecinit = insertelement <4 x half> poison, half %c, i64 0
  %vecinit3 = shufflevector <4 x half> %vecinit, <4 x half> poison, <4 x i32> zeroinitializer
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %b, <4 x half> %vecinit3, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmaq_n_f16(<8 x half> %a, <8 x half> %b, half %c) #0 {
; CHECK-LABEL: test_vfmaq_n_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $h2 killed $h2 def $q2
; CHECK-NEXT:    fmla v0.8h, v1.8h, v2.h[0]
; CHECK-NEXT:    ret
entry:
  %vecinit = insertelement <8 x half> poison, half %c, i64 0
  %vecinit7 = shufflevector <8 x half> %vecinit, <8 x half> poison, <8 x i32> zeroinitializer
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %b, <8 x half> %vecinit7, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define half @test_vfmah_lane_f16(half %a, half %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfmah_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fmla h0, h1, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %extract = extractelement <4 x half> %c, i64 3
  %0 = call half @llvm.experimental.constrained.fma.f16(half %b, half %extract, half %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret half %0
}

define half @test_vfmah_laneq_f16(half %a, half %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmah_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmla h0, h1, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %extract = extractelement <8 x half> %c, i64 7
  %0 = call half @llvm.experimental.constrained.fma.f16(half %b, half %extract, half %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret half %0
}

define <4 x half> @test_vfms_lane_f16(<4 x half> %a, <4 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfms_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fmls v0.4h, v1.4h, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <4 x half> %b
  %lane = shufflevector <4 x half> %c, <4 x half> poison, <4 x i32> <i32 3, i32 3, i32 3, i32 3>
  %fmla2 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %fneg, <4 x half> %lane, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %fmla2
}

define <8 x half> @test_vfmsq_lane_f16(<8 x half> %a, <8 x half> %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfmsq_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fmls v0.8h, v1.8h, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <8 x half> %b
  %lane = shufflevector <4 x half> %c, <4 x half> poison, <8 x i32> <i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3, i32 3>
  %fmla2 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %fneg, <8 x half> %lane, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %fmla2
}

define <4 x half> @test_vfms_laneq_f16(<4 x half> %a, <4 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfms_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmls v0.4h, v1.4h, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <4 x half> %b
  %lane = shufflevector <8 x half> %c, <8 x half> poison, <4 x i32> <i32 7, i32 7, i32 7, i32 7>
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %lane, <4 x half> %fneg, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmsq_laneq_f16(<8 x half> %a, <8 x half> %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmsq_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fmls v0.8h, v1.8h, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <8 x half> %b
  %lane = shufflevector <8 x half> %c, <8 x half> poison, <8 x i32> <i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7, i32 7>
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %lane, <8 x half> %fneg, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define <4 x half> @test_vfms_n_f16(<4 x half> %a, <4 x half> %b, half %c) #0 {
; CHECK-LABEL: test_vfms_n_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $h2 killed $h2 def $q2
; CHECK-NEXT:    fmls v0.4h, v1.4h, v2.h[0]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <4 x half> %b
  %vecinit = insertelement <4 x half> poison, half %c, i64 0
  %vecinit3 = shufflevector <4 x half> %vecinit, <4 x half> poison, <4 x i32> zeroinitializer
  %0 = call <4 x half> @llvm.experimental.constrained.fma.v4f16(<4 x half> %fneg, <4 x half> %vecinit3, <4 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <4 x half> %0
}

define <8 x half> @test_vfmsq_n_f16(<8 x half> %a, <8 x half> %b, half %c) #0 {
; CHECK-LABEL: test_vfmsq_n_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    // kill: def $h2 killed $h2 def $q2
; CHECK-NEXT:    fmls v0.8h, v1.8h, v2.h[0]
; CHECK-NEXT:    ret
entry:
  %fneg = fneg <8 x half> %b
  %vecinit = insertelement <8 x half> poison, half %c, i64 0
  %vecinit7 = shufflevector <8 x half> %vecinit, <8 x half> poison, <8 x i32> zeroinitializer
  %0 = call <8 x half> @llvm.experimental.constrained.fma.v8f16(<8 x half> %fneg, <8 x half> %vecinit7, <8 x half> %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret <8 x half> %0
}

define half @test_vfmsh_lane_f16(half %a, half %b, <4 x half> %c) #0 {
; CHECK-LABEL: test_vfmsh_lane_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fcvt s1, h1
; CHECK-NEXT:    // kill: def $d2 killed $d2 def $q2
; CHECK-NEXT:    fneg s1, s1
; CHECK-NEXT:    fcvt h1, s1
; CHECK-NEXT:    fmla h0, h1, v2.h[3]
; CHECK-NEXT:    ret
entry:
  %conv = call float @llvm.experimental.constrained.fpext.f32.f16(half %b, metadata !"fpexcept.strict") #1
  %fneg = fneg float %conv
  %0 = call half @llvm.experimental.constrained.fptrunc.f16.f32(float %fneg, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  %extract = extractelement <4 x half> %c, i64 3
  %1 = call half @llvm.experimental.constrained.fma.f16(half %0, half %extract, half %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret half %1
}

define half @test_vfmsh_laneq_f16(half %a, half %b, <8 x half> %c) #0 {
; CHECK-LABEL: test_vfmsh_laneq_f16:
; CHECK:       // %bb.0: // %entry
; CHECK-NEXT:    fcvt s1, h1
; CHECK-NEXT:    fneg s1, s1
; CHECK-NEXT:    fcvt h1, s1
; CHECK-NEXT:    fmla h0, h1, v2.h[7]
; CHECK-NEXT:    ret
entry:
  %conv = call float @llvm.experimental.constrained.fpext.f32.f16(half %b, metadata !"fpexcept.strict") #1
  %fneg = fneg float %conv
  %0 = call half @llvm.experimental.constrained.fptrunc.f16.f32(float %fneg, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  %extract = extractelement <8 x half> %c, i64 7
  %1 = call half @llvm.experimental.constrained.fma.f16(half %0, half %extract, half %a, metadata !"round.tonearest", metadata !"fpexcept.strict") #1
  ret half %1
}

attributes #0 = { noinline nounwind strictfp "target-features"="+crc,+fp-armv8,+fullfp16,+lse,+neon,+ras,+rdm,+v8.1a,+v8.2a,+v8a" }
attributes #1 = { strictfp }
