101217368SeopXD; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 201217368SeopXD; REQUIRES: asserts 301217368SeopXD; RUN: opt < %s -S -debug -passes=loop-idiom 2>&1 | FileCheck %s 401217368SeopXD; The C code to generate this testcase: 501217368SeopXD; void test(int *ar, int n, int m) 601217368SeopXD; { 701217368SeopXD; long i; 801217368SeopXD; for (i=0; i<n; ++i) { 901217368SeopXD; int *arr = ar + i * m; 1001217368SeopXD; memset(arr, 0, i + m * sizeof(int)); 1101217368SeopXD; } 1201217368SeopXD; } 1301217368SeopXD 1401217368SeopXD; Check on debug outputs... 1501217368SeopXD; CHECK: loop-idiom Scanning: F[MemsetSize_LoopVariant] Countable Loop %for.body 1601217368SeopXD; CHECK-NEXT: memset size is non-constant 1701217368SeopXD; CHECK-NEXT: memset size is not a loop-invariant, abort 1801217368SeopXD; CHECK: loop-idiom Scanning: F[MemsetSize_Stride_Mismatch] Countable Loop %for.body 1901217368SeopXD; CHECK-NEXT: memset size is non-constant 2001217368SeopXD; CHECK-NEXT: MemsetSizeSCEV: (4 * (sext i32 %m to i64))<nsw> 2101217368SeopXD; CHECK-NEXT: PositiveStrideSCEV: (4 + (4 * (sext i32 %m to i64))<nsw>)<nsw> 22bc17d32aSeopXD; CHECK-NEXT: Try to fold SCEV based on loop guard 23bc17d32aSeopXD; CHECK-NEXT: FoldedMemsetSize: (4 * (sext i32 %m to i64))<nsw> 24bc17d32aSeopXD; CHECK-NEXT: FoldedPositiveStride: (4 + (4 * (sext i32 %m to i64))<nsw>)<nsw> 2501217368SeopXD; CHECK-NEXT: SCEV don't match, abort 2601217368SeopXD; CHECK: loop-idiom Scanning: F[NonZeroAddressSpace] Countable Loop %for.cond1.preheader 2701217368SeopXD; CHECK-NEXT: memset size is non-constant 2801217368SeopXD; CHECK-NEXT: pointer is not in address space zero, abort 2901217368SeopXD; CHECK: loop-idiom Scanning: F[NonAffinePointer] Countable Loop %for.body 3001217368SeopXD; CHECK-NEXT: Pointer is not affine, abort 3101217368SeopXD 32*055fb779SNikita Popovdefine void @MemsetSize_LoopVariant(ptr %ar, i32 %n, i32 %m) { 3301217368SeopXD; CHECK-LABEL: @MemsetSize_LoopVariant( 3401217368SeopXD; CHECK-NEXT: entry: 3501217368SeopXD; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[N:%.*]] to i64 3601217368SeopXD; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 0, [[CONV]] 3701217368SeopXD; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END:%.*]] 3801217368SeopXD; CHECK: for.body.lr.ph: 3901217368SeopXD; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[M:%.*]] to i64 4001217368SeopXD; CHECK-NEXT: [[CONV2:%.*]] = sext i32 [[M]] to i64 4101217368SeopXD; CHECK-NEXT: [[MUL3:%.*]] = mul i64 [[CONV2]], 4 4201217368SeopXD; CHECK-NEXT: br label [[FOR_BODY:%.*]] 4301217368SeopXD; CHECK: for.body: 4401217368SeopXD; CHECK-NEXT: [[I_02:%.*]] = phi i64 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 4501217368SeopXD; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[I_02]], [[CONV1]] 46*055fb779SNikita Popov; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[AR:%.*]], i64 [[MUL]] 4701217368SeopXD; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[I_02]], [[MUL3]] 48*055fb779SNikita Popov; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ADD_PTR]], i8 0, i64 [[ADD]], i1 false) 4901217368SeopXD; CHECK-NEXT: br label [[FOR_INC]] 5001217368SeopXD; CHECK: for.inc: 5101217368SeopXD; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_02]], 1 5201217368SeopXD; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], [[CONV]] 5301217368SeopXD; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]] 5401217368SeopXD; CHECK: for.cond.for.end_crit_edge: 5501217368SeopXD; CHECK-NEXT: br label [[FOR_END]] 5601217368SeopXD; CHECK: for.end: 5701217368SeopXD; CHECK-NEXT: ret void 5801217368SeopXD; 5901217368SeopXDentry: 6001217368SeopXD %conv = sext i32 %n to i64 6101217368SeopXD %cmp1 = icmp slt i64 0, %conv 6201217368SeopXD br i1 %cmp1, label %for.body.lr.ph, label %for.end 6301217368SeopXD 6401217368SeopXDfor.body.lr.ph: ; preds = %entry 6501217368SeopXD %conv1 = sext i32 %m to i64 6601217368SeopXD %conv2 = sext i32 %m to i64 6701217368SeopXD %mul3 = mul i64 %conv2, 4 6801217368SeopXD br label %for.body 6901217368SeopXD 7001217368SeopXDfor.body: ; preds = %for.body.lr.ph, %for.inc 7101217368SeopXD %i.02 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 7201217368SeopXD %mul = mul nsw i64 %i.02, %conv1 73*055fb779SNikita Popov %add.ptr = getelementptr inbounds i32, ptr %ar, i64 %mul 7401217368SeopXD %add = add nsw i64 %i.02, %mul3 75*055fb779SNikita Popov call void @llvm.memset.p0.i64(ptr align 4 %add.ptr, i8 0, i64 %add, i1 false) 7601217368SeopXD br label %for.inc 7701217368SeopXD 7801217368SeopXDfor.inc: ; preds = %for.body 7901217368SeopXD %inc = add nuw nsw i64 %i.02, 1 8001217368SeopXD %cmp = icmp slt i64 %inc, %conv 8101217368SeopXD br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge 8201217368SeopXD 8301217368SeopXDfor.cond.for.end_crit_edge: ; preds = %for.inc 8401217368SeopXD br label %for.end 8501217368SeopXD 8601217368SeopXDfor.end: ; preds = %for.cond.for.end_crit_edge, %entry 8701217368SeopXD ret void 8801217368SeopXD} 8901217368SeopXD; void test(int *ar, int n, int m) 9001217368SeopXD; { 9101217368SeopXD; long i; 9201217368SeopXD; for (i=0; i<n; ++i) { 9301217368SeopXD; int *arr = ar + i + i * m; 9401217368SeopXD; memset(arr, 0, m * sizeof(int)); 9501217368SeopXD; } 9601217368SeopXD; } 97*055fb779SNikita Popovdefine void @MemsetSize_Stride_Mismatch(ptr %ar, i32 %n, i32 %m) { 9801217368SeopXD; CHECK-LABEL: @MemsetSize_Stride_Mismatch( 9901217368SeopXD; CHECK-NEXT: entry: 10001217368SeopXD; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[N:%.*]] to i64 10101217368SeopXD; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 0, [[CONV]] 10201217368SeopXD; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END:%.*]] 10301217368SeopXD; CHECK: for.body.lr.ph: 10401217368SeopXD; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[M:%.*]] to i64 10501217368SeopXD; CHECK-NEXT: [[CONV3:%.*]] = sext i32 [[M]] to i64 10601217368SeopXD; CHECK-NEXT: [[MUL4:%.*]] = mul i64 [[CONV3]], 4 10701217368SeopXD; CHECK-NEXT: br label [[FOR_BODY:%.*]] 10801217368SeopXD; CHECK: for.body: 10901217368SeopXD; CHECK-NEXT: [[I_02:%.*]] = phi i64 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ] 110*055fb779SNikita Popov; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[AR:%.*]], i64 [[I_02]] 11101217368SeopXD; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[I_02]], [[CONV1]] 112*055fb779SNikita Popov; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds i32, ptr [[ADD_PTR]], i64 [[MUL]] 113*055fb779SNikita Popov; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ADD_PTR2]], i8 0, i64 [[MUL4]], i1 false) 11401217368SeopXD; CHECK-NEXT: br label [[FOR_INC]] 11501217368SeopXD; CHECK: for.inc: 11601217368SeopXD; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_02]], 1 11701217368SeopXD; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], [[CONV]] 11801217368SeopXD; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]] 11901217368SeopXD; CHECK: for.cond.for.end_crit_edge: 12001217368SeopXD; CHECK-NEXT: br label [[FOR_END]] 12101217368SeopXD; CHECK: for.end: 12201217368SeopXD; CHECK-NEXT: ret void 12301217368SeopXD; 12401217368SeopXDentry: 12501217368SeopXD %conv = sext i32 %n to i64 12601217368SeopXD %cmp1 = icmp slt i64 0, %conv 12701217368SeopXD br i1 %cmp1, label %for.body.lr.ph, label %for.end 12801217368SeopXD 12901217368SeopXDfor.body.lr.ph: ; preds = %entry 13001217368SeopXD %conv1 = sext i32 %m to i64 13101217368SeopXD %conv3 = sext i32 %m to i64 13201217368SeopXD %mul4 = mul i64 %conv3, 4 13301217368SeopXD br label %for.body 13401217368SeopXD 13501217368SeopXDfor.body: ; preds = %for.body.lr.ph, %for.inc 13601217368SeopXD %i.02 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 137*055fb779SNikita Popov %add.ptr = getelementptr inbounds i32, ptr %ar, i64 %i.02 13801217368SeopXD %mul = mul nsw i64 %i.02, %conv1 139*055fb779SNikita Popov %add.ptr2 = getelementptr inbounds i32, ptr %add.ptr, i64 %mul 140*055fb779SNikita Popov call void @llvm.memset.p0.i64(ptr align 4 %add.ptr2, i8 0, i64 %mul4, i1 false) 14101217368SeopXD br label %for.inc 14201217368SeopXD 14301217368SeopXDfor.inc: ; preds = %for.body 14401217368SeopXD %inc = add nuw nsw i64 %i.02, 1 14501217368SeopXD %cmp = icmp slt i64 %inc, %conv 14601217368SeopXD br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge 14701217368SeopXD 14801217368SeopXDfor.cond.for.end_crit_edge: ; preds = %for.inc 14901217368SeopXD br label %for.end 15001217368SeopXD 15101217368SeopXDfor.end: ; preds = %for.cond.for.end_crit_edge, %entry 15201217368SeopXD ret void 15301217368SeopXD} 15401217368SeopXD 155*055fb779SNikita Popovdefine void @NonZeroAddressSpace(ptr addrspace(2) nocapture %ar, i64 %n, i64 %m) { 15601217368SeopXD; CHECK-LABEL: @NonZeroAddressSpace( 15701217368SeopXD; CHECK-NEXT: entry: 15801217368SeopXD; CHECK-NEXT: [[TMP0:%.*]] = shl nuw i64 [[M:%.*]], 2 15901217368SeopXD; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 16001217368SeopXD; CHECK: for.cond1.preheader: 16101217368SeopXD; CHECK-NEXT: [[I_017:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC5:%.*]], [[FOR_INC4:%.*]] ] 16201217368SeopXD; CHECK-NEXT: [[TMP1:%.*]] = mul i64 [[M]], [[I_017]] 163*055fb779SNikita Popov; CHECK-NEXT: [[SCEVGEP:%.*]] = getelementptr i32, ptr addrspace(2) [[AR:%.*]], i64 [[TMP1]] 16401217368SeopXD; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[I_017]], [[M]] 165*055fb779SNikita Popov; CHECK-NEXT: call void @llvm.memset.p2.i64(ptr addrspace(2) align 4 [[SCEVGEP]], i8 0, i64 [[TMP0]], i1 false) 16601217368SeopXD; CHECK-NEXT: br label [[FOR_INC4]] 16701217368SeopXD; CHECK: for.inc4: 16801217368SeopXD; CHECK-NEXT: [[INC5]] = add nuw nsw i64 [[I_017]], 1 16901217368SeopXD; CHECK-NEXT: [[EXITCOND18_NOT:%.*]] = icmp eq i64 [[INC5]], [[N:%.*]] 17001217368SeopXD; CHECK-NEXT: br i1 [[EXITCOND18_NOT]], label [[FOR_END6:%.*]], label [[FOR_COND1_PREHEADER]] 17101217368SeopXD; CHECK: for.end6: 17201217368SeopXD; CHECK-NEXT: ret void 17301217368SeopXD; 17401217368SeopXDentry: 17501217368SeopXD %0 = shl nuw i64 %m, 2 17601217368SeopXD br label %for.cond1.preheader 17701217368SeopXD 17801217368SeopXDfor.cond1.preheader: ; preds = %for.inc4, %entry 17901217368SeopXD %i.017 = phi i64 [ 0, %entry ], [ %inc5, %for.inc4 ] 18001217368SeopXD %1 = mul i64 %m, %i.017 181*055fb779SNikita Popov %scevgep = getelementptr i32, ptr addrspace(2) %ar, i64 %1 18201217368SeopXD %mul = mul nsw i64 %i.017, %m 183*055fb779SNikita Popov call void @llvm.memset.p2.i64(ptr addrspace(2) align 4 %scevgep, i8 0, i64 %0, i1 false) 18401217368SeopXD br label %for.inc4 18501217368SeopXD 18601217368SeopXDfor.inc4: ; preds = %for.cond1.preheader 18701217368SeopXD %inc5 = add nuw nsw i64 %i.017, 1 18801217368SeopXD %exitcond18.not = icmp eq i64 %inc5, %n 18901217368SeopXD br i1 %exitcond18.not, label %for.end6, label %for.cond1.preheader 19001217368SeopXD 19101217368SeopXDfor.end6: ; preds = %for.inc4 19201217368SeopXD ret void 19301217368SeopXD} 19401217368SeopXD 19501217368SeopXD; void test(int *ar, int n, int m) 19601217368SeopXD; { 19701217368SeopXD; long i; 19801217368SeopXD; for (i=0; i<n; ++i) { 19901217368SeopXD; int *arr = ar + i * m; 20001217368SeopXD; memset(arr, 0, m * sizeof(int)); 20101217368SeopXD; ar = ar + i; 20201217368SeopXD; } 20301217368SeopXD; } 204*055fb779SNikita Popovdefine void @NonAffinePointer(ptr %ar, i32 %n, i32 %m) { 20501217368SeopXD; CHECK-LABEL: @NonAffinePointer( 20601217368SeopXD; CHECK-NEXT: entry: 20701217368SeopXD; CHECK-NEXT: [[CONV:%.*]] = sext i32 [[N:%.*]] to i64 20801217368SeopXD; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i64 0, [[CONV]] 20901217368SeopXD; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY_LR_PH:%.*]], label [[FOR_END:%.*]] 21001217368SeopXD; CHECK: for.body.lr.ph: 21101217368SeopXD; CHECK-NEXT: [[CONV1:%.*]] = sext i32 [[M:%.*]] to i64 21201217368SeopXD; CHECK-NEXT: [[CONV2:%.*]] = sext i32 [[M]] to i64 21301217368SeopXD; CHECK-NEXT: [[MUL3:%.*]] = mul i64 [[CONV2]], 4 21401217368SeopXD; CHECK-NEXT: br label [[FOR_BODY:%.*]] 21501217368SeopXD; CHECK: for.body: 216*055fb779SNikita Popov; CHECK-NEXT: [[AR_ADDR_03:%.*]] = phi ptr [ [[AR:%.*]], [[FOR_BODY_LR_PH]] ], [ [[ADD_PTR4:%.*]], [[FOR_INC:%.*]] ] 21701217368SeopXD; CHECK-NEXT: [[I_02:%.*]] = phi i64 [ 0, [[FOR_BODY_LR_PH]] ], [ [[INC:%.*]], [[FOR_INC]] ] 21801217368SeopXD; CHECK-NEXT: [[MUL:%.*]] = mul nsw i64 [[I_02]], [[CONV1]] 219*055fb779SNikita Popov; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds i32, ptr [[AR_ADDR_03]], i64 [[MUL]] 220*055fb779SNikita Popov; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 4 [[ADD_PTR]], i8 0, i64 [[MUL3]], i1 false) 221*055fb779SNikita Popov; CHECK-NEXT: [[ADD_PTR4]] = getelementptr inbounds i32, ptr [[AR_ADDR_03]], i64 [[I_02]] 22201217368SeopXD; CHECK-NEXT: br label [[FOR_INC]] 22301217368SeopXD; CHECK: for.inc: 22401217368SeopXD; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[I_02]], 1 22501217368SeopXD; CHECK-NEXT: [[CMP:%.*]] = icmp slt i64 [[INC]], [[CONV]] 22601217368SeopXD; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_CRIT_EDGE:%.*]] 22701217368SeopXD; CHECK: for.cond.for.end_crit_edge: 22801217368SeopXD; CHECK-NEXT: br label [[FOR_END]] 22901217368SeopXD; CHECK: for.end: 23001217368SeopXD; CHECK-NEXT: ret void 23101217368SeopXD; 23201217368SeopXDentry: 23301217368SeopXD %conv = sext i32 %n to i64 23401217368SeopXD %cmp1 = icmp slt i64 0, %conv 23501217368SeopXD br i1 %cmp1, label %for.body.lr.ph, label %for.end 23601217368SeopXD 23701217368SeopXDfor.body.lr.ph: ; preds = %entry 23801217368SeopXD %conv1 = sext i32 %m to i64 23901217368SeopXD %conv2 = sext i32 %m to i64 24001217368SeopXD %mul3 = mul i64 %conv2, 4 24101217368SeopXD br label %for.body 24201217368SeopXD 24301217368SeopXDfor.body: ; preds = %for.body.lr.ph, %for.inc 244*055fb779SNikita Popov %ar.addr.03 = phi ptr [ %ar, %for.body.lr.ph ], [ %add.ptr4, %for.inc ] 24501217368SeopXD %i.02 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %for.inc ] 24601217368SeopXD %mul = mul nsw i64 %i.02, %conv1 247*055fb779SNikita Popov %add.ptr = getelementptr inbounds i32, ptr %ar.addr.03, i64 %mul 248*055fb779SNikita Popov call void @llvm.memset.p0.i64(ptr align 4 %add.ptr, i8 0, i64 %mul3, i1 false) 249*055fb779SNikita Popov %add.ptr4 = getelementptr inbounds i32, ptr %ar.addr.03, i64 %i.02 25001217368SeopXD br label %for.inc 25101217368SeopXD 25201217368SeopXDfor.inc: ; preds = %for.body 25301217368SeopXD %inc = add nuw nsw i64 %i.02, 1 25401217368SeopXD %cmp = icmp slt i64 %inc, %conv 25501217368SeopXD br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge 25601217368SeopXD 25701217368SeopXDfor.cond.for.end_crit_edge: ; preds = %for.inc 25801217368SeopXD br label %for.end 25901217368SeopXD 26001217368SeopXDfor.end: ; preds = %for.cond.for.end_crit_edge, %entry 26101217368SeopXD ret void 26201217368SeopXD} 26301217368SeopXD 264*055fb779SNikita Popovdeclare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) 265*055fb779SNikita Popovdeclare void @llvm.memset.p2.i64(ptr addrspace(2) nocapture writeonly, i8, i64, i1 immarg) 266