; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -mattr=+ipu1 -march=colossus -enable-pipeliner < %s | FileCheck %s

define void @swp_half4_fabs(i32 %size, <4 x half>* noalias nocapture readonly %in, <4 x half>* noalias nocapture %out) {
; CHECK-LABEL: swp_half4_fabs:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    brz $m0, .LBB0_5
; CHECK-NEXT:  # %bb.1: # %for.body.preheader
; CHECK-NEXT:    setzi $a0, 32768
; CHECK-NEXT:    or $a0, $a0, 2147483648
; CHECK-NEXT:    {
; CHECK-NEXT:     setzi $m3, 1
; CHECK-NEXT:     mov $a1, $a0
; CHECK-NEXT:    }
; CHECK-NEXT:    ld64step $a2:3, $m15, $m1+=, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     cmpslt $m3, $m3, $m0
; CHECK-NEXT:     andc64 $a2:3, $a2:3, $a0:1
; CHECK-NEXT:    }
; CHECK-NEXT:    add $m0, $m0, -1
; CHECK-NEXT:  # %bb.2: # %for.body
; CHECK-NEXT:  # %bb.3: # %for.body
; CHECK-NEXT:    {
; CHECK-NEXT:     rpt $m0, 1
; CHECK-NEXT:     fnop
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     ld64step $a4:5, $m15, $m1+=, 1
; CHECK-NEXT:     fnop
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     st64step $a2:3, $m15, $m2+=, 1
; CHECK-NEXT:     andc64 $a2:3, $a4:5, $a0:1
; CHECK-NEXT:    }
; CHECK-NEXT:  # %bb.4:
; CHECK-NEXT:    st64step $a2:3, $m15, $m2+=, 1
; CHECK-NEXT:  .LBB0_5: # %for.cond.cleanup
; CHECK-NEXT:    br $m10
entry:
  %cmp = icmp ult i32 %size, 4095
  tail call void @llvm.assume(i1 %cmp)
  %cmp110.not = icmp eq i32 %size, 0
  br i1 %cmp110.not, label %for.cond.cleanup, label %for.body

for.cond.cleanup:
  ret void

for.body:
  %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %h4Out.012 = phi <4 x half>* [ %incdec.ptr2, %for.body ], [ %out, %entry ]
  %h4In.011 = phi <4 x half>* [ %incdec.ptr, %for.body ], [ %in, %entry ]
  %0 = load <4 x half>, <4 x half>* %h4In.011, align 8, !tbaa !2
  %call = tail call <4 x half> @llvm.fabs.v4f16(<4 x half> %0) #6
  store <4 x half> %call, <4 x half>* %h4Out.012, align 8, !tbaa !2
  %incdec.ptr = getelementptr inbounds <4 x half>, <4 x half>* %h4In.011, i32 1
  %incdec.ptr2 = getelementptr inbounds <4 x half>, <4 x half>* %h4Out.012, i32 1
  %inc = add nuw i32 %i.013, 1
  %exitcond.not = icmp eq i32 %inc, %size
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !5
}

declare void @llvm.assume(i1 noundef) #1

define void @swp_half2_fabs(i32 %size, <2 x half>* noalias nocapture readonly %in, <2 x half>* noalias nocapture %out) local_unnamed_addr #2 {
; CHECK-LABEL: swp_half2_fabs:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    brz $m0, .LBB1_5
; CHECK-NEXT:  # %bb.1: # %for.body.preheader
; CHECK-NEXT:    setzi $a0, 32768
; CHECK-NEXT:    {
; CHECK-NEXT:     setzi $m3, 1
; CHECK-NEXT:     or $a1, $a0, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:    ld32step $a0, $m15, $m1+=, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     cmpslt $m3, $m3, $m0
; CHECK-NEXT:     andc $a0, $a0, $a1
; CHECK-NEXT:    }
; CHECK-NEXT:    add $m0, $m0, -1
; CHECK-NEXT:  # %bb.2: # %for.body
; CHECK-NEXT:  # %bb.3: # %for.body
; CHECK-NEXT:    {
; CHECK-NEXT:     rpt $m0, 1
; CHECK-NEXT:     fnop
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     ld32step $a2, $m15, $m1+=, 1
; CHECK-NEXT:     fnop
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     st32step $a0, $m15, $m2+=, 1
; CHECK-NEXT:     andc $a0, $a2, $a1
; CHECK-NEXT:    }
; CHECK-NEXT:  # %bb.4:
; CHECK-NEXT:    st32step $a0, $m15, $m2+=, 1
; CHECK-NEXT:  .LBB1_5: # %for.cond.cleanup
; CHECK-NEXT:    br $m10
entry:
  %cmp = icmp ult i32 %size, 4095
  tail call void @llvm.assume(i1 %cmp)
  %cmp110.not = icmp eq i32 %size, 0
  br i1 %cmp110.not, label %for.cond.cleanup, label %for.body

