1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -loop-vectorize -instcombine -force-vector-width=4 -S < %s 2>&1 | FileCheck %s 3 4target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 5 6;;;; Derived from the following C code 7;; void forked_ptrs_different_base_same_offset(float *A, float *B, float *C, int *D) { 8;; for (int i=0; i<100; i++) { 9;; if (D[i] != 0) { 10;; C[i] = A[i]; 11;; } else { 12;; C[i] = B[i]; 13;; } 14;; } 15;; } 16 17define dso_local void @forked_ptrs_different_base_same_offset(float* nocapture readonly %Base1, float* nocapture readonly %Base2, float* nocapture %Dest, i32* nocapture readonly %Preds) { 18; CHECK-LABEL: @forked_ptrs_different_base_same_offset( 19; CHECK-NEXT: entry: 20; CHECK-NEXT: br label [[FOR_BODY:%.*]] 21; CHECK: for.cond.cleanup: 22; CHECK-NEXT: ret void 23; CHECK: for.body: 24; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 25; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[PREDS:%.*]], i64 [[INDVARS_IV]] 26; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 27; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i32 [[TMP0]], 0 28; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[CMP1_NOT]], float* [[BASE2:%.*]], float* [[BASE1:%.*]] 29; CHECK-NEXT: [[DOTSINK_IN:%.*]] = getelementptr inbounds float, float* [[SPEC_SELECT]], i64 [[INDVARS_IV]] 30; CHECK-NEXT: [[DOTSINK:%.*]] = load float, float* [[DOTSINK_IN]], align 4 31; CHECK-NEXT: [[TMP1:%.*]] = getelementptr inbounds float, float* [[DEST:%.*]], i64 [[INDVARS_IV]] 32; CHECK-NEXT: store float [[DOTSINK]], float* [[TMP1]], align 4 33; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 34; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 100 35; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 36; 37entry: 38 br label %for.body 39 40for.cond.cleanup: 41 ret void 42 43for.body: 44 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 45 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 46 %0 = load i32, i32* %arrayidx, align 4 47 %cmp1.not = icmp eq i32 %0, 0 48 %spec.select = select i1 %cmp1.not, float* %Base2, float* %Base1 49 %.sink.in = getelementptr inbounds float, float* %spec.select, i64 %indvars.iv 50 %.sink = load float, float* %.sink.in, align 4 51 %1 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 52 store float %.sink, float* %1, align 4 53 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 54 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 55 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 56} 57 58;;;; Derived from the following C code 59;; void forked_ptrs_same_base_different_offset(float *A, float *B, int *C) { 60;; int offset; 61;; for (int i = 0; i < 100; i++) { 62;; if (C[i] != 0) 63;; offset = i; 64;; else 65;; offset = i+1; 66;; B[i] = A[offset]; 67;; } 68;; } 69 70define dso_local void @forked_ptrs_same_base_different_offset(float* nocapture readonly %Base, float* nocapture %Dest, i32* nocapture readonly %Preds) { 71; CHECK-LABEL: @forked_ptrs_same_base_different_offset( 72; CHECK-NEXT: entry: 73; CHECK-NEXT: br label [[FOR_BODY:%.*]] 74; CHECK: for.cond.cleanup: 75; CHECK-NEXT: ret void 76; CHECK: for.body: 77; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ] 78; CHECK-NEXT: [[I_014:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 79; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[PREDS:%.*]], i64 [[INDVARS_IV]] 80; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 81; CHECK-NEXT: [[CMP1_NOT:%.*]] = icmp eq i32 [[TMP0]], 0 82; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 83; CHECK-NEXT: [[ADD]] = add nuw nsw i32 [[I_014]], 1 84; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32 85; CHECK-NEXT: [[OFFSET_0:%.*]] = select i1 [[CMP1_NOT]], i32 [[ADD]], i32 [[TMP1]] 86; CHECK-NEXT: [[IDXPROM213:%.*]] = zext i32 [[OFFSET_0]] to i64 87; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds float, float* [[BASE:%.*]], i64 [[IDXPROM213]] 88; CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[ARRAYIDX3]], align 4 89; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds float, float* [[DEST:%.*]], i64 [[INDVARS_IV]] 90; CHECK-NEXT: store float [[TMP2]], float* [[ARRAYIDX5]], align 4 91; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i64 [[INDVARS_IV_NEXT]], 100 92; CHECK-NEXT: br i1 [[EXITCOND_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_BODY]] 93; 94entry: 95 br label %for.body 96 97for.cond.cleanup: ; preds = %for.body 98 ret void 99 100for.body: ; preds = %entry, %for.body 101 %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ] 102 %i.014 = phi i32 [ 0, %entry ], [ %add, %for.body ] 103 %arrayidx = getelementptr inbounds i32, i32* %Preds, i64 %indvars.iv 104 %0 = load i32, i32* %arrayidx, align 4 105 %cmp1.not = icmp eq i32 %0, 0 106 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1 107 %add = add nuw nsw i32 %i.014, 1 108 %1 = trunc i64 %indvars.iv to i32 109 %offset.0 = select i1 %cmp1.not, i32 %add, i32 %1 110 %idxprom213 = zext i32 %offset.0 to i64 111 %arrayidx3 = getelementptr inbounds float, float* %Base, i64 %idxprom213 112 %2 = load float, float* %arrayidx3, align 4 113 %arrayidx5 = getelementptr inbounds float, float* %Dest, i64 %indvars.iv 114 store float %2, float* %arrayidx5, align 4 115 %exitcond.not = icmp eq i64 %indvars.iv.next, 100 116 br i1 %exitcond.not, label %for.cond.cleanup, label %for.body 117} 118