blob: 64fe4252b89c3de3d2e8471260d701b1875fe7e6 [file] [edit]
; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter "(Cost of .*(WIDEN-INDUCTION|SCALAR-STEPS|DERIVED-IV|WIDEN-POINTER-INDUCTION))|(canonical IV increment)|(Cost for VF)" --filter-out-after "LV: (Selecting|Using user) VF" --version 6
; REQUIRES: asserts
; RUN: opt -passes=loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -debug-only=loop-vectorize -disable-output %s 2>&1 | FileCheck --check-prefix=VF2 %s
; RUN: opt -passes=loop-vectorize -force-vector-width=4 -force-vector-interleave=1 -debug-only=loop-vectorize -disable-output %s 2>&1 | FileCheck --check-prefix=VF4 %s
define void @int_induction(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'int_induction'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost for VF 2: 6 (Estimated cost per lane: 3)
;
; VF4-LABEL: 'int_induction'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost for VF 4: 6 (Estimated cost per lane: 1.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%gep = getelementptr inbounds i64, ptr %dst, i64 %iv
store i64 %iv, ptr %gep, align 8
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @fp_induction(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction'
; VF2: Cost of 2 for VF 2: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 6 (Estimated cost per lane: 3)
;
; VF4-LABEL: 'fp_induction'
; VF4: Cost of 2 for VF 4: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 6 (Estimated cost per lane: 1.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%gep = getelementptr inbounds float, ptr %dst, i64 %iv
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @trunc_induction(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'trunc_induction'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]> (truncated to i32)
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost for VF 2: 6 (Estimated cost per lane: 3)
;
; VF4-LABEL: 'trunc_induction'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]> (truncated to i32)
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost for VF 4: 6 (Estimated cost per lane: 1.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.trunc = trunc i64 %iv to i32
%gep = getelementptr inbounds i32, ptr %dst, i64 %iv
store i32 %iv.trunc, ptr %gep, align 4
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @trunc_and_wide_induction(ptr noalias %dst, ptr noalias %dst2, i64 %n) {
; VF2-LABEL: 'trunc_and_wide_induction'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: ir<%iv>.1 = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0]]> (truncated to i32)
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost for VF 2: 9 (Estimated cost per lane: 4.5)
;
; VF4-LABEL: 'trunc_and_wide_induction'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: ir<%iv>.1 = WIDEN-INDUCTION ir<0>, ir<1>, vp<[[VP0]]> (truncated to i32)
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = SCALAR-STEPS vp<[[VP3:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost for VF 4: 9 (Estimated cost per lane: 2.25)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%iv.trunc = trunc i64 %iv to i32
%gep = getelementptr inbounds i32, ptr %dst, i64 %iv
store i32 %iv.trunc, ptr %gep, align 4
%gep2 = getelementptr inbounds i64, ptr %dst2, i64 %iv
store i64 %iv, ptr %gep2, align 8
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; All users of the FP induction need scalars, so no wide induction is generated
; and the scalar steps materialize one FAdd per lane, except for the first.
define void @fp_induction_scalar_users(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_scalar_users'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 10 (Estimated cost per lane: 5)
;
; VF4-LABEL: 'fp_induction_scalar_users'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 14 (Estimated cost per lane: 3.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_scalar_users, but for a decreasing induction, which uses
; FSub to compute the per-lane values.
define void @fp_induction_fsub_scalar_users(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_fsub_scalar_users'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<1.000000e+02> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 2 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<1.000000e+02> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 11 (Estimated cost per lane: 5.5)
;
; VF4-LABEL: 'fp_induction_fsub_scalar_users'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<1.000000e+02> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 2 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<1.000000e+02> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 15 (Estimated cost per lane: 3.75)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 1.000000e+02, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fsub fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_scalar_users, but with a loop-invariant step.
define void @fp_induction_invariant_step_scalar_users(ptr noalias %dst, float %step, i64 %n) {
; VF2-LABEL: 'fp_induction_invariant_step_scalar_users'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 3 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<%step>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<%step>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 3 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<%step>
; VF2: Cost for VF 2: 12 (Estimated cost per lane: 6)
;
; VF4-LABEL: 'fp_induction_invariant_step_scalar_users'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 3 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<%step>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<%step>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 3 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<%step>
; VF4: Cost for VF 4: 16 (Estimated cost per lane: 4)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd fast float %fp.iv, %step
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_scalar_users (fadd, unit step, zero start), but
; without fast-math flags. The add is still expected to fold away: with a
; unit step the DERIVED-IV's addend is exactly sitofp(<the non-negative
; canonical/scalar IV>), which can never be -0.0, so "fadd 0.0, X" folds to X
; regardless of fast-math flags.
define void @fp_induction_no_fastmath_unit_step_zero_start(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_no_fastmath_unit_step_zero_start'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 10 (Estimated cost per lane: 5)
;
; VF4-LABEL: 'fp_induction_no_fastmath_unit_step_zero_start'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 14 (Estimated cost per lane: 3.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_no_fastmath_unit_step_zero_start, but with a
; loop-invariant, sign-unknown step. Unlike the unit-step case, the add is
; not known to fold away here: with a non-unit step the DERIVED-IV's addend
; is Step * sitofp(Index), whose sign depends on the unknown sign of Step, so
; it may be -0.0, and "fadd 0.0, X" doesn't fold to X in that case.
define void @fp_induction_no_fastmath_zero_start_invariant_step(ptr noalias %dst, float %step, i64 %n) {
; VF2-LABEL: 'fp_induction_no_fastmath_zero_start_invariant_step'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 3 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<%step>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<%step>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 3 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<%step>
; VF2: Cost for VF 2: 12 (Estimated cost per lane: 6)
;
; VF4-LABEL: 'fp_induction_no_fastmath_zero_start_invariant_step'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 3 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<%step>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<%step>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 3 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<%step>
; VF4: Cost for VF 4: 16 (Estimated cost per lane: 4)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, %step
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; FSub never folds away for a zero start, regardless of the step: "fsub 0.0,
; X" isn't X, at best it simplifies to "fneg X", which is still a real
; instruction.
define void @fp_induction_fsub_zero_start(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_fsub_zero_start'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 2 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 11 (Estimated cost per lane: 5.5)
;
; VF4-LABEL: 'fp_induction_fsub_zero_start'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 2 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 15 (Estimated cost per lane: 3.75)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fsub fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Start of -0.0 so the FAdd can be folded.
define void @fp_induction_neg_zero_start_neg_step(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_neg_zero_start_neg_step'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<-0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<-2.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<-2.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 2 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<-0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<-2.000000e+00>
; VF2: Cost for VF 2: 11 (Estimated cost per lane: 5.5)
;
; VF4-LABEL: 'fp_induction_neg_zero_start_neg_step'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<-0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<-2.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<-2.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 2 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<-0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<-2.000000e+00>
; VF4: Cost for VF 4: 15 (Estimated cost per lane: 3.75)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ -0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, -2.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_neg_zero_start_neg_step, but with a +0.0 start: the
; FAdd cannot be folded.
define void @fp_induction_pos_zero_start_neg_step(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_pos_zero_start_neg_step'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 3 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<-2.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<-2.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 3 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<-2.000000e+00>
; VF2: Cost for VF 2: 12 (Estimated cost per lane: 6)
;
; VF4-LABEL: 'fp_induction_pos_zero_start_neg_step'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 3 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<-2.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<-2.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 3 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<-2.000000e+00>
; VF4: Cost for VF 4: 16 (Estimated cost per lane: 4)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, -2.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_induction_pos_zero_start_neg_step, but with a positive step.
define void @fp_induction_pos_zero_start_pos_step(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_pos_zero_start_pos_step'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 3 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<2.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<2.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 3 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<2.000000e+00>
; VF2: Cost for VF 2: 12 (Estimated cost per lane: 6)
;
; VF4-LABEL: 'fp_induction_pos_zero_start_pos_step'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 3 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4:%[0-9]+]]> * ir<2.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<2.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 3 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<2.000000e+00>
; VF4: Cost for VF 4: 16 (Estimated cost per lane: 4)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, 2.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; A non-zero start value never folds, so the FAdd is charged even though the
; unit step folds the FMul away.
define void @fp_induction_invariant_start(ptr noalias %dst, float %start, i64 %n) {
; VF2-LABEL: 'fp_induction_invariant_start'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 2 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 11 (Estimated cost per lane: 5.5)
;
; VF4-LABEL: 'fp_induction_invariant_start'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP4:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 2 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 15 (Estimated cost per lane: 3.75)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ %start, %entry ], [ %fp.iv.next, %loop ]
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; The FP induction is only used outside the loop, so it is dead in the vector
; loop and nothing is charged for it.
define float @fp_induction_used_outside_loop_only(ptr noalias %dst, i64 %n) {
; VF2-LABEL: 'fp_induction_used_outside_loop_only'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost for VF 2: 8 (Estimated cost per lane: 4)
;
; VF4-LABEL: 'fp_induction_used_outside_loop_only'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost for VF 4: 8 (Estimated cost per lane: 2)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%gep = getelementptr inbounds i64, ptr %dst, i64 %iv
store i64 %iv, ptr %gep, align 8
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret float %fp.iv.next
}
; The FP induction has both wide and scalar users, so both the wide induction
; and the scalar steps are generated and need to be accounted for.
define void @fp_induction_wide_and_scalar_users(ptr noalias %dst, ptr noalias %dst2, i64 %n) {
; VF2-LABEL: 'fp_induction_wide_and_scalar_users'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 2 for VF 2: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4]]> * ir<1.000000e+00>
; VF2: Cost of 1 for VF 2: vp<[[VP7:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 13 (Estimated cost per lane: 6.5)
;
; VF4-LABEL: 'fp_induction_wide_and_scalar_users'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 2 for VF 4: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4]]> * ir<1.000000e+00>
; VF4: Cost of 3 for VF 4: vp<[[VP7:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 17 (Estimated cost per lane: 4.25)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%gep = getelementptr inbounds float, ptr %dst, i64 %iv
store float %fp.iv, ptr %gep, align 4
%idx = mul i64 %iv, 3
%gep2 = getelementptr inbounds float, ptr %dst2, i64 %idx
store float %fp.iv, ptr %gep2, align 4
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; The scalar steps are inside a replicate region, for which no cost is computed
; yet.
define void @fp_induction_predicated(ptr noalias %dst, ptr noalias %cond, i64 %n) {
; VF2-LABEL: 'fp_induction_predicated'
; VF2: Cost of 2 for VF 2: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4]]> * ir<1.000000e+00>
; VF2: Cost of 0.5 for VF 2: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 12.5 (Estimated cost per lane: 6)
;
; VF4-LABEL: 'fp_induction_predicated'
; VF4: Cost of 2 for VF 4: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP4]]> * ir<1.000000e+00>
; VF4: Cost of 1.5 for VF 4: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<1.000000e+00>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 16.5 (Estimated cost per lane: 4)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %latch ]
%c.gep = getelementptr inbounds i8, ptr %cond, i64 %iv
%c = load i8, ptr %c.gep, align 1
%c.0 = icmp eq i8 %c, 0
br i1 %c.0, label %latch, label %then
then:
%idx = mul i64 %iv, 3
%gep = getelementptr inbounds float, ptr %dst, i64 %idx
store float %fp.iv, ptr %gep, align 4
br label %latch
latch:
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, %n
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; The vector loop is executed exactly once for VF 4, so the induction increments
; and the canonical IV increment are all simplified away.
define void @fp_induction_tc_eq_4(ptr noalias %dst) {
; VF2-LABEL: 'fp_induction_tc_eq_4'
; VF2: Cost of 2 for VF 2: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 1 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 6 (Estimated cost per lane: 3)
;
; VF4-LABEL: 'fp_induction_tc_eq_4'
; VF4: Cost of 0 for VF 4: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = SCALAR-STEPS vp<[[VP4:%[0-9]+]]>, ir<1>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2:%[0-9]+]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 2 (Estimated cost per lane: 0.5)
;
entry:
br label %loop
loop:
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
%gep = getelementptr inbounds float, ptr %dst, i64 %iv
store float %fp.iv, ptr %gep, align 4
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 4
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; The loop is advanced by both an FP and a pointer induction. Neither induction
; is costed by the legacy cost model any more; the scalarized pointer induction
; is covered by its DERIVED-IV and SCALAR-STEPS recipes.
define void @fp_and_ptr_induction(ptr noalias %dst, ptr %end) {
; VF2-LABEL: 'fp_and_ptr_induction'
; VF2: Cost of 2 for VF 2: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: vp<[[VP7:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP6:%[0-9]+]]> * ir<4>
; VF2: Cost of 0 for VF 2: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP7]]>, ir<4>, vp<[[VP0]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<4>
; VF2: Cost of 1 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2]]> * ir<1.000000e+00>
; VF2: Cost for VF 2: 7 (Estimated cost per lane: 3.5)
;
; VF4-LABEL: 'fp_and_ptr_induction'
; VF4: Cost of 2 for VF 4: ir<%fp.iv> = WIDEN-INDUCTION fast ir<0.000000e+00>, ir<1.000000e+00>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: vp<[[VP7:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP6:%[0-9]+]]> * ir<4>
; VF4: Cost of 0 for VF 4: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP7]]>, ir<4>, vp<[[VP0]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<4>
; VF4: Cost of 1 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0.000000e+00> + vp<[[VP2]]> * ir<1.000000e+00>
; VF4: Cost for VF 4: 7 (Estimated cost per lane: 1.75)
;
entry:
br label %loop
loop:
%ptr.iv = phi ptr [ %dst, %entry ], [ %ptr.iv.next, %loop ]
%fp.iv = phi float [ 0.000000e+00, %entry ], [ %fp.iv.next, %loop ]
store float %fp.iv, ptr %ptr.iv, align 4
%fp.iv.next = fadd fast float %fp.iv, 1.000000e+00
%ptr.iv.next = getelementptr inbounds float, ptr %ptr.iv, i64 1
%ec = icmp eq ptr %ptr.iv.next, %end
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @fp_and_ptr_induction, but the loop is only advanced by a pointer
; induction. The canonical IV increment is still charged, even though the GEP
; incrementing the pointer induction is free in the scalar cost.
define void @ptr_induction_only(ptr %start, ptr %end) {
; VF2-LABEL: 'ptr_induction_only'
; VF2: Cost of 0 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5:%[0-9]+]]>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP2:%[0-9]+]]> * ir<1>
; VF2: Cost for VF 2: 6 (Estimated cost per lane: 3)
;
; VF4-LABEL: 'ptr_induction_only'
; VF4: Cost of 0 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5:%[0-9]+]]>, ir<1>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%start> + vp<[[VP2:%[0-9]+]]> * ir<1>
; VF4: Cost for VF 4: 6 (Estimated cost per lane: 1.5)
;
entry:
br label %loop
loop:
%ptr.iv = phi ptr [ %start, %entry ], [ %ptr.iv.next, %loop ]
%l = load i8, ptr %ptr.iv, align 1
%a = add i8 %l, 1
store i8 %a, ptr %ptr.iv, align 1
%ptr.iv.next = getelementptr inbounds i8, ptr %ptr.iv, i64 1
%ec = icmp eq ptr %ptr.iv.next, %end
br i1 %ec, label %exit, label %loop
exit:
ret void
}
define void @ptr_induction(ptr noalias %dst, ptr %end) {
; VF2-LABEL: 'ptr_induction'
; VF2: Cost of 1 for VF 2: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP5:%[0-9]+]]> * ir<8>
; VF2: Cost of 0 for VF 2: vp<[[VP7:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF2: Cost for VF 2: 5 (Estimated cost per lane: 2.5)
;
; VF4-LABEL: 'ptr_induction'
; VF4: Cost of 1 for VF 4: vp<[[VP6:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP5:%[0-9]+]]> * ir<8>
; VF4: Cost of 0 for VF 4: vp<[[VP7:%[0-9]+]]> = SCALAR-STEPS vp<[[VP6]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF4: Cost for VF 4: 5 (Estimated cost per lane: 1.25)
;
entry:
br label %loop
loop:
%ptr.iv = phi ptr [ %dst, %entry ], [ %ptr.iv.next, %loop ]
store i64 0, ptr %ptr.iv, align 8
%ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i64 1
%ec = icmp eq ptr %ptr.iv.next, %end
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Same as @ptr_induction, but the vector loop body executes at most once for
; VF 4, so there the canonical IV increment is simplified away and must not be
; costed.
define void @ptr_induction_tc_eq_vf(ptr noalias %dst) {
; VF2-LABEL: 'ptr_induction_tc_eq_vf'
; VF2: Cost of 1 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP4:%[0-9]+]]> * ir<8>
; VF2: Cost of 0 for VF 2: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 0 for VF 2: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF2: Cost for VF 2: 5 (Estimated cost per lane: 2.5)
;
; VF4-LABEL: 'ptr_induction_tc_eq_vf'
; VF4: Cost of 1 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP4:%[0-9]+]]> * ir<8>
; VF4: Cost of 0 for VF 4: vp<[[VP6:%[0-9]+]]> = SCALAR-STEPS vp<[[VP5]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 0 for VF 4: vp<[[VP3:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF4: Cost for VF 4: 3 (Estimated cost per lane: 0.75)
;
entry:
br label %loop
loop:
%ptr.iv = phi ptr [ %dst, %entry ], [ %ptr.iv.next, %loop ]
%iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
store i64 0, ptr %ptr.iv, align 8
%ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i64 1
%iv.next = add nuw nsw i64 %iv, 1
%ec = icmp eq i64 %iv.next, 4
br i1 %ec, label %exit, label %loop
exit:
ret void
}
; Test case where %ptr.iv remains a wide pointer induction, while %arr.iv is scalarized.
define void @ptr_induction_widened(ptr noalias %dst, ptr noalias %arr, ptr %end) {
; VF2-LABEL: 'ptr_induction_widened'
; VF2: Cost of 1 for VF 2: EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION ir<%dst>, ir<8>, vp<[[VP1:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: vp<[[VP7:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP6:%[0-9]+]]> * ir<8>
; VF2: Cost of 0 for VF 2: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP7]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF2: Cost of 1 for VF 2: canonical IV increment
; VF2: Cost of 0 for VF 2: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF2: Cost of 0 for VF 2: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<%arr> + vp<[[VP2]]> * ir<8>
; VF2: Cost for VF 2: 7 (Estimated cost per lane: 3.5)
;
; VF4-LABEL: 'ptr_induction_widened'
; VF4: Cost of 1 for VF 4: EMIT ir<%ptr.iv> = WIDEN-POINTER-INDUCTION ir<%dst>, ir<8>, vp<[[VP1:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: vp<[[VP7:%[0-9]+]]> = DERIVED-IV ir<0> + vp<[[VP6:%[0-9]+]]> * ir<8>
; VF4: Cost of 0 for VF 4: vp<[[VP8:%[0-9]+]]> = SCALAR-STEPS vp<[[VP7]]>, ir<8>, vp<[[VP0:%[0-9]+]]>
; VF4: Cost of 1 for VF 4: canonical IV increment
; VF4: Cost of 0 for VF 4: vp<[[VP4:%[0-9]+]]> = DERIVED-IV ir<%dst> + vp<[[VP2:%[0-9]+]]> * ir<8>
; VF4: Cost of 0 for VF 4: vp<[[VP5:%[0-9]+]]> = DERIVED-IV ir<%arr> + vp<[[VP2]]> * ir<8>
; VF4: Cost for VF 4: 7 (Estimated cost per lane: 1.75)
;
entry:
br label %loop
loop:
%ptr.iv = phi ptr [ %dst, %entry ], [ %ptr.iv.next, %loop ]
%arr.iv = phi ptr [ %arr, %entry ], [ %arr.iv.next, %loop ]
store ptr %ptr.iv, ptr %arr.iv, align 8
store i64 0, ptr %ptr.iv, align 8
%ptr.iv.next = getelementptr inbounds i64, ptr %ptr.iv, i64 1
%arr.iv.next = getelementptr inbounds ptr, ptr %arr.iv, i64 1
%ec = icmp eq ptr %ptr.iv.next, %end
br i1 %ec, label %exit, label %loop
exit:
ret void
}