| ; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter-out-after "middle.block:" --version 6 | |
| ; RUN: opt -passes=loop-vectorize -force-vector-width=2 -force-vector-interleave=1 -disable-output -vplan-print-before=makeCallWideningDecisions %s 2>&1 | FileCheck --strict-whitespace %s | |
| declare i64 @bar(i64) | |
| declare <2 x i64> @vec_bar(<2 x i64>) | |
| declare i64 @"quoted name"(i64) | |
| declare <2 x i64> @vec_quoted(<2 x i64>) | |
| ; Call with return, argument and function attributes at the call site. | |
| define void @call_site_attrs(ptr noalias %in.ptr, ptr noalias %out.ptr) { | |
| ; CHECK-LABEL: VPlan for loop in 'call_site_attrs' | |
| ; CHECK: VPlan ' for UF>=1' { | |
| ; CHECK-NEXT: Live-in vp<[[VP0:%[0-9]+]]> = VF | |
| ; CHECK-NEXT: Live-in vp<[[VP1:%[0-9]+]]> = VF * UF | |
| ; CHECK-NEXT: Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count | |
| ; CHECK-NEXT: Live-in ir<1000> = original trip-count | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: ir-bb<entry>: | |
| ; CHECK-NEXT: Successor(s): scalar.ph, vector.ph | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.ph: | |
| ; CHECK-NEXT: Successor(s): vector loop | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: <x1> vector loop: { | |
| ; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.body: | |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0]]> | |
| ; CHECK-NEXT: CLONE ir<%in.gep> = getelementptr inbounds ir<%in.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP4:%[0-9]+]]> = vector-pointer inbounds i64, ir<%in.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN ir<%in> = load vp<[[VP4]]> | |
| ; CHECK-NEXT: EMIT ir<%call> = call noundef range(i64 0, 100) i64 @bar(noundef range(i64 0, 80) ir<%in>) nounwind memory(none) "vector-function-abi-variant"="_ZGVnN2v_bar(vec_bar)" | |
| ; CHECK-NEXT: CLONE ir<%out.gep> = getelementptr inbounds ir<%out.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP5:%[0-9]+]]> = vector-pointer inbounds i64, ir<%out.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN store vp<[[VP5]]>, ir<%call> | |
| ; CHECK-NEXT: CLONE ir<%iv.next> = add nuw nsw ir<%iv>, ir<1> | |
| ; CHECK-NEXT: CLONE ir<%exitcond> = icmp eq ir<%iv.next>, ir<1000> | |
| ; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1]]> | |
| ; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2]]> | |
| ; CHECK-NEXT: No successors | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: Successor(s): middle.block | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: middle.block: | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] | |
| %in.gep = getelementptr inbounds i64, ptr %in.ptr, i64 %iv | |
| %in = load i64, ptr %in.gep, align 8 | |
| %call = call range(i64 0, 100) noundef i64 @bar(i64 range(i64 0, 80) noundef %in) #0 | |
| %out.gep = getelementptr inbounds i64, ptr %out.ptr, i64 %iv | |
| store i64 %call, ptr %out.gep, align 8 | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %exitcond = icmp eq i64 %iv.next, 1000 | |
| br i1 %exitcond, label %exit, label %loop | |
| exit: | |
| ret void | |
| } | |
| ; Conditional call, the call VPInstruction gets a mask operand. | |
| define void @masked_call_site_attrs(ptr noalias %in.ptr, ptr noalias %out.ptr) { | |
| ; CHECK-LABEL: VPlan for loop in 'masked_call_site_attrs' | |
| ; CHECK: VPlan ' for UF>=1' { | |
| ; CHECK-NEXT: Live-in vp<[[VP0:%[0-9]+]]> = VF | |
| ; CHECK-NEXT: Live-in vp<[[VP1:%[0-9]+]]> = VF * UF | |
| ; CHECK-NEXT: Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count | |
| ; CHECK-NEXT: Live-in ir<1000> = original trip-count | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: ir-bb<entry>: | |
| ; CHECK-NEXT: Successor(s): scalar.ph, vector.ph | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.ph: | |
| ; CHECK-NEXT: Successor(s): vector loop | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: <x1> vector loop: { | |
| ; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.body: | |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0]]> | |
| ; CHECK-NEXT: CLONE ir<%in.gep> = getelementptr inbounds ir<%in.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP4:%[0-9]+]]> = vector-pointer inbounds i64, ir<%in.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN ir<%in> = load vp<[[VP4]]> | |
| ; CHECK-NEXT: EMIT ir<%cmp> = icmp ugt ir<%in>, ir<50> | |
| ; CHECK-NEXT: Successor(s): then | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: then: | |
| ; CHECK-NEXT: EMIT ir<%call> = call noundef i64 @bar(noundef ir<%in>) nounwind memory(none) "vector-function-abi-variant"="_ZGVnN2v_bar(vec_bar)", ir<%cmp> (!vplan.execution.frequency 9223372036854775807 (50%, estimated)) | |
| ; CHECK-NEXT: EMIT ir<%out.gep> = getelementptr inbounds ir<%out.ptr>, ir<%iv> | |
| ; CHECK-NEXT: REPLICATE store ir<%call>, ir<%out.gep>, ir<%cmp> (!vplan.execution.frequency 9223372036854775807 (50%, estimated)) | |
| ; CHECK-NEXT: Successor(s): latch | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: latch: | |
| ; CHECK-NEXT: CLONE ir<%iv.next> = add nuw nsw ir<%iv>, ir<1> | |
| ; CHECK-NEXT: CLONE ir<%exitcond> = icmp eq ir<%iv.next>, ir<1000> | |
| ; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1]]> | |
| ; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2]]> | |
| ; CHECK-NEXT: No successors | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: Successor(s): middle.block | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: middle.block: | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ] | |
| %in.gep = getelementptr inbounds i64, ptr %in.ptr, i64 %iv | |
| %in = load i64, ptr %in.gep, align 8 | |
| %cmp = icmp ugt i64 %in, 50 | |
| br i1 %cmp, label %then, label %latch | |
| then: | |
| %call = call noundef i64 @bar(i64 noundef %in) #0 | |
| %out.gep = getelementptr inbounds i64, ptr %out.ptr, i64 %iv | |
| store i64 %call, ptr %out.gep, align 8 | |
| br label %latch | |
| latch: | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %exitcond = icmp eq i64 %iv.next, 1000 | |
| br i1 %exitcond, label %exit, label %loop | |
| exit: | |
| ret void | |
| } | |
| ; Call with memory attributes at the call site. | |
| define void @call_site_memory_attrs(ptr noalias %in.ptr, ptr noalias %out.ptr) { | |
| ; CHECK-LABEL: VPlan for loop in 'call_site_memory_attrs' | |
| ; CHECK: VPlan ' for UF>=1' { | |
| ; CHECK-NEXT: Live-in vp<[[VP0:%[0-9]+]]> = VF | |
| ; CHECK-NEXT: Live-in vp<[[VP1:%[0-9]+]]> = VF * UF | |
| ; CHECK-NEXT: Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count | |
| ; CHECK-NEXT: Live-in ir<1000> = original trip-count | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: ir-bb<entry>: | |
| ; CHECK-NEXT: Successor(s): scalar.ph, vector.ph | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.ph: | |
| ; CHECK-NEXT: Successor(s): vector loop | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: <x1> vector loop: { | |
| ; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.body: | |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0]]> | |
| ; CHECK-NEXT: CLONE ir<%in.gep> = getelementptr inbounds ir<%in.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP4:%[0-9]+]]> = vector-pointer inbounds i64, ir<%in.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN ir<%in> = load vp<[[VP4]]> | |
| ; CHECK-NEXT: EMIT ir<%call> = call i64 @bar(ir<%in>) nounwind memory(read) "vector-function-abi-variant"="_ZGVnN2v_bar(vec_bar)" | |
| ; CHECK-NEXT: CLONE ir<%out.gep> = getelementptr inbounds ir<%out.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP5:%[0-9]+]]> = vector-pointer inbounds i64, ir<%out.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN store vp<[[VP5]]>, ir<%call> | |
| ; CHECK-NEXT: CLONE ir<%iv.next> = add nuw nsw ir<%iv>, ir<1> | |
| ; CHECK-NEXT: CLONE ir<%exitcond> = icmp eq ir<%iv.next>, ir<1000> | |
| ; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1]]> | |
| ; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2]]> | |
| ; CHECK-NEXT: No successors | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: Successor(s): middle.block | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: middle.block: | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] | |
| %in.gep = getelementptr inbounds i64, ptr %in.ptr, i64 %iv | |
| %in = load i64, ptr %in.gep, align 8 | |
| %call = call i64 @bar(i64 %in) #1 | |
| %out.gep = getelementptr inbounds i64, ptr %out.ptr, i64 %iv | |
| store i64 %call, ptr %out.gep, align 8 | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %exitcond = icmp eq i64 %iv.next, 1000 | |
| br i1 %exitcond, label %exit, label %loop | |
| exit: | |
| ret void | |
| } | |
| ; Callee name that needs quoting. | |
| define void @call_quoted_name(ptr noalias %in.ptr, ptr noalias %out.ptr) { | |
| ; CHECK-LABEL: VPlan for loop in 'call_quoted_name' | |
| ; CHECK: VPlan ' for UF>=1' { | |
| ; CHECK-NEXT: Live-in vp<[[VP0:%[0-9]+]]> = VF | |
| ; CHECK-NEXT: Live-in vp<[[VP1:%[0-9]+]]> = VF * UF | |
| ; CHECK-NEXT: Live-in vp<[[VP2:%[0-9]+]]> = vector-trip-count | |
| ; CHECK-NEXT: Live-in ir<1000> = original trip-count | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: ir-bb<entry>: | |
| ; CHECK-NEXT: Successor(s): scalar.ph, vector.ph | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.ph: | |
| ; CHECK-NEXT: Successor(s): vector loop | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: <x1> vector loop: { | |
| ; CHECK-NEXT: vp<[[VP3:%[0-9]+]]> = CANONICAL-IV | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: vector.body: | |
| ; CHECK-NEXT: ir<%iv> = WIDEN-INDUCTION nuw nsw ir<0>, ir<1>, vp<[[VP0]]> | |
| ; CHECK-NEXT: CLONE ir<%in.gep> = getelementptr inbounds ir<%in.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP4:%[0-9]+]]> = vector-pointer inbounds i64, ir<%in.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN ir<%in> = load vp<[[VP4]]> | |
| ; CHECK-NEXT: EMIT ir<%call> = call i64 @"quoted name"(ir<%in>) nounwind memory(none) "vector-function-abi-variant"="_ZGVnN2v_quoted name(vec_quoted)" | |
| ; CHECK-NEXT: CLONE ir<%out.gep> = getelementptr inbounds ir<%out.ptr>, ir<%iv> | |
| ; CHECK-NEXT: vp<[[VP5:%[0-9]+]]> = vector-pointer inbounds i64, ir<%out.gep>, ir<1> | |
| ; CHECK-NEXT: WIDEN store vp<[[VP5]]>, ir<%call> | |
| ; CHECK-NEXT: CLONE ir<%iv.next> = add nuw nsw ir<%iv>, ir<1> | |
| ; CHECK-NEXT: CLONE ir<%exitcond> = icmp eq ir<%iv.next>, ir<1000> | |
| ; CHECK-NEXT: EMIT vp<%index.next> = add nuw vp<[[VP3]]>, vp<[[VP1]]> | |
| ; CHECK-NEXT: EMIT branch-on-count vp<%index.next>, vp<[[VP2]]> | |
| ; CHECK-NEXT: No successors | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: Successor(s): middle.block | |
| ; CHECK-EMPTY: | |
| ; CHECK-NEXT: middle.block: | |
| ; | |
| entry: | |
| br label %loop | |
| loop: | |
| %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ] | |
| %in.gep = getelementptr inbounds i64, ptr %in.ptr, i64 %iv | |
| %in = load i64, ptr %in.gep, align 8 | |
| %call = call i64 @"quoted name"(i64 %in) #2 | |
| %out.gep = getelementptr inbounds i64, ptr %out.ptr, i64 %iv | |
| store i64 %call, ptr %out.gep, align 8 | |
| %iv.next = add nuw nsw i64 %iv, 1 | |
| %exitcond = icmp eq i64 %iv.next, 1000 | |
| br i1 %exitcond, label %exit, label %loop | |
| exit: | |
| ret void | |
| } | |
| attributes #0 = { nounwind memory(none) "vector-function-abi-variant"="_ZGVnN2v_bar(vec_bar)" } | |
| attributes #1 = { nounwind memory(read) "vector-function-abi-variant"="_ZGVnN2v_bar(vec_bar)" } | |
| attributes #2 = { nounwind memory(none) "vector-function-abi-variant"="_ZGVnN2v_quoted name(vec_quoted)" } |