for.cond.cleanup:
  ret void

for.body:
  %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %h2Out.012 = phi <2 x half>* [ %incdec.ptr2, %for.body ], [ %out, %entry ]
  %h2In.011 = phi <2 x half>* [ %incdec.ptr, %for.body ], [ %in, %entry ]
  %0 = load <2 x half>, <2 x half>* %h2In.011, align 4, !tbaa !2
  %call = tail call <2 x half> @llvm.fabs.v2f16(<2 x half> %0) #6
  store <2 x half> %call, <2 x half>* %h2Out.012, align 4, !tbaa !2
  %incdec.ptr = getelementptr inbounds <2 x half>, <2 x half>* %h2In.011, i32 1
  %incdec.ptr2 = getelementptr inbounds <2 x half>, <2 x half>* %h2Out.012, i32 1
  %inc = add nuw i32 %i.013, 1
  %exitcond.not = icmp eq i32 %inc, %size
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !7
}

define void @swp_float_fabs(i32 %size, float* noalias nocapture readonly %in, float* noalias nocapture %out) local_unnamed_addr #3 {
; CHECK-LABEL: swp_float_fabs:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    add $m11, $m11, -8
; CHECK-NEXT:    st32 $m7, $m11, $m15, 1
; CHECK-NEXT:    brz $m0, .LBB2_11
; CHECK-NEXT:  # %bb.1: # %entry
; CHECK-NEXT:    cmpeq $m3, $m0, 1
; CHECK-NEXT:    brz $m3, .LBB2_3
; CHECK-NEXT:  # %bb.2:
; CHECK-NEXT:    mov $m5, $m15
; CHECK-NEXT:    mov $m3, $m2
; CHECK-NEXT:    mov $m4, $m1
; CHECK-NEXT:    bri .LBB2_7
; CHECK-NEXT:  .LBB2_3: # %vector.ph
; CHECK-NEXT:    and $m5, $m0, 4094
; CHECK-NEXT:    add $m3, $m5, -2
; CHECK-NEXT:    shl $m4, $m5, 2
; CHECK-NEXT:    shr $m6, $m3, 1
; CHECK-NEXT:    add $m3, $m2, $m4
; CHECK-NEXT:    add $m4, $m1, $m4
; CHECK-NEXT:    add $m6, $m6, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     ld32 $a1, $m1, $m15, 1
; CHECK-NEXT:     or $a2, $a15, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:    ld32step $a0, $m15, $m1+=, 2
; CHECK-NEXT:    {
; CHECK-NEXT:     setzi $m7, 1
; CHECK-NEXT:     mov $a3, $a2
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     cmpslt $m7, $m7, $m6
; CHECK-NEXT:     andc64 $a0:1, $a0:1, $a2:3
; CHECK-NEXT:    }
; CHECK-NEXT:    st32 $a1, $m2, $m15, 1
; CHECK-NEXT:    add $m6, $m6, -1
; CHECK-NEXT:    brz $m7, .LBB2_6
; CHECK-NEXT:  # %bb.4: # %vector.body
; CHECK-NEXT:    add $m6, $m6, -1
; CHECK-NEXT:    {
; CHECK-NEXT:     mov $m7, $m1
; CHECK-NEXT:     or $a4, $a15, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:  .LBB2_5: # %vector.body
; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ld32step $a2, $m15, $m7+=, 2
; CHECK-NEXT:    {
; CHECK-NEXT:     ld32 $a3, $m1, $m15, 1
; CHECK-NEXT:     mov $a5, $a4
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     st32step $a0, $m15, $m2+=, 2
; CHECK-NEXT:     andc64 $a0:1, $a2:3, $a4:5
; CHECK-NEXT:    }
; CHECK-NEXT:    st32 $a1, $m2, $m15, 1
; CHECK-NEXT:    mov $m1, $m7
; CHECK-NEXT:    brnzdec $m6, .LBB2_5
; CHECK-NEXT:  .LBB2_6:
; CHECK-NEXT:    st32step $a0, $m15, $m2+=, 2
; CHECK-NEXT:    cmpeq $m1, $m5, $m0
; CHECK-NEXT:    brnz $m1, .LBB2_11
; CHECK-NEXT:  .LBB2_7: # %for.body.preheader
; CHECK-NEXT:    sub $m0, $m0, $m5
; CHECK-NEXT:    setzi $m1, 1
; CHECK-NEXT:    ld32step $a0, $m15, $m4+=, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     cmpslt $m1, $m1, $m0
; CHECK-NEXT:     andc $a0, $a0, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:    add $m0, $m0, -1
; CHECK-NEXT:    brz $m1, .LBB2_10
; CHECK-NEXT:  # %bb.8: # %for.body
; CHECK-NEXT:    add $m0, $m0, -1
; CHECK-NEXT:  .LBB2_9: # %for.body
; CHECK-NEXT:    # =>This Inner Loop Header: Depth=1
; CHECK-NEXT:    ld32step $a1, $m15, $m4+=, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     st32step $a0, $m15, $m3+=, 1
; CHECK-NEXT:     andc $a0, $a1, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:    brnzdec $m0, .LBB2_9
; CHECK-NEXT:  .LBB2_10:
; CHECK-NEXT:    st32step $a0, $m15, $m3+=, 1
; CHECK-NEXT:  .LBB2_11: # %for.cond.cleanup
; CHECK-NEXT:    ld32 $m7, $m11, $m15, 1
; CHECK-NEXT:    add $m11, $m11, 8
; CHECK-NEXT:    br $m10
entry:
  %cmp = icmp ult i32 %size, 4095
  tail call void @llvm.assume(i1 %cmp)
  switch i32 %size, label %vector.ph [
    i32 0, label %for.cond.cleanup
    i32 1, label %for.body.preheader
  ]

vector.ph:
  %n.vec = and i32 %size, 4094
  %ind.end = getelementptr float, float* %out, i32 %n.vec
  %ind.end16 = getelementptr float, float* %in, i32 %n.vec
  br label %vector.body

vector.body:
  %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
  %next.gep = getelementptr float, float* %out, i32 %index
  %next.gep17 = getelementptr float, float* %in, i32 %index
  %0 = bitcast float* %next.gep17 to <2 x float>*
  %wide.load = load <2 x float>, <2 x float>* %0, align 4, !tbaa !8
  %1 = call <2 x float> @llvm.fabs.v2f32(<2 x float> %wide.load)
  %2 = bitcast float* %next.gep to <2 x float>*
  store <2 x float> %1, <2 x float>* %2, align 4, !tbaa !8
  %index.next = add nuw i32 %index, 2
  %3 = icmp eq i32 %index.next, %n.vec
  br i1 %3, label %middle.block, label %vector.body, !llvm.loop !10

middle.block:
  %cmp.n = icmp eq i32 %n.vec, %size
  br i1 %cmp.n, label %for.cond.cleanup, label %for.body.preheader

for.body.preheader:
  %i.013.ph = phi i32 [ 0, %entry ], [ %n.vec, %middle.block ]
  %fOut.012.ph = phi float* [ %out, %entry ], [ %ind.end, %middle.block ]
  %fIn.011.ph = phi float* [ %in, %entry ], [ %ind.end16, %middle.block ]
  br label %for.body

for.cond.cleanup:
  ret void

for.body:
  %i.013 = phi i32 [ %inc, %for.body ], [ %i.013.ph, %for.body.preheader ]
  %fOut.012 = phi float* [ %incdec.ptr2, %for.body ], [ %fOut.012.ph, %for.body.preheader ]
  %fIn.011 = phi float* [ %incdec.ptr, %for.body ], [ %fIn.011.ph, %for.body.preheader ]
  %4 = load float, float* %fIn.011, align 4, !tbaa !8
  %5 = tail call float @llvm.fabs.f32(float %4)
  store float %5, float* %fOut.012, align 4, !tbaa !8
  %incdec.ptr = getelementptr inbounds float, float* %fIn.011, i32 1
  %incdec.ptr2 = getelementptr inbounds float, float* %fOut.012, i32 1
  %inc = add nuw i32 %i.013, 1
  %exitcond.not = icmp eq i32 %inc, %size
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !12
}


