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