1; REQUIRES: asserts
2
3; RUN: opt -loop-vectorize -mtriple=arm64-apple-ios %s -S -debug -disable-output 2>&1 | FileCheck --check-prefix=CM %s
4; RUN: opt -loop-vectorize -force-vector-width=2 -force-vector-interleave=1 %s -S | FileCheck --check-prefix=FORCED %s
5
6; Test case from PR41294.
7
8; Check scalar cost for extractvalue. The constant and loop invariant operands are free,
9; leaving cost 3 for scalarizing the result + 2 for executing the op with VF 2.
10
11; CM: LV: Scalar loop costs: 5.
12; CM: LV: Found an estimated cost of 0 for VF 2 For instruction:   %a = extractvalue { i64, i64 } %sv, 0
13; CM-NEXT: LV: Found an estimated cost of 0 for VF 2 For instruction:   %b = extractvalue { i64, i64 } %sv, 1
14
15; Check that the extractvalue operands are actually free in vector code.
16
17; FORCED-LABEL: vector.body:                                      ; preds = %vector.body, %vector.ph
18; FORCED-NEXT:    %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
19; FORCED-NEXT:    %0 = add i32 %index, 0
20; FORCED-NEXT:    %1 = extractvalue { i64, i64 } %sv, 0
21; FORCED-NEXT:    %2 = extractvalue { i64, i64 } %sv, 0
22; FORCED-NEXT:    %3 = insertelement <2 x i64> poison, i64 %1, i32 0
23; FORCED-NEXT:    %4 = insertelement <2 x i64> %3, i64 %2, i32 1
24; FORCED-NEXT:    %5 = extractvalue { i64, i64 } %sv, 1
25; FORCED-NEXT:    %6 = extractvalue { i64, i64 } %sv, 1
26; FORCED-NEXT:    %7 = insertelement <2 x i64> poison, i64 %5, i32 0
27; FORCED-NEXT:    %8 = insertelement <2 x i64> %7, i64 %6, i32 1
28; FORCED-NEXT:    %9 = getelementptr i64, i64* %dst, i32 %0
29; FORCED-NEXT:    %10 = add <2 x i64> %4, %8
30; FORCED-NEXT:    %11 = getelementptr i64, i64* %9, i32 0
31; FORCED-NEXT:    %12 = bitcast i64* %11 to <2 x i64>*
32; FORCED-NEXT:    store <2 x i64> %10, <2 x i64>* %12, align 4
33; FORCED-NEXT:    %index.next = add nuw i32 %index, 2
34; FORCED-NEXT:    %13 = icmp eq i32 %index.next, 0
35; FORCED-NEXT:    br i1 %13, label %middle.block, label %vector.body, !llvm.loop !0
36
37define void @test1(i64* %dst, {i64, i64} %sv) {
38entry:
39  br label %loop.body
40
41loop.body:
42  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.body ]
43  %a = extractvalue { i64, i64 } %sv, 0
44  %b = extractvalue { i64, i64 } %sv, 1
45  %addr = getelementptr i64, i64* %dst, i32 %iv
46  %add = add i64 %a, %b
47  store i64 %add, i64* %addr
48  %iv.next = add nsw i32 %iv, 1
49  %cond = icmp ne i32 %iv.next, 0
50  br i1 %cond, label %loop.body, label %exit
51
52exit:
53  ret void
54}
55
56
57; Similar to the test case above, but checks getVectorCallCost as well.
58declare float @pow(float, float) readnone nounwind
59
60; CM: LV: Scalar loop costs: 14.
61; CM: LV: Found an estimated cost of 0 for VF 2 For instruction:   %a = extractvalue { float, float } %sv, 0
62; CM-NEXT: LV: Found an estimated cost of 0 for VF 2 For instruction:   %b = extractvalue { float, float } %sv, 1
63
64; FORCED-LABEL: define void @test_getVectorCallCost
65
66; FORCED-LABEL: vector.body:                                      ; preds = %vector.body, %vector.ph
67; FORCED-NEXT:    %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ]
68; FORCED-NEXT:    %0 = add i32 %index, 0
69; FORCED-NEXT:    %1 = extractvalue { float, float } %sv, 0
70; FORCED-NEXT:    %2 = extractvalue { float, float } %sv, 0
71; FORCED-NEXT:    %3 = insertelement <2 x float> poison, float %1, i32 0
72; FORCED-NEXT:    %4 = insertelement <2 x float> %3, float %2, i32 1
73; FORCED-NEXT:    %5 = extractvalue { float, float } %sv, 1
74; FORCED-NEXT:    %6 = extractvalue { float, float } %sv, 1
75; FORCED-NEXT:    %7 = insertelement <2 x float> poison, float %5, i32 0
76; FORCED-NEXT:    %8 = insertelement <2 x float> %7, float %6, i32 1
77; FORCED-NEXT:    %9 = getelementptr float, float* %dst, i32 %0
78; FORCED-NEXT:    %10 = call <2 x float> @llvm.pow.v2f32(<2 x float> %4, <2 x float> %8)
79; FORCED-NEXT:    %11 = getelementptr float, float* %9, i32 0
80; FORCED-NEXT:    %12 = bitcast float* %11 to <2 x float>*
81; FORCED-NEXT:    store <2 x float> %10, <2 x float>* %12, align 4
82; FORCED-NEXT:    %index.next = add nuw i32 %index, 2
83; FORCED-NEXT:    %13 = icmp eq i32 %index.next, 0
84; FORCED-NEXT:    br i1 %13, label %middle.block, label %vector.body, !llvm.loop !4
85
86define void @test_getVectorCallCost(float* %dst, {float, float} %sv) {
87entry:
88  br label %loop.body
89
90loop.body:
91  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop.body ]
92  %a = extractvalue { float, float } %sv, 0
93  %b = extractvalue { float, float } %sv, 1
94  %addr = getelementptr float, float* %dst, i32 %iv
95  %p = call float @pow(float %a, float %b)
96  store float %p, float* %addr
97  %iv.next = add nsw i32 %iv, 1
98  %cond = icmp ne i32 %iv.next, 0
99  br i1 %cond, label %loop.body, label %exit
100
101exit:
102  ret void
103}
104