1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes="loop-idiom" < %s -S | FileCheck %s 3 4define void @looper(ptr nocapture %out) { 5; CHECK-LABEL: @looper( 6; CHECK-NEXT: entry: 7; CHECK-NEXT: [[M:%.*]] = getelementptr double, ptr [[OUT:%.*]], i32 16 8; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 8 [[OUT]], ptr align 8 [[M]], i64 256, i1 false), !tbaa [[TBAA0:![0-9]+]] 9; CHECK-NEXT: br label [[FOR_BODY4:%.*]] 10; CHECK: for.body4: 11; CHECK-NEXT: [[J_020:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY4]] ] 12; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[M]], i64 [[J_020]] 13; CHECK-NEXT: [[A0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA0]] 14; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds double, ptr [[OUT]], i64 [[J_020]] 15; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[J_020]], 1 16; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[J_020]], 31 17; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY4]], label [[FOR_COND_CLEANUP:%.*]] 18; CHECK: for.cond.cleanup: 19; CHECK-NEXT: ret void 20; 21entry: 22 %M = getelementptr double, ptr %out, i32 16 23 br label %for.body4 24 25for.body4: ; preds = %for.cond1.preheader, %for.body4 26 %j.020 = phi i64 [ 0, %entry ], [ %inc, %for.body4 ] 27 %arrayidx = getelementptr inbounds double, ptr %M, i64 %j.020 28 %a0 = load double, ptr %arrayidx, align 8, !tbaa !5 29 %arrayidx8 = getelementptr inbounds double, ptr %out, i64 %j.020 30 store double %a0, ptr %arrayidx8, align 8, !tbaa !5 31 %inc = add nuw nsw i64 %j.020, 1 32 %cmp2 = icmp ult i64 %j.020, 31 33 br i1 %cmp2, label %for.body4, label %for.cond.cleanup 34 35for.cond.cleanup: ; preds = %for.cond.cleanup3 36 ret void 37} 38 39 40define void @looperBadMerge(ptr nocapture %out) { 41; CHECK-LABEL: @looperBadMerge( 42; CHECK-NEXT: entry: 43; CHECK-NEXT: [[M:%.*]] = getelementptr double, ptr [[OUT:%.*]], i32 16 44; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 8 [[OUT]], ptr align 8 [[M]], i64 256, i1 false), !tbaa [[TBAA4:![0-9]+]] 45; CHECK-NEXT: br label [[FOR_BODY4:%.*]] 46; CHECK: for.body4: 47; CHECK-NEXT: [[J_020:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY4]] ] 48; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[M]], i64 [[J_020]] 49; CHECK-NEXT: [[A0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA0]] 50; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds double, ptr [[OUT]], i64 [[J_020]] 51; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[J_020]], 1 52; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[J_020]], 31 53; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY4]], label [[FOR_COND_CLEANUP:%.*]] 54; CHECK: for.cond.cleanup: 55; CHECK-NEXT: ret void 56; 57entry: 58 %M = getelementptr double, ptr %out, i32 16 59 br label %for.body4 60 61for.body4: ; preds = %for.cond1.preheader, %for.body4 62 %j.020 = phi i64 [ 0, %entry ], [ %inc, %for.body4 ] 63 %arrayidx = getelementptr inbounds double, ptr %M, i64 %j.020 64 %a0 = load double, ptr %arrayidx, align 8, !tbaa !5 65 %arrayidx8 = getelementptr inbounds double, ptr %out, i64 %j.020 66 store double %a0, ptr %arrayidx8, align 8, !tbaa !3 67 %inc = add nuw nsw i64 %j.020, 1 68 %cmp2 = icmp ult i64 %j.020, 31 69 br i1 %cmp2, label %for.body4, label %for.cond.cleanup 70 71for.cond.cleanup: ; preds = %for.cond.cleanup3 72 ret void 73} 74 75define void @looperGoodMerge(ptr nocapture %out) { 76; CHECK-LABEL: @looperGoodMerge( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[M:%.*]] = getelementptr double, ptr [[OUT:%.*]], i32 16 79; CHECK-NEXT: call void @llvm.memmove.p0.p0.i64(ptr align 8 [[OUT]], ptr align 8 [[M]], i64 256, i1 false) 80; CHECK-NEXT: br label [[FOR_BODY4:%.*]] 81; CHECK: for.body4: 82; CHECK-NEXT: [[J_020:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_BODY4]] ] 83; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds double, ptr [[M]], i64 [[J_020]] 84; CHECK-NEXT: [[A0:%.*]] = load double, ptr [[ARRAYIDX]], align 8, !tbaa [[TBAA0]] 85; CHECK-NEXT: [[ARRAYIDX8:%.*]] = getelementptr inbounds double, ptr [[OUT]], i64 [[J_020]] 86; CHECK-NEXT: [[INC]] = add nuw nsw i64 [[J_020]], 1 87; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i64 [[J_020]], 31 88; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_BODY4]], label [[FOR_COND_CLEANUP:%.*]] 89; CHECK: for.cond.cleanup: 90; CHECK-NEXT: ret void 91; 92entry: 93 %M = getelementptr double, ptr %out, i32 16 94 br label %for.body4 95 96for.body4: ; preds = %for.cond1.preheader, %for.body4 97 %j.020 = phi i64 [ 0, %entry ], [ %inc, %for.body4 ] 98 %arrayidx = getelementptr inbounds double, ptr %M, i64 %j.020 99 %a0 = load double, ptr %arrayidx, align 8, !tbaa !5 100 %arrayidx8 = getelementptr inbounds double, ptr %out, i64 %j.020 101 store double %a0, ptr %arrayidx8, align 8 102 %inc = add nuw nsw i64 %j.020, 1 103 %cmp2 = icmp ult i64 %j.020, 31 104 br i1 %cmp2, label %for.body4, label %for.cond.cleanup 105 106for.cond.cleanup: ; preds = %for.cond.cleanup3 107 ret void 108} 109 110 111!3 = !{!4, !4, i64 0} 112!4 = !{!"float", !7, i64 0} 113!5 = !{!6, !6, i64 0} 114!6 = !{!"double", !7, i64 0} 115!7 = !{!"omnipotent char", !8, i64 0} 116!8 = !{!"Simple C++ TBAA"} 117