brintos

brintos / llvm-project-archived public Read only

0
0
Text · 19.7 KiB · 8dfe4b1 Raw
580 lines · plain
1; RUN: opt -passes=loop-unroll-and-jam -allow-unroll-and-jam -unroll-and-jam-count=4 < %s -S | FileCheck %s2; RUN: opt -aa-pipeline=basic-aa -passes='loop-unroll-and-jam' -allow-unroll-and-jam -unroll-and-jam-count=4 < %s -S | FileCheck %s3 4target datalayout = "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"5 6; CHECK-LABEL: fore_aft_less7; CHECK: %j = phi8; CHECK: %j.1 = phi9; CHECK: %j.2 = phi10; CHECK: %j.3 = phi11;12; fore_aft_less SHOULD be unroll-and-jammed (count=4) as it's safe.13; Memory accesses:14;   - Fore block: A[i] = 1      (write in outer loop before inner)15;   - Aft block:  A[i-1] = sum  (write in outer loop after inner)16; No dependency conflict: The fore block write A[i] and aft block write A[i-1]17; access different array elements, so unrolling the outer loop and jamming the18; inner loop is safe. The backward dependency (i-1) doesn't create conflicts19; between different unrolled iterations.20define void @fore_aft_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {21entry:22  %cmp = icmp sgt i32 %N, 023  br i1 %cmp, label %for.outer, label %cleanup24 25for.outer:26  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]27  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i28  store i32 1, ptr %arrayidx, align 429  br label %for.inner30 31for.inner:32  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]33  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]34  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j35  %0 = load i32, ptr %arrayidx5, align 436  %mul = mul nsw i32 %0, %i37  %add = add nsw i32 %mul, %sum38  %add6 = add nuw nsw i32 %j, 139  %exitcond = icmp eq i32 %add6, %N40  br i1 %exitcond, label %for.latch, label %for.inner41 42for.latch:43  %add7 = add nuw nsw i32 %i, 144  %add72 = add nuw nsw i32 %i, -145  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add7246  store i32 %add, ptr %arrayidx8, align 447  %exitcond29 = icmp eq i32 %add7, %N48  br i1 %exitcond29, label %cleanup, label %for.outer49 50cleanup:51  ret void52}53 54 55; CHECK-LABEL: fore_aft_eq56; CHECK: %j = phi57; CHECK: %j.1 = phi58; CHECK: %j.2 = phi59; CHECK: %j.3 = phi60;61; fore_aft_eq SHOULD be unroll-and-jammed (count=4) as it's safe.62; Memory accesses:63;   - Fore block: A[i] = 1    (write in outer loop before inner)64;   - Aft block:  A[i] = sum  (write in outer loop after inner)65; Dependency conflict: Both fore and aft blocks write to A[i], creating a66; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam67; because the aft block write always happens after the fore block write in68; the same iteration, preserving the original execution order.69define void @fore_aft_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {70entry:71  %cmp = icmp sgt i32 %N, 072  br i1 %cmp, label %for.outer, label %cleanup73 74for.outer:75  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]76  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i77  store i32 1, ptr %arrayidx, align 478  br label %for.inner79 80for.inner:81  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]82  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]83  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j84  %0 = load i32, ptr %arrayidx5, align 485  %mul = mul nsw i32 %0, %i86  %add = add nsw i32 %mul, %sum87  %add6 = add nuw nsw i32 %j, 188  %exitcond = icmp eq i32 %add6, %N89  br i1 %exitcond, label %for.latch, label %for.inner90 91for.latch:92  %add7 = add nuw nsw i32 %i, 193  %add72 = add nuw nsw i32 %i, 094  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %i95  store i32 %add, ptr %arrayidx8, align 496  %exitcond29 = icmp eq i32 %add7, %N97  br i1 %exitcond29, label %cleanup, label %for.outer98 99cleanup:100  ret void101}102 103 104; CHECK-LABEL: fore_aft_more105; CHECK: %j = phi106; CHECK-NOT: %j.1 = phi107;108; fore_aft_more should NOT be unroll-and-jammed due to a dependency violation.109; Memory accesses:110;   - Fore block: A[i] = 1      (write in outer loop before inner)111;   - Aft block:  A[i+1] = sum  (write in outer loop after inner)112; Dependency conflict: The fore block writes A[i] and aft block writes A[i+1].113; When unroll-and-jamming, iteration i's aft block writes A[i+1] which conflicts114; with iteration i+1's fore block write to A[i+1], creating a write-after-write115; race condition that violates the original sequential semantics.116define void @fore_aft_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {117entry:118  %cmp = icmp sgt i32 %N, 0119  br i1 %cmp, label %for.outer, label %cleanup120 121for.outer:122  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]123  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i124  store i32 1, ptr %arrayidx, align 4125  br label %for.inner126 127for.inner:128  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]129  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]130  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j131  %0 = load i32, ptr %arrayidx5, align 4132  %mul = mul nsw i32 %0, %i133  %add = add nsw i32 %mul, %sum134  %add6 = add nuw nsw i32 %j, 1135  %exitcond = icmp eq i32 %add6, %N136  br i1 %exitcond, label %for.latch, label %for.inner137 138for.latch:139  %add7 = add nuw nsw i32 %i, 1140  %add72 = add nuw nsw i32 %i, 1141  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72142  store i32 %add, ptr %arrayidx8, align 4143  %exitcond29 = icmp eq i32 %add7, %N144  br i1 %exitcond29, label %cleanup, label %for.outer145 146cleanup:147  ret void148}149 150 151; CHECK-LABEL: fore_sub_less152; CHECK: %j = phi153; CHECK: %j.1 = phi154; CHECK: %j.2 = phi155; CHECK: %j.3 = phi156;157; fore_sub_less SHOULD be unroll-and-jammed (count=4) as it's safe.158; Memory accesses:159;   - Fore block: A[i] = 1      (write in outer loop before inner)160;   - Sub block:  A[i-1] = sum  (write inside inner loop)161; No dependency conflict: The fore block writes A[i] and sub block writes A[i-1].162; These access different array elements, so unroll-and-jam is safe. The backward163; dependency pattern doesn't create conflicts between unrolled iterations.164define void @fore_sub_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {165entry:166  %cmp = icmp sgt i32 %N, 0167  br i1 %cmp, label %for.outer, label %cleanup168 169for.outer:170  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]171  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i172  store i32 1, ptr %arrayidx, align 4173  br label %for.inner174 175for.inner:176  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]177  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]178  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j179  %0 = load i32, ptr %arrayidx5, align 4180  %mul = mul nsw i32 %0, %i181  %add = add nsw i32 %mul, %sum182  %add72 = add nuw nsw i32 %i, -1183  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72184  store i32 %add, ptr %arrayidx8, align 4185  %add6 = add nuw nsw i32 %j, 1186  %exitcond = icmp eq i32 %add6, %N187  br i1 %exitcond, label %for.latch, label %for.inner188 189for.latch:190  %add7 = add nuw nsw i32 %i, 1191  %exitcond29 = icmp eq i32 %add7, %N192  br i1 %exitcond29, label %cleanup, label %for.outer193 194cleanup:195  ret void196}197 198 199; CHECK-LABEL: fore_sub_eq200; CHECK: %j = phi201; CHECK: %j.1 = phi202; CHECK: %j.2 = phi203; CHECK: %j.3 = phi204;205; fore_sub_eq SHOULD be unroll-and-jammed (count=4) as it's safe.206; Memory accesses:207;   - Fore block: A[i] = 1    (write in outer loop before inner)208;   - Sub block:  A[i] = sum  (write inside inner loop)209; Dependency conflict: Both fore and sub blocks write to A[i], creating a210; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam211; because the execution order is preserved: fore block executes first, then212; the entire inner loop (sub block) executes, maintaining the original semantics.213define void @fore_sub_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {214entry:215  %cmp = icmp sgt i32 %N, 0216  br i1 %cmp, label %for.outer, label %cleanup217 218for.outer:219  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]220  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i221  store i32 1, ptr %arrayidx, align 4222  br label %for.inner223 224for.inner:225  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]226  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]227  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j228  %0 = load i32, ptr %arrayidx5, align 4229  %mul = mul nsw i32 %0, %i230  %add = add nsw i32 %mul, %sum231  %add72 = add nuw nsw i32 %i, 0232  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72233  store i32 %add, ptr %arrayidx8, align 4234  %add6 = add nuw nsw i32 %j, 1235  %exitcond = icmp eq i32 %add6, %N236  br i1 %exitcond, label %for.latch, label %for.inner237 238for.latch:239  %add7 = add nuw nsw i32 %i, 1240  %exitcond29 = icmp eq i32 %add7, %N241  br i1 %exitcond29, label %cleanup, label %for.outer242 243cleanup:244  ret void245}246 247 248; CHECK-LABEL: fore_sub_more249; CHECK: %j = phi250; CHECK-NOT: %j.1 = phi251;252; fore_sub_more should NOT be unroll-and-jammed due to a dependency violation.253; Memory accesses:254;   - Fore block: A[i] = 1      (write in outer loop before inner)255;   - Sub block:  A[i+1] = sum  (write inside inner loop)256; Dependency conflict: The fore block writes A[i] and sub block writes A[i+1].257; When unroll-and-jamming, iteration i's fore block writes A[i] but iteration i's258; sub block writes A[i+1]. This conflicts with iteration i+1's fore block write259; to A[i+1], creating a write-after-write race condition.260define void @fore_sub_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {261entry:262  %cmp = icmp sgt i32 %N, 0263  br i1 %cmp, label %for.outer, label %cleanup264 265for.outer:266  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]267  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i268  store i32 1, ptr %arrayidx, align 4269  br label %for.inner270 271for.inner:272  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]273  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]274  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j275  %0 = load i32, ptr %arrayidx5, align 4276  %mul = mul nsw i32 %0, %i277  %add = add nsw i32 %mul, %sum278  %add72 = add nuw nsw i32 %i, 1279  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72280  store i32 %add, ptr %arrayidx8, align 4281  %add6 = add nuw nsw i32 %j, 1282  %exitcond = icmp eq i32 %add6, %N283  br i1 %exitcond, label %for.latch, label %for.inner284 285for.latch:286  %add7 = add nuw nsw i32 %i, 1287  %exitcond29 = icmp eq i32 %add7, %N288  br i1 %exitcond29, label %cleanup, label %for.outer289 290cleanup:291  ret void292}293 294 295; CHECK-LABEL: sub_aft_less296; CHECK: %j = phi297; CHECK: %j.1 = phi298; CHECK: %j.2 = phi299; CHECK: %j.3 = phi300;301; sub_aft_less SHOULD be unroll-and-jammed (count=4) as it's safe.302; Memory accesses:303;   - Sub block: A[i] = 1      (write inside inner loop)304;   - Aft block: A[i-1] = sum  (write in outer loop after inner)305; No dependency conflict: The sub block writes A[i] and aft block writes A[i-1].306; These access different array elements, so unroll-and-jam is safe. The backward307; dependency pattern doesn't create conflicts between unrolled iterations.308define void @sub_aft_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {309entry:310  %cmp = icmp sgt i32 %N, 0311  br i1 %cmp, label %for.outer, label %cleanup312 313for.outer:314  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]315  br label %for.inner316 317for.inner:318  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]319  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]320  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j321  %0 = load i32, ptr %arrayidx5, align 4322  %mul = mul nsw i32 %0, %i323  %add = add nsw i32 %mul, %sum324  %add6 = add nuw nsw i32 %j, 1325  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i326  store i32 1, ptr %arrayidx, align 4327  %exitcond = icmp eq i32 %add6, %N328  br i1 %exitcond, label %for.latch, label %for.inner329 330for.latch:331  %add7 = add nuw nsw i32 %i, 1332  %add72 = add nuw nsw i32 %i, -1333  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72334  store i32 %add, ptr %arrayidx8, align 4335  %exitcond29 = icmp eq i32 %add7, %N336  br i1 %exitcond29, label %cleanup, label %for.outer337 338cleanup:339  ret void340}341 342 343; CHECK-LABEL: sub_aft_eq344; CHECK: %j = phi345; CHECK: %j.1 = phi346; CHECK: %j.2 = phi347; CHECK: %j.3 = phi348;349; sub_aft_eq SHOULD be unroll-and-jammed (count=4) as it's safe.350; Memory accesses:351;   - Sub block: A[i] = 1    (write inside inner loop)352;   - Aft block: A[i] = sum  (write in outer loop after inner)353; Dependency conflict: Both sub and aft blocks write to A[i], creating a354; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam355; because the execution order is preserved: the entire inner loop (sub block)356; executes first, then the aft block executes, maintaining original semantics.357define void @sub_aft_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {358entry:359  %cmp = icmp sgt i32 %N, 0360  br i1 %cmp, label %for.outer, label %cleanup361 362for.outer:363  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]364  br label %for.inner365 366for.inner:367  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]368  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]369  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j370  %0 = load i32, ptr %arrayidx5, align 4371  %mul = mul nsw i32 %0, %i372  %add = add nsw i32 %mul, %sum373  %add6 = add nuw nsw i32 %j, 1374  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i375  store i32 1, ptr %arrayidx, align 4376  %exitcond = icmp eq i32 %add6, %N377  br i1 %exitcond, label %for.latch, label %for.inner378 379for.latch:380  %add7 = add nuw nsw i32 %i, 1381  %add72 = add nuw nsw i32 %i, 0382  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %i383  store i32 %add, ptr %arrayidx8, align 4384  %exitcond29 = icmp eq i32 %add7, %N385  br i1 %exitcond29, label %cleanup, label %for.outer386 387cleanup:388  ret void389}390 391 392; CHECK-LABEL: sub_aft_more393; CHECK: %j = phi394; CHECK-NOT: %j.1 = phi395;396; sub_aft_more should NOT be unroll-and-jammed due to a dependency violation.397; Memory accesses:398;   - Sub block: A[i] = 1      (write inside inner loop)399;   - Aft block: A[i+1] = sum  (write in outer loop after inner)400; Dependency conflict: The sub block writes A[i] and aft block writes A[i+1].401; When unroll-and-jamming, iteration i's aft block writes A[i+1] which conflicts402; with iteration i+1's sub block write to A[i+1], creating a write-after-write403; race condition that violates the original sequential semantics.404define void @sub_aft_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {405entry:406  %cmp = icmp sgt i32 %N, 0407  br i1 %cmp, label %for.outer, label %cleanup408 409for.outer:410  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]411  br label %for.inner412 413for.inner:414  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]415  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]416  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j417  %0 = load i32, ptr %arrayidx5, align 4418  %mul = mul nsw i32 %0, %i419  %add = add nsw i32 %mul, %sum420  %add6 = add nuw nsw i32 %j, 1421  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i422  store i32 1, ptr %arrayidx, align 4423  %exitcond = icmp eq i32 %add6, %N424  br i1 %exitcond, label %for.latch, label %for.inner425 426for.latch:427  %add7 = add nuw nsw i32 %i, 1428  %add72 = add nuw nsw i32 %i, 1429  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72430  store i32 %add, ptr %arrayidx8, align 4431  %exitcond29 = icmp eq i32 %add7, %N432  br i1 %exitcond29, label %cleanup, label %for.outer433 434cleanup:435  ret void436}437 438 439; CHECK-LABEL: sub_sub_less440; CHECK: %j = phi441; CHECK-NOT: %j.1 = phi442;443; sub_sub_less should NOT be unroll-and-jammed due to a dependency violation.444; Memory accesses:445;   - Sub block: A[i] = 1      (write inside inner loop)446;   - Sub block: A[i-1] = sum  (write inside inner loop)447; Dependency conflict: Both writes are in the sub block (inner loop), accessing448; A[i] and A[i-1]. When unroll-and-jamming, the inner loop is jammed, meaning449; iterations of the inner loop from different outer iterations execute together.450; This creates a backward dependency that can cause race conditions.451define void @sub_sub_less(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {452entry:453  %cmp = icmp sgt i32 %N, 0454  br i1 %cmp, label %for.outer, label %cleanup455 456for.outer:457  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]458  br label %for.inner459 460for.inner:461  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]462  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]463  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j464  %0 = load i32, ptr %arrayidx5, align 4465  %mul = mul nsw i32 %0, %i466  %add = add nsw i32 %mul, %sum467  %add6 = add nuw nsw i32 %j, 1468  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i469  store i32 1, ptr %arrayidx, align 4470  %add72 = add nuw nsw i32 %i, -1471  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72472  store i32 %add, ptr %arrayidx8, align 4473  %exitcond = icmp eq i32 %add6, %N474  br i1 %exitcond, label %for.latch, label %for.inner475 476for.latch:477  %add7 = add nuw nsw i32 %i, 1478  %exitcond29 = icmp eq i32 %add7, %N479  br i1 %exitcond29, label %cleanup, label %for.outer480 481cleanup:482  ret void483}484 485 486; CHECK-LABEL: sub_sub_eq487; CHECK: %j = phi488; CHECK: %j.1 = phi489; CHECK: %j.2 = phi490; CHECK: %j.3 = phi491;492; sub_sub_eq SHOULD be unroll-and-jammed (count=4) as it's safe.493; Memory accesses:494;   - Sub block: A[i] = 1    (write inside inner loop)495;   - Sub block: A[i] = sum  (write inside inner loop)496; Dependency conflict: Both writes are to A[i] within the sub block, creating a497; write-after-write (WAW) dependency. However, this is safe for unroll-and-jam498; because both writes are in the same basic block and maintain their relative499; order: A[i] = 1 always executes before A[i] = sum in each iteration.500define void @sub_sub_eq(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {501entry:502  %cmp = icmp sgt i32 %N, 0503  br i1 %cmp, label %for.outer, label %cleanup504 505for.outer:506  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]507  br label %for.inner508 509for.inner:510  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]511  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]512  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j513  %0 = load i32, ptr %arrayidx5, align 4514  %mul = mul nsw i32 %0, %i515  %add = add nsw i32 %mul, %sum516  %add6 = add nuw nsw i32 %j, 1517  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i518  store i32 1, ptr %arrayidx, align 4519  %add72 = add nuw nsw i32 %i, 0520  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72521  store i32 %add, ptr %arrayidx8, align 4522  %exitcond = icmp eq i32 %add6, %N523  br i1 %exitcond, label %for.latch, label %for.inner524 525for.latch:526  %add7 = add nuw nsw i32 %i, 1527  %exitcond29 = icmp eq i32 %add7, %N528  br i1 %exitcond29, label %cleanup, label %for.outer529 530cleanup:531  ret void532}533 534 535; CHECK-LABEL: sub_sub_more536; CHECK: %j = phi537; CHECK-NOT: %j.1 = phi538;539; sub_sub_more should NOT be unroll-and-jammed due to a dependency violation.540; Memory accesses:541;   - Sub block: A[i] = 1      (write inside inner loop)542;   - Sub block: A[i+1] = sum  (write inside inner loop)543; Dependency conflict: Both writes are in the sub block, accessing A[i] and A[i+1].544; When unroll-and-jamming, iteration i's sub block writes A[i+1] which conflicts545; with iteration i+1's sub block write to A[i+1]. This creates a forward546; dependency that causes write-after-write race conditions.547define void @sub_sub_more(ptr noalias nocapture %A, i32 %N, ptr noalias nocapture readonly %B) {548entry:549  %cmp = icmp sgt i32 %N, 0550  br i1 %cmp, label %for.outer, label %cleanup551 552for.outer:553  %i = phi i32 [ %add7, %for.latch ], [ 0, %entry ]554  br label %for.inner555 556for.inner:557  %j = phi i32 [ %add6, %for.inner ], [ 0, %for.outer ]558  %sum = phi i32 [ %add, %for.inner ], [ 0, %for.outer ]559  %arrayidx5 = getelementptr inbounds i32, ptr %B, i32 %j560  %0 = load i32, ptr %arrayidx5, align 4561  %mul = mul nsw i32 %0, %i562  %add = add nsw i32 %mul, %sum563  %add6 = add nuw nsw i32 %j, 1564  %arrayidx = getelementptr inbounds i32, ptr %A, i32 %i565  store i32 1, ptr %arrayidx, align 4566  %add72 = add nuw nsw i32 %i, 1567  %arrayidx8 = getelementptr inbounds i32, ptr %A, i32 %add72568  store i32 %add, ptr %arrayidx8, align 4569  %exitcond = icmp eq i32 %add6, %N570  br i1 %exitcond, label %for.latch, label %for.inner571 572for.latch:573  %add7 = add nuw nsw i32 %i, 1574  %exitcond29 = icmp eq i32 %add7, %N575  br i1 %exitcond29, label %cleanup, label %for.outer576 577cleanup:578  ret void579}580