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