| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --filter-out-after "scalar.ph:" --version 6 |
| ; RUN: opt -passes='loop-vectorize' -force-vector-width=4 -S < %s | FileCheck %s |
| |
| ; This checks we don't crash when the inner loop we're trying to vectorize |
| ; is a SCEV AddRec with respect to an outer loop. |
| |
| ; In this case, the problematic PHI is: |
| ; %0 = phi i32 [ poison, %for.cond1.preheader ], [ %inc54, %for.body3 ] |
| ; Since %inc54 is the IV of the outer loop, and %0 equivalent to it, |
| ; we get the situation described above. |
| |
| ; Code that leads to this situation can look something like: |
| ; |
| ; int a, b[1], c; |
| ; void fn1 () |
| ; { |
| ; for (; c; c++) |
| ; for (a = 0; a; a++) |
| ; b[c] = 4; |
| ; } |
| ; |
| ; The PHI is an artifact of the register promotion of c. |
| |
| ; Note that we can no longer get the vectorizer to actually see such PHIs, |
| ; because LV now simplifies the loop internally, but the test is still |
| ; useful as a regression test, and in case loop-simplify behavior changes. |
| |
| @c = external global i32, align 4 |
| @a = external global i32, align 4 |
| @b = external global [1 x i32], align 4 |
| |
| ; We can vectorize this loop because we are storing an invariant value into an |
| ; invariant address. |
| |
| define void @test() { |
| ; CHECK-LABEL: define void @test() { |
| ; CHECK-NEXT: [[ENTRY:.*]]: |
| ; CHECK-NEXT: [[A_PROMOTED2:%.*]] = load i32, ptr @a, align 1 |
| ; CHECK-NEXT: [[C_PROMOTED:%.*]] = load i32, ptr @c, align 1 |
| ; CHECK-NEXT: br label %[[FOR_COND1_PREHEADER:.*]] |
| ; CHECK: [[FOR_COND1_PREHEADER]]: |
| ; CHECK-NEXT: [[INC54:%.*]] = phi i32 [ [[INC5:%.*]], %[[FOR_COND1_FOR_INC4_CRIT_EDGE:.*]] ], [ [[C_PROMOTED]], %[[ENTRY]] ] |
| ; CHECK-NEXT: [[INC_LCSSA3:%.*]] = phi i32 [ [[INC_LCSSA:%.*]], %[[FOR_COND1_FOR_INC4_CRIT_EDGE]] ], [ [[A_PROMOTED2]], %[[ENTRY]] ] |
| ; CHECK-NEXT: [[TMP0:%.*]] = mul i32 [[INC_LCSSA3]], -1 |
| ; CHECK-NEXT: [[MIN_ITERS_CHECK:%.*]] = icmp ult i32 [[TMP0]], 4 |
| ; CHECK-NEXT: br i1 [[MIN_ITERS_CHECK]], label %[[SCALAR_PH:.*]], label %[[VECTOR_PH:.*]] |
| ; CHECK: [[VECTOR_PH]]: |
| ; CHECK-NEXT: [[N_MOD_VF:%.*]] = urem i32 [[TMP0]], 4 |
| ; CHECK-NEXT: [[N_VEC:%.*]] = sub i32 [[TMP0]], [[N_MOD_VF]] |
| ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[INC_LCSSA3]], [[N_VEC]] |
| ; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[INC54]] to i64 |
| ; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds [1 x i32], ptr @b, i64 0, i64 [[TMP2]] |
| ; CHECK-NEXT: br label %[[VECTOR_BODY:.*]] |
| ; CHECK: [[VECTOR_BODY]]: |
| ; CHECK-NEXT: [[INDEX:%.*]] = phi i32 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ] |
| ; CHECK-NEXT: store i32 4, ptr [[TMP3]], align 4 |
| ; CHECK-NEXT: [[INDEX_NEXT]] = add nuw i32 [[INDEX]], 4 |
| ; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i32 [[INDEX_NEXT]], [[N_VEC]] |
| ; CHECK-NEXT: br i1 [[TMP4]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP0:![0-9]+]] |
| ; CHECK: [[MIDDLE_BLOCK]]: |
| ; CHECK-NEXT: [[CMP_N:%.*]] = icmp eq i32 [[TMP0]], [[N_VEC]] |
| ; CHECK-NEXT: br i1 [[CMP_N]], label %[[FOR_COND1_FOR_INC4_CRIT_EDGE]], label %[[SCALAR_PH]] |
| ; CHECK: [[SCALAR_PH]]: |
| ; |
| entry: |
| %a.promoted2 = load i32, ptr @a, align 1 |
| %c.promoted = load i32, ptr @c, align 1 |
| br label %for.cond1.preheader |
| |
| for.cond1.preheader: |
| %inc54 = phi i32 [ %inc5, %for.cond1.for.inc4_crit_edge ], [ %c.promoted, %entry ] |
| %inc.lcssa3 = phi i32 [ %inc.lcssa, %for.cond1.for.inc4_crit_edge ], [ %a.promoted2, %entry ] |
| br label %for.body3 |
| |
| for.body3: |
| %inc1 = phi i32 [ %inc.lcssa3, %for.cond1.preheader ], [ %inc, %for.body3 ] |
| %0 = phi i32 [ poison, %for.cond1.preheader ], [ %inc54, %for.body3 ] |
| %idxprom = sext i32 %0 to i64 |
| %arrayidx = getelementptr inbounds [1 x i32], ptr @b, i64 0, i64 %idxprom |
| store i32 4, ptr %arrayidx, align 4 |
| %inc = add nsw i32 %inc1, 1 |
| %tobool2 = icmp eq i32 %inc, 0 |
| br i1 %tobool2, label %for.cond1.for.inc4_crit_edge, label %for.body3 |
| |
| for.cond1.for.inc4_crit_edge: |
| %inc.lcssa = phi i32 [ %inc, %for.body3 ] |
| %.lcssa = phi i32 [ %inc54, %for.body3 ] |
| %inc5 = add nsw i32 %.lcssa, 1 |
| br label %for.cond1.preheader |
| } |