define void @swp_float2_fabs(i32 %size, <2 x float>* noalias nocapture readonly %in, <2 x float>* noalias nocapture %out) local_unnamed_addr #0 {
; CHECK-LABEL: swp_float2_fabs:
; CHECK:       # %bb.0: # %entry
; CHECK-NEXT:    brz $m0, .LBB3_5
; CHECK-NEXT:  # %bb.1: # %for.body
; CHECK-NEXT:    {
; CHECK-NEXT:     setzi $m3, 1
; CHECK-NEXT:     or $a0, $a15, 2147483648
; CHECK-NEXT:    }
; CHECK-NEXT:    ld64step $a2:3, $m15, $m1+=, 1
; CHECK-NEXT:    {
; CHECK-NEXT:     cmpslt $m3, $m3, $m0
; CHECK-NEXT:     mov $a1, $a0
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     add $m0, $m0, -1
; CHECK-NEXT:     andc64 $a0:1, $a2:3, $a0:1
; CHECK-NEXT:    }
; CHECK-NEXT:  # %bb.2: # %for.body
; CHECK-NEXT:    or $a4, $a15, 2147483648
; CHECK-NEXT:  # %bb.3: # %for.body
; CHECK-NEXT:    {
; CHECK-NEXT:     rpt $m0, 1
; CHECK-NEXT:     fnop
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     ld64step $a2:3, $m15, $m1+=, 1
; CHECK-NEXT:     mov $a5, $a4
; CHECK-NEXT:    }
; CHECK-NEXT:    {
; CHECK-NEXT:     st64step $a0:1, $m15, $m2+=, 1
; CHECK-NEXT:     andc64 $a0:1, $a2:3, $a4:5
; CHECK-NEXT:    }
; CHECK-NEXT:  # %bb.4:
; CHECK-NEXT:    st64step $a0:1, $m15, $m2+=, 1
; CHECK-NEXT:  .LBB3_5: # %for.cond.cleanup
; CHECK-NEXT:    br $m10
entry:
  %cmp = icmp ult i32 %size, 4095
  tail call void @llvm.assume(i1 %cmp)
  %cmp110.not = icmp eq i32 %size, 0
  br i1 %cmp110.not, label %for.cond.cleanup, label %for.body

for.cond.cleanup:
  ret void

for.body:
  %i.013 = phi i32 [ %inc, %for.body ], [ 0, %entry ]
  %f2Out.012 = phi <2 x float>* [ %incdec.ptr2, %for.body ], [ %out, %entry ]
  %f2In.011 = phi <2 x float>* [ %incdec.ptr, %for.body ], [ %in, %entry ]
  %0 = load <2 x float>, <2 x float>* %f2In.011, align 8, !tbaa !2
  %call = tail call <2 x float> @llvm.fabs.v2f32(<2 x float> %0) #6
  store <2 x float> %call, <2 x float>* %f2Out.012, align 8, !tbaa !2
  %incdec.ptr = getelementptr inbounds <2 x float>, <2 x float>* %f2In.011, i32 1
  %incdec.ptr2 = getelementptr inbounds <2 x float>, <2 x float>* %f2Out.012, i32 1
  %inc = add nuw i32 %i.013, 1
  %exitcond.not = icmp eq i32 %inc, %size
  br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !llvm.loop !14
}

declare float @llvm.fabs.f32(float) #4

declare <4 x half> @llvm.fabs.v4f16(<4 x half>) #5

declare <2 x half> @llvm.fabs.v2f16(<2 x half>) #5

declare <2 x float> @llvm.fabs.v2f32(<2 x float>) #5

attributes #0 = { nounwind "frame-pointer"="none" "min-legal-vector-width"="64" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+worker" }
attributes #1 = { inaccessiblememonly mustprogress nofree nosync nounwind willreturn }
attributes #2 = { nounwind "frame-pointer"="none" "min-legal-vector-width"="32" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+worker" }
attributes #3 = { nofree nosync nounwind "frame-pointer"="none" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+worker" }
attributes #4 = { mustprogress nofree nosync nounwind readnone speculatable willreturn }
attributes #5 = { nofree nosync nounwind readnone speculatable willreturn }
attributes #6 = { nounwind }

!llvm.module.flags = !{!0}
!llvm.ident = !{!1}

!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{!"clang version 14.0.0 (ssh://git@phabricator.sourcevertex.net/diffusion/LLVMPROJECT/llvm-project.git f4497a33ff076b07a488785ff24fa7a1643c9a2f)"}
!2 = !{!3, !3, i64 0}
!3 = !{!"omnipotent char", !4, i64 0}
!4 = !{!"Simple C/C++ TBAA"}
!5 = distinct !{!5, !6}
!6 = !{!"llvm.loop.mustprogress"}
!7 = distinct !{!7, !6}
!8 = !{!9, !9, i64 0}
!9 = !{!"float", !3, i64 0}
!10 = distinct !{!10, !6, !11}
!11 = !{!"llvm.loop.isvectorized", i32 1}
!12 = distinct !{!12, !6, !13, !11}
!13 = !{!"llvm.loop.unroll.runtime.disable"}
!14 = distinct !{!14, !6}
