1; RUN: opt -passes=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; ptr p = &A[i + j + k + l]; 9; double x = *p; 10; double y = *p; 11; arg(x + y); 12; } 13; } 14; 15; Check that the original access group on %0 is preserved when replacing uses 16; of %1 with it, as %0 is not moved and if %0 would not be parallel in the 17; original loop it would be UB. 18; 19target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 20 21declare void @arg(double) 22 23define void @func(i64 %n, ptr noalias nonnull %A) { 24entry: 25 br label %for.cond 26 27for.cond: 28 %i.0 = phi i32 [ 0, %entry ], [ %add31, %for.inc30 ] 29 %conv = sext i32 %i.0 to i64 30 %cmp = icmp slt i64 %conv, %n 31 br i1 %cmp, label %for.cond2, label %for.end32 32 33for.cond2: 34 %j.0 = phi i32 [ %add28, %for.inc27 ], [ 0, %for.cond ] 35 %conv3 = sext i32 %j.0 to i64 36 %cmp4 = icmp slt i64 %conv3, %n 37 br i1 %cmp4, label %for.cond8, label %for.inc30 38 39for.cond8: 40 %k.0 = phi i32 [ %add25, %for.inc24 ], [ 0, %for.cond2 ] 41 %conv9 = sext i32 %k.0 to i64 42 %cmp10 = icmp slt i64 %conv9, %n 43 br i1 %cmp10, label %for.cond14, label %for.inc27 44 45for.cond14: 46 %l.0 = phi i32 [ %add23, %for.body19 ], [ 0, %for.cond8 ] 47 %conv15 = sext i32 %l.0 to i64 48 %cmp16 = icmp slt i64 %conv15, %n 49 br i1 %cmp16, label %for.body19, label %for.inc24 50 51for.body19: 52 %add = add nsw i32 %i.0, %j.0 53 %add20 = add nsw i32 %add, %k.0 54 %add21 = add nsw i32 %add20, %l.0 55 %idxprom = sext i32 %add21 to i64 56 %arrayidx = getelementptr inbounds double, ptr %A, i64 %idxprom 57 %0 = load double, ptr %arrayidx, align 8, !llvm.access.group !1 58 %1 = load double, ptr %arrayidx, align 8, !llvm.access.group !2 59 %add22 = fadd double %0, %1 60 call void @arg(double %add22), !llvm.access.group !3 61 %add23 = add nsw i32 %l.0, 1 62 br label %for.cond14, !llvm.loop !11 63 64for.inc24: 65 %add25 = add nsw i32 %k.0, 1 66 br label %for.cond8, !llvm.loop !14 67 68for.inc27: 69 %add28 = add nsw i32 %j.0, 1 70 br label %for.cond2, !llvm.loop !16 71 72for.inc30: 73 %add31 = add nsw i32 %i.0, 1 74 br label %for.cond, !llvm.loop !18 75 76for.end32: 77 ret void 78} 79 80 81; access groups 82!7 = distinct !{} 83!8 = distinct !{} 84!9 = distinct !{} 85 86; access group lists 87!1 = !{!7, !9} 88!2 = !{!7, !8} 89!3 = !{!7, !8, !9} 90 91!11 = distinct !{!11, !13} 92!13 = !{!"llvm.loop.parallel_accesses", !7} 93 94!14 = distinct !{!14, !15} 95!15 = !{!"llvm.loop.parallel_accesses", !8} 96 97!16 = distinct !{!16, !17} 98!17 = !{!"llvm.loop.parallel_accesses", !8, !9} 99 100!18 = distinct !{!18, !19} 101!19 = !{!"llvm.loop.parallel_accesses", !9} 102 103 104; CHECK: load double, {{.*}} !llvm.access.group ![[ACCESSGROUP_0:[0-9]+]] 105; CHECK: br label %for.cond14, !llvm.loop ![[LOOP_4:[0-9]+]] 106 107; CHECK: ![[ACCESSGROUP_0]] = !{![[G1:[0-9]+]], ![[G2:[0-9]+]]} 108; CHECK: ![[G1]] = distinct !{} 109; CHECK: ![[G2]] = distinct !{} 110 111; CHECK: ![[LOOP_4]] = distinct !{![[LOOP_4]], ![[PARALLEL_ACCESSES_5:[0-9]+]]} 112; CHECK: ![[PARALLEL_ACCESSES_5]] = !{!"llvm.loop.parallel_accesses", ![[G1]]} 113