1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -loop-vectorize -mtriple=x86_64-apple-darwin %s | FileCheck %s
3
4; Two mostly identical functions. The only difference is the presence of
5; fast-math flags on the second. The loop is a pretty simple reduction:
6
7; for (int i = 0; i < 32; ++i)
8;   if (arr[i] != 42)
9;     tot += arr[i];
10
11define double @sumIfScalar(double* nocapture readonly %arr) {
12; CHECK-LABEL: @sumIfScalar(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    br label [[LOOP:%.*]]
15; CHECK:       loop:
16; CHECK-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_NEXT:%.*]], [[NEXT_ITER:%.*]] ]
17; CHECK-NEXT:    [[TOT:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TOT_NEXT:%.*]], [[NEXT_ITER]] ]
18; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr double, double* [[ARR:%.*]], i32 [[I]]
19; CHECK-NEXT:    [[NEXTVAL:%.*]] = load double, double* [[ADDR]]
20; CHECK-NEXT:    [[TST:%.*]] = fcmp une double [[NEXTVAL]], 4.200000e+01
21; CHECK-NEXT:    br i1 [[TST]], label [[DO_ADD:%.*]], label [[NO_ADD:%.*]]
22; CHECK:       do.add:
23; CHECK-NEXT:    [[TOT_NEW:%.*]] = fadd double [[TOT]], [[NEXTVAL]]
24; CHECK-NEXT:    br label [[NEXT_ITER]]
25; CHECK:       no.add:
26; CHECK-NEXT:    br label [[NEXT_ITER]]
27; CHECK:       next.iter:
28; CHECK-NEXT:    [[TOT_NEXT]] = phi double [ [[TOT]], [[NO_ADD]] ], [ [[TOT_NEW]], [[DO_ADD]] ]
29; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
30; CHECK-NEXT:    [[AGAIN:%.*]] = icmp ult i32 [[I_NEXT]], 32
31; CHECK-NEXT:    br i1 [[AGAIN]], label [[LOOP]], label [[DONE:%.*]]
32; CHECK:       done:
33; CHECK-NEXT:    [[TOT_NEXT_LCSSA:%.*]] = phi double [ [[TOT_NEXT]], [[NEXT_ITER]] ]
34; CHECK-NEXT:    ret double [[TOT_NEXT_LCSSA]]
35;
36entry:
37  br label %loop
38
39loop:
40  %i = phi i32 [0, %entry], [%i.next, %next.iter]
41  %tot = phi double [0.0, %entry], [%tot.next, %next.iter]
42
43  %addr = getelementptr double, double* %arr, i32 %i
44  %nextval = load double, double* %addr
45
46  %tst = fcmp une double %nextval, 42.0
47  br i1 %tst, label %do.add, label %no.add
48
49do.add:
50  %tot.new = fadd double %tot, %nextval
51  br label %next.iter
52
53no.add:
54  br label %next.iter
55
56next.iter:
57  %tot.next = phi double [%tot, %no.add], [%tot.new, %do.add]
58  %i.next = add i32 %i, 1
59  %again = icmp ult i32 %i.next, 32
60  br i1 %again, label %loop, label %done
61
62done:
63  ret double %tot.next
64}
65
66define double @sumIfVector(double* nocapture readonly %arr) {
67; CHECK-LABEL: @sumIfVector(
68; CHECK-NEXT:  entry:
69; CHECK-NEXT:    br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]]
70; CHECK:       vector.ph:
71; CHECK-NEXT:    br label [[VECTOR_BODY:%.*]]
72; CHECK:       vector.body:
73; CHECK-NEXT:    [[INDEX:%.*]] = phi i32 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[VECTOR_BODY]] ]
74; CHECK-NEXT:    [[VEC_PHI:%.*]] = phi <2 x double> [ zeroinitializer, [[VECTOR_PH]] ], [ [[PREDPHI:%.*]], [[VECTOR_BODY]] ]
75; CHECK-NEXT:    [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i32> undef, i32 [[INDEX]], i32 0
76; CHECK-NEXT:    [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i32> [[BROADCAST_SPLATINSERT]], <2 x i32> undef, <2 x i32> zeroinitializer
77; CHECK-NEXT:    [[INDUCTION:%.*]] = add <2 x i32> [[BROADCAST_SPLAT]], <i32 0, i32 1>
78; CHECK-NEXT:    [[TMP0:%.*]] = add i32 [[INDEX]], 0
79; CHECK-NEXT:    [[TMP1:%.*]] = getelementptr double, double* [[ARR:%.*]], i32 [[TMP0]]
80; CHECK-NEXT:    [[TMP2:%.*]] = getelementptr double, double* [[TMP1]], i32 0
81; CHECK-NEXT:    [[TMP3:%.*]] = bitcast double* [[TMP2]] to <2 x double>*
82; CHECK-NEXT:    [[WIDE_LOAD:%.*]] = load <2 x double>, <2 x double>* [[TMP3]], align 8
83; CHECK-NEXT:    [[TMP4:%.*]] = fcmp fast une <2 x double> [[WIDE_LOAD]], <double 4.200000e+01, double 4.200000e+01>
84; CHECK-NEXT:    [[TMP5:%.*]] = fadd fast <2 x double> [[VEC_PHI]], [[WIDE_LOAD]]
85; CHECK-NEXT:    [[TMP6:%.*]] = xor <2 x i1> [[TMP4]], <i1 true, i1 true>
86; CHECK-NEXT:    [[PREDPHI]] = select <2 x i1> [[TMP4]], <2 x double> [[TMP5]], <2 x double> [[VEC_PHI]]
87; CHECK-NEXT:    [[INDEX_NEXT]] = add i32 [[INDEX]], 2
88; CHECK-NEXT:    [[TMP7:%.*]] = icmp eq i32 [[INDEX_NEXT]], 32
89; CHECK-NEXT:    br i1 [[TMP7]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop !0
90; CHECK:       middle.block:
91; CHECK-NEXT:    [[RDX_SHUF:%.*]] = shufflevector <2 x double> [[PREDPHI]], <2 x double> undef, <2 x i32> <i32 1, i32 undef>
92; CHECK-NEXT:    [[BIN_RDX:%.*]] = fadd fast <2 x double> [[PREDPHI]], [[RDX_SHUF]]
93; CHECK-NEXT:    [[TMP8:%.*]] = extractelement <2 x double> [[BIN_RDX]], i32 0
94; CHECK-NEXT:    [[CMP_N:%.*]] = icmp eq i32 32, 32
95; CHECK-NEXT:    br i1 [[CMP_N]], label [[DONE:%.*]], label [[SCALAR_PH]]
96; CHECK:       scalar.ph:
97; CHECK-NEXT:    [[BC_RESUME_VAL:%.*]] = phi i32 [ 32, [[MIDDLE_BLOCK]] ], [ 0, [[ENTRY:%.*]] ]
98; CHECK-NEXT:    [[BC_MERGE_RDX:%.*]] = phi double [ 0.000000e+00, [[ENTRY]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ]
99; CHECK-NEXT:    br label [[LOOP:%.*]]
100; CHECK:       loop:
101; CHECK-NEXT:    [[I:%.*]] = phi i32 [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ], [ [[I_NEXT:%.*]], [[NEXT_ITER:%.*]] ]
102; CHECK-NEXT:    [[TOT:%.*]] = phi double [ [[BC_MERGE_RDX]], [[SCALAR_PH]] ], [ [[TOT_NEXT:%.*]], [[NEXT_ITER]] ]
103; CHECK-NEXT:    [[ADDR:%.*]] = getelementptr double, double* [[ARR]], i32 [[I]]
104; CHECK-NEXT:    [[NEXTVAL:%.*]] = load double, double* [[ADDR]]
105; CHECK-NEXT:    [[TST:%.*]] = fcmp fast une double [[NEXTVAL]], 4.200000e+01
106; CHECK-NEXT:    br i1 [[TST]], label [[DO_ADD:%.*]], label [[NO_ADD:%.*]]
107; CHECK:       do.add:
108; CHECK-NEXT:    [[TOT_NEW:%.*]] = fadd fast double [[TOT]], [[NEXTVAL]]
109; CHECK-NEXT:    br label [[NEXT_ITER]]
110; CHECK:       no.add:
111; CHECK-NEXT:    br label [[NEXT_ITER]]
112; CHECK:       next.iter:
113; CHECK-NEXT:    [[TOT_NEXT]] = phi double [ [[TOT]], [[NO_ADD]] ], [ [[TOT_NEW]], [[DO_ADD]] ]
114; CHECK-NEXT:    [[I_NEXT]] = add i32 [[I]], 1
115; CHECK-NEXT:    [[AGAIN:%.*]] = icmp ult i32 [[I_NEXT]], 32
116; CHECK-NEXT:    br i1 [[AGAIN]], label [[LOOP]], label [[DONE]], !llvm.loop !2
117; CHECK:       done:
118; CHECK-NEXT:    [[TOT_NEXT_LCSSA:%.*]] = phi double [ [[TOT_NEXT]], [[NEXT_ITER]] ], [ [[TMP8]], [[MIDDLE_BLOCK]] ]
119; CHECK-NEXT:    ret double [[TOT_NEXT_LCSSA]]
120;
121entry:
122  br label %loop
123
124loop:
125  %i = phi i32 [0, %entry], [%i.next, %next.iter]
126  %tot = phi double [0.0, %entry], [%tot.next, %next.iter]
127
128  %addr = getelementptr double, double* %arr, i32 %i
129  %nextval = load double, double* %addr
130
131  %tst = fcmp fast une double %nextval, 42.0
132  br i1 %tst, label %do.add, label %no.add
133
134do.add:
135  %tot.new = fadd fast double %tot, %nextval
136  br label %next.iter
137
138no.add:
139  br label %next.iter
140
141next.iter:
142  %tot.next = phi double [%tot, %no.add], [%tot.new, %do.add]
143  %i.next = add i32 %i, 1
144  %again = icmp ult i32 %i.next, 32
145  br i1 %again, label %loop, label %done
146
147done:
148  ret double %tot.next
149}
150
151