1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=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_CONTINUE4:%.*]] ] 33; CHECK-NEXT: [[BROADCAST_SPLATINSERT1:%.*]] = insertelement <2 x i64> poison, i64 [[INDEX]], i32 0 34; CHECK-NEXT: [[BROADCAST_SPLAT2:%.*]] = shufflevector <2 x i64> [[BROADCAST_SPLATINSERT1]], <2 x i64> poison, <2 x i32> zeroinitializer 35; CHECK-NEXT: [[VEC_IV:%.*]] = add <2 x i64> [[BROADCAST_SPLAT2]], <i64 0, i64 1> 36; CHECK-NEXT: [[TMP3:%.*]] = icmp ule <2 x i64> [[VEC_IV]], [[BROADCAST_SPLAT]] 37; CHECK-NEXT: [[TMP4:%.*]] = extractelement <2 x i1> [[TMP3]], i32 0 38; CHECK-NEXT: br i1 [[TMP4]], label [[PRED_STORE_IF:%.*]], label [[PRED_STORE_CONTINUE:%.*]] 39; CHECK: pred.store.if: 40; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]], align 4 41; CHECK-NEXT: br label [[PRED_STORE_CONTINUE]] 42; CHECK: pred.store.continue: 43; CHECK-NEXT: [[TMP5:%.*]] = extractelement <2 x i1> [[TMP3]], i32 1 44; CHECK-NEXT: br i1 [[TMP5]], label [[PRED_STORE_IF3:%.*]], label [[PRED_STORE_CONTINUE4]] 45; CHECK: pred.store.if3: 46; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 47; CHECK-NEXT: br label [[PRED_STORE_CONTINUE4]] 48; CHECK: pred.store.continue4: 49; CHECK-NEXT: [[INDEX_NEXT]] = add i64 [[INDEX]], 2 50; CHECK-NEXT: [[TMP6:%.*]] = icmp eq i64 [[INDEX_NEXT]], [[N_VEC]] 51; CHECK-NEXT: br i1 [[TMP6]], label [[MIDDLE_BLOCK:%.*]], label [[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] 52; CHECK: middle.block: 53; CHECK-NEXT: br i1 true, label [[LOOP_EXIT:%.*]], label [[SCALAR_PH]] 54; CHECK: scalar.ph: 55; CHECK-NEXT: [[BC_RESUME_VAL:%.*]] = phi i64 [ [[IND_END]], [[MIDDLE_BLOCK]] ], [ 0, [[LOOP_PREHEADER]] ] 56; CHECK-NEXT: br label [[LOOP:%.*]] 57; CHECK: loop: 58; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ [[BC_RESUME_VAL]], [[SCALAR_PH]] ] 59; CHECK-NEXT: store i32 0, i32* [[PTR]], align 4 60; CHECK-NEXT: [[V2:%.*]] = trunc i64 [[IV]] to i8 61; CHECK-NEXT: [[V3:%.*]] = add i8 [[V2]], 1 62; CHECK-NEXT: [[CMP15:%.*]] = icmp slt i8 [[V3]], 5 63; CHECK-NEXT: [[IV_NEXT]] = add i64 [[IV]], [[INC]] 64; CHECK-NEXT: br i1 [[CMP15]], label [[LOOP]], label [[LOOP_EXIT]], !llvm.loop [[LOOP2:![0-9]+]] 65; CHECK: loop.exit: 66; CHECK-NEXT: [[DIV_1:%.*]] = udiv i64 [[Y]], [[ADD]] 67; CHECK-NEXT: [[V1:%.*]] = add i64 [[DIV_1]], 1 68; CHECK-NEXT: br label [[LOOP_2:%.*]] 69; CHECK: loop.2: 70; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ [[IV_NEXT_1:%.*]], [[LOOP_2]] ], [ 0, [[LOOP_EXIT]] ] 71; CHECK-NEXT: [[IV_NEXT_1]] = add i64 [[IV_1]], [[V1]] 72; CHECK-NEXT: call void @use(i64 [[IV_NEXT_1]]) 73; CHECK-NEXT: [[EC:%.*]] = icmp ult i64 [[IV_NEXT_1]], 200 74; CHECK-NEXT: br i1 [[EC]], label [[LOOP_2]], label [[LOOP_2_EXIT:%.*]] 75; CHECK: loop.2.exit: 76; CHECK-NEXT: [[C:%.*]] = call i1 @cond() 77; CHECK-NEXT: br i1 [[C]], label [[LOOP_PREHEADER]], label [[EXIT:%.*]] 78; CHECK: exit: 79; CHECK-NEXT: ret void 80; 81entry: 82 %conv19 = sext i16 %x to i64 83 %add = add i64 %conv19, 492802768830814067 84 br label %loop.preheader 85 86loop.preheader: 87 %div = udiv i64 %y, %add 88 %inc = add i64 %div, 1 89 br label %loop 90 91loop: 92 %iv = phi i64 [ %iv.next, %loop ], [ 0, %loop.preheader ] 93 store i32 0, i32* %ptr, align 4 94 %v2 = trunc i64 %iv to i8 95 %v3 = add i8 %v2, 1 96 %cmp15 = icmp slt i8 %v3, 5 97 %iv.next = add i64 %iv, %inc 98 br i1 %cmp15, label %loop, label %loop.exit 99 100loop.exit: 101 %div.1 = udiv i64 %y, %add 102 %v1 = add i64 %div.1, 1 103 br label %loop.2 104 105loop.2: 106 %iv.1 = phi i64 [ %iv.next.1, %loop.2 ], [ 0, %loop.exit ] 107 %iv.next.1 = add i64 %iv.1, %v1 108 call void @use(i64 %iv.next.1) 109 %ec = icmp ult i64 %iv.next.1, 200 110 br i1 %ec, label %loop.2, label %loop.2.exit 111 112loop.2.exit: 113 %c = call i1 @cond() 114 br i1 %c, label %loop.preheader, label %exit 115 116exit: 117 ret void 118} 119 120declare void @use(i64) 121declare i1 @cond() 122