1; RUN: opt -instcombine -S < %s | FileCheck %s 2; 3; void func(long n, double A[static const restrict n]) { 4; for (int i = 0; i < n; i+=1) 5; for (int j = 0; j < n;j+=1) 6; for (int k = 0; k < n; k += 1) 7; for (int l = 0; l < n; l += 1) { 8; double *p = &A[i + j + k + l]; 9; double x = *p; 10; double y = *p; 11; arg(x + y); 12; } 13; } 14; 15; Check for correctly merging access group metadata for instcombine 16; (only common loops are parallel == intersection) 17; Note that combined load would be parallel to loop !16 since both 18; origin loads are parallel to it, but it references two access groups 19; (!8 and !9), neither of which contain both loads. As such, the 20; information that the combined load is parallel to !16 is lost. 21; 22target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 23 24declare void @arg(double) 25 26define void @func(i64 %n, double* noalias nonnull %A) { 27entry: 28 br label %for.cond 29 30for.cond: 31 %i.0 = phi i32 [ 0, %entry ], [ %add31, %for.inc30 ] 32 %conv = sext i32 %i.0 to i64 33 %cmp = icmp slt i64 %conv, %n 34 br i1 %cmp, label %for.cond2, label %for.end32 35 36for.cond2: 37 %j.0 = phi i32 [ %add28, %for.inc27 ], [ 0, %for.cond ] 38 %conv3 = sext i32 %j.0 to i64 39 %cmp4 = icmp slt i64 %conv3, %n 40 br i1 %cmp4, label %for.cond8, label %for.inc30 41 42for.cond8: 43 %k.0 = phi i32 [ %add25, %for.inc24 ], [ 0, %for.cond2 ] 44 %conv9 = sext i32 %k.0 to i64 45 %cmp10 = icmp slt i64 %conv9, %n 46 br i1 %cmp10, label %for.cond14, label %for.inc27 47 48for.cond14: 49 %l.0 = phi i32 [ %add23, %for.body19 ], [ 0, %for.cond8 ] 50 %conv15 = sext i32 %l.0 to i64 51 %cmp16 = icmp slt i64 %conv15, %n 52 br i1 %cmp16, label %for.body19, label %for.inc24 53 54for.body19: 55 %add = add nsw i32 %i.0, %j.0 56 %add20 = add nsw i32 %add, %k.0 57 %add21 = add nsw i32 %add20, %l.0 58 %idxprom = sext i32 %add21 to i64 59 %arrayidx = getelementptr inbounds double, double* %A, i64 %idxprom 60 %0 = load double, double* %arrayidx, align 8, !llvm.access.group !1 61 %1 = load double, double* %arrayidx, align 8, !llvm.access.group !2 62 %add22 = fadd double %0, %1 63 call void @arg(double %add22), !llvm.access.group !3 64 %add23 = add nsw i32 %l.0, 1 65 br label %for.cond14, !llvm.loop !11 66 67for.inc24: 68 %add25 = add nsw i32 %k.0, 1 69 br label %for.cond8, !llvm.loop !14 70 71for.inc27: 72 %add28 = add nsw i32 %j.0, 1 73 br label %for.cond2, !llvm.loop !16 74 75for.inc30: 76 %add31 = add nsw i32 %i.0, 1 77 br label %for.cond, !llvm.loop !18 78 79for.end32: 80 ret void 81} 82 83 84; access groups 85!7 = distinct !{} 86!8 = distinct !{} 87!9 = distinct !{} 88 89; access group lists 90!1 = !{!7, !9} 91!2 = !{!7, !8} 92!3 = !{!7, !8, !9} 93 94!11 = distinct !{!11, !13} 95!13 = !{!"llvm.loop.parallel_accesses", !7} 96 97!14 = distinct !{!14, !15} 98!15 = !{!"llvm.loop.parallel_accesses", !8} 99 100!16 = distinct !{!16, !17} 101!17 = !{!"llvm.loop.parallel_accesses", !8, !9} 102 103!18 = distinct !{!18, !19} 104!19 = !{!"llvm.loop.parallel_accesses", !9} 105 106 107; CHECK: load double, {{.*}} !llvm.access.group ![[ACCESSGROUP_0:[0-9]+]] 108; CHECK: br label %for.cond14, !llvm.loop ![[LOOP_4:[0-9]+]] 109 110; CHECK: ![[ACCESSGROUP_0]] = distinct !{} 111 112; CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[PARALLEL_ACCESSES_5:[0-9]+]]} 113; CHECK: ![[PARALLEL_ACCESSES_5]] = !{!"llvm.loop.parallel_accesses", ![[ACCESSGROUP_0]]} 114