1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -loop-vectorize -force-vector-width=2 -S -prefer-predicate-over-epilogue=predicate-dont-vectorize %s | FileCheck %s 3 4 5; Test case for PR46525. There are two candidates to pick for 6; `udiv i64 %y, %add` when expanding SCEV expressions. Make sure we pick %div, 7; which dominates the vector loop. 8 9define void @test(i16 %x, i64 %y, i32* %ptr) { 10; CHECK-LABEL: @test( 11; CHECK-NEXT: entry: 12; CHECK-NEXT: [[CONV19:%.*]] = sext i16 [[X:%.*]] to i64 13; CHECK-NEXT: [[ADD:%.*]] = add i64 [[CONV19]], 492802768830814067 14; CHECK-NEXT: br label [[LOOP_PREHEADER:%.*]] 15; CHECK: loop.preheader: 16; CHECK-NEXT: [[DIV:%.*]] = udiv i64 [[Y:%.*]], [[ADD]] 17; CHECK-NEXT: [[INC:%.*]] = add i64 [[DIV]], 1 18; CHECK-NEXT: [[TMP0:%.*]] = add nuw nsw i64 [[DIV]], 4 19; CHECK-NEXT: [[TMP1:%.*]] = udiv i64 [[TMP0]], [[INC]] 20; CHECK-NEXT: [[TMP2:%.*]] = add nuw nsw i64 [[TMP1]], 1 21; CHECK-NEXT: br i1 false, label [[SCALAR_PH:%.*]], label [[VECTOR_PH:%.*]] 22; CHECK: vector.ph: 23; CHECK-NEXT: [[N_RND_UP:%.*]] = add i64 [[TMP2]], 1 24; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i64 [[N_RND_UP]], 2 25; CHECK-NEXT: [[N_VEC:%.*]] = sub i64 [[N_RND_UP]], [[N_MOD_VF]] 26; CHECK-NEXT: [[IND_END:%.*]] = mul i64 [[N_VEC]], [[INC]] 27; CHECK-NEXT: [[TRIP_COUNT_MINUS_1:%.*]] = sub i64 [[TMP2]], 1 28; CHECK-NEXT: [[BROADCAST_SPLATINSERT:%.*]] = insertelement <2 x i64> poison, i64 [[TRIP_COUNT_MINUS_1]], i32 0 29; CHECK-NEXT: [[BROADCAST_SPLAT:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT]], <2 x i64> poison, <2 x i32> zeroinitializer 30; CHECK-NEXT: br label [[VECTOR_BODY:%.*]] 31; CHECK: vector.body: 32; CHECK-NEXT: [[INDEX:%.*]] = phi i64 [ 0, [[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], [[PRED_STORE_CONTINUE12:%.*]] ] 33; CHECK-NEXT: [[OFFSET_IDX:%.*]] = mul i64 [[INDEX]], [[INC]] 34; CHECK-NEXT: [[TMP4:%.*]] = mul i64 0, [[INC]] 35; CHECK-NEXT: [[TMP5:%.*]] = add i64 [[OFFSET_IDX]], [[TMP4]] 36; CHECK-NEXT: [[OFFSET_IDX3:%.*]] = mul i64 [[INDEX]], [[INC]] 37; CHECK-NEXT: [[TMP6:%.*]] = trunc i64 [[OFFSET_IDX3]] to i8 38; CHECK-NEXT: [[TMP7:%.*]] = trunc i64 [[INC]] to i8 39; CHECK-NEXT: [[TMP9:%.*]] = mul i8 0, [[TMP7]] 40; CHECK-NEXT: [[TMP10:%.*]] = add i8 [[TMP6]], [[TMP9]] 41; CHECK-NEXT: [[BROADCAST_SPLATINSERT9:%.*]] = insertelement <2 x i64> poison, i64 [[INDEX]], i32 0 42; CHECK-NEXT: [[BROADCAST_SPLAT10:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT9]], <2 x i64> poison, <2 x i32> zeroinitializer 43; CHECK-NEXT: [[VEC_IV:%.*]] = add <2 x i64> [[BROADCAST_SPLAT10]], <i64 0, i64 1> 44; CHECK-NEXT: [[TMP11:%.*]] = icmp ule <2 x i64> [[VEC_IV]], [[BROADCAST_SPLAT]] 45; CHECK-NEXT: [[TMP12:%.*]] = extractelement <2 x i1> [[TMP11]], i32 0 46; CHECK-NEXT: br i1 [[TMP12]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] 47; CHECK: pred.store.if: 48; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]], align 4 49; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] 50; CHECK: pred.store.continue: 51; CHECK-NEXT: [[TMP13:%.*]] = extractelement <2 x i1> [[TMP11]], i32 1 52; CHECK-NEXT: br i1 [[TMP13]], label [[PRED_STORE_IF11:%.*]], label [[PRED_STORE_CONTINUE12]] 53; CHECK: pred.store.if4: 54; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 55; CHECK-NEXT: br label [[PRED_STORE_CONTINUE12]] 56; CHECK: pred.store.continue5: 57; CHECK-NEXT: [[TMP14:%.*]] = add i8 [[TMP10]], 1 58; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 2 59; CHECK-NEXT: [[TMP15:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 60; CHECK-NEXT: br i1 [[TMP15]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 61; CHECK: middle.block: 62; CHECK-NEXT: br i1 true, label [[LOOP_EXIT:%.*]], label [[SCALAR_PH]] 63; CHECK: scalar.ph: 64; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_PREHEADER]] ] 65; CHECK-NEXT: br label [[LOOP:%.*]] 66; CHECK: loop: 67; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 68; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 69; CHECK-NEXT: [[V2:%.*]] = trunc i64 [[IV]] to i8 70; CHECK-NEXT: [[V3:%.*]] = add i8 [[V2]], 1 71; CHECK-NEXT: [[CMP15:%.*]] = icmp slt i8 [[V3]], 5 72; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], [[INC]] 73; CHECK-NEXT: br i1 [[CMP15]], label [[LOOP]], label [[LOOP_EXIT]], !llvm.loop [[LOOP2:![0-9]+]] 74; CHECK: loop.exit: 75; CHECK-NEXT: [[DIV_1:%.*]] = udiv i64 [[Y]], [[ADD]] 76; CHECK-NEXT: [[V1:%.*]] = add i64 [[DIV_1]], 1 77; CHECK-NEXT: br label [[LOOP_2:%.*]] 78; CHECK: loop.2: 79; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ [[IV_NEXT_1:%.*]], [[LOOP_2]] ], [ 0, [[LOOP_EXIT]] ] 80; CHECK-NEXT: [[IV_NEXT_1]] = add i64 [[IV_1]], [[V1]] 81; CHECK-NEXT: call void @use(i64 [[IV_NEXT_1]]) 82; CHECK-NEXT: [[EC:%.*]] = icmp ult i64 [[IV_NEXT_1]], 200 83; CHECK-NEXT: br i1 [[EC]], label [[LOOP_2]], label [[LOOP_2_EXIT:%.*]] 84; CHECK: loop.2.exit: 85; CHECK-NEXT: [[C:%.*]] = call i1 @cond() 86; CHECK-NEXT: br i1 [[C]], label [[LOOP_PREHEADER]], label [[EXIT:%.*]] 87; CHECK: exit: 88; CHECK-NEXT: ret void 89; 90entry: 91 %conv19 = sext i16 %x to i64 92 %add = add i64 %conv19, 492802768830814067 93 br label %loop.preheader 94 95loop.preheader: 96 %div = udiv i64 %y, %add 97 %inc = add i64 %div, 1 98 br label %loop 99 100loop: 101 %iv = phi i64 [ %iv.next, %loop ], [ 0, %loop.preheader ] 102 store i32 0, i32* %ptr, align 4 103 %v2 = trunc i64 %iv to i8 104 %v3 = add i8 %v2, 1 105 %cmp15 = icmp slt i8 %v3, 5 106 %iv.next = add i64 %iv, %inc 107 br i1 %cmp15, label %loop, label %loop.exit 108 109loop.exit: 110 %div.1 = udiv i64 %y, %add 111 %v1 = add i64 %div.1, 1 112 br label %loop.2 113 114loop.2: 115 %iv.1 = phi i64 [ %iv.next.1, %loop.2 ], [ 0, %loop.exit ] 116 %iv.next.1 = add i64 %iv.1, %v1 117 call void @use(i64 %iv.next.1) 118 %ec = icmp ult i64 %iv.next.1, 200 119 br i1 %ec, label %loop.2, label %loop.2.exit 120 121loop.2.exit: 122 %c = call i1 @cond() 123 br i1 %c, label %loop.preheader, label %exit 124 125exit: 126 ret void 127} 128 129declare void @use(i64) 130declare i1 @cond() 131