<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/123349>123349</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Failing to derive NoAlias for non-aliasing stores in a loop
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            llvm:optimizations
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          bjope
      </td>
    </tr>
</table>

<pre>
    Consider this IR:

```
define dso_local void @bar(ptr noalias nocapture noundef %p, i16 noundef %nr) {
entry:
  %cmp45 = icmp sgt i16 %nr, 0
  tail call void @llvm.assume(i1 %cmp45)
  br label %for.body

for.body:
  %a = phi i16 [ 0, %entry ], [ %add, %for.body ]
  %mul = mul nsw nuw i16 %a, %nr
  %gep = getelementptr inbounds i32, ptr %p, i16 %mul
  ; mul2 = (a + 1) * nr
  %or = or disjoint i16 %a, 1
  %mul2 = mul nsw nuw i16 %or, %nr
  %gep2 = getelementptr inbounds i32, ptr %p, i16 %mul2
  store i32 7, ptr %gep
 store i32 9, ptr %gep2
  %add = add nuw nsw i16 %a, 4
  %cmp = icmp samesign ult i16 %a, 60
  br i1 %cmp, label %for.body, label %for.cond.cleanup

for.cond.cleanup:
  ret void
}
```

If running `opt -passes='aa-eval' -print-all-alias-modref-info` we see that %gep and %gep2 id detected as "MayAlias".
(This also happens if replacing the "or disjoint" by "add nsw nuw".)


I did try to manually rewrite the IR a bit. Given that a>=0 and nr>0 I think we can rewrite
```
  ; mul2 = (a + 1) * nr
  %or = or disjoint i16 %a, 1
  %mul2 = mul nsw nuw i16 %or, %nr
```
as
```
  ; mul2 = (a * nr) + nr
  %mul = mul nsw nuw i16 %a, %nr
  %mul2 = add nsw nuw i16 %mul, %nr
```

And then it looks like we would derive "NoAlias" when the IR looks like this instead:
```
define dso_local void @foo(ptr noalias nocapture noundef %p, i16 noundef %nr) {
entry:
  %cmp45 = icmp sgt i16 %nr, 0
  tail call void @llvm.assume(i1 %cmp45)
  br label %for.body

for.body:
  %a = phi i16 [ 0, %entry ], [ %add, %for.body ]
  %mul = mul nsw nuw i16 %a, %nr
  %gep = getelementptr inbounds i32, ptr %p, i16 %mul
  ; mul2 = (a * nr) + nr
  %mul2 = add nsw nuw i16 %mul, %nr
  %gep2 = getelementptr inbounds i32, ptr %p, i16 %mul2
 store i32 7, ptr %gep
  store i32 9, ptr %gep2
  %add = add nuw nsw i16 %a, 4
  %cmp = icmp samesign ult i16 %a, 60
  br i1 %cmp, label %for.body, label %for.cond.cleanup

for.cond.cleanup:
  ret void
}
```

So there seems to be a bit of inconsistency in the analysis, making it sensitive to what the IR looks like.


Here is a C level reproducer:
```
void large(int *p, int nr) {
    __builtin_assume(nr > 0);
    #pragma clang loop unroll(disable)
    for (int a = 0; a < 64; a+=2) {
        p[a * nr] = 7;
        p[(a + 1) * nr] = 9;
    }
}
```

Compiled with `-emit-llvm -O3 -g0` we get IR similar to @bar above:
```
define dso_local void @csource(ptr nocapture noundef writeonly %p, i32 noundef %nr) local_unnamed_addr #0 {
entry:
  %cmp = icmp sgt i32 %nr, 0
  tail call void @llvm.assume(i1 %cmp)
  %0 = zext nneg i32 %nr to i64
  br label %for.body

for.cond.cleanup:
  ret void

for.body:
  %indvars.iv = phi i64 [ 0, %entry ], [ %indvars.iv.next, %for.body ]
  %1 = mul nuw nsw i64 %indvars.iv, %0
  %arrayidx = getelementptr inbounds nuw i32, ptr %p, i64 %1
  store i32 7, ptr %arrayidx, align 4
  %2 = or disjoint i64 %indvars.iv, 1
  %3 = mul nuw nsw i64 %2, %0
  %arrayidx4 = getelementptr inbounds nuw i32, ptr %p, i64 %3
  store i32 9, ptr %arrayidx4, align 4
 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 2
  %cmp1 = icmp samesign ult i64 %indvars.iv, 62
  br i1 %cmp1, label %for.body, label %for.cond.cleanup
}

declare void @llvm.assume(i1 noundef) #1

attributes #0 = { nofree norecurse nosync nounwind memory(argmem: write, inaccessiblemem: write) uwtable "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cmov,+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" }
attributes #1 = { mustprogress nocallback nofree nosync nounwind willreturn memory(inaccessiblemem: write) }
```

Which according to aa-eval is identified as:
```
Function: csource: 2 pointers, 1 call sites
  MayAlias:     i32* %arrayidx, i32* %arrayidx4
```

Given that it is possible to derive NoAlias for `@foo` above then I think it should be possible for `@bar` as well. And if that is solved I guess we would be able to see that the stores in the `@csource` test case as well.

It is at least a bit unfortunate that the C code is lowered into IR that doesn't satisfy alias analysis in the sense that we can derive that the stores are safe to reorder (or execute in parallel). Btw, if unrolling the loop we do get 64 pointers that has NoAlias, so there isn't even aliasing between iterations.

PS. Context for this problem is that I've been analysing downstream regressions after https://github.com/llvm/llvm-project/pull/119365 . This might be one part of the puzzle, but real problem seem to be that we drop knowledge about "nsw" after LoopStrenghtReduce. I suspect that if we can't derive NoAlias before loop-reduce, then it is even harder for loop-reduce/scev-expander to reason about "nsw" when generating reassociations.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJzsWNtu4zjSfhrmpiBDony88IWdTP4_wJ4ws8BeBpRYkjmhSIGk7LifflHUwU6cZLobCywWu40GzJDFYh2_qpLwXtUGccsWe7Z4uBNdOFi3LX63Ld4VVp6399Z4JdFBOCgPT7-yfMfS-H-ZDv_TncRKGQTp7bO2pdBwtEoCm6eFcIyv2-DAWKGV8GBsKdrQOQRjOyOxAsYXLeP3oLLl9Z5xjG-ArfYs3aEJ7ty_DHRWNu18ASx_AFU2Lfg6xNvDrXtII2EQSkMp9EUcrY_NTHjfNcj4WmUTL8Y38UrhQIsCNR1U1s3IBL26018XKUSUoD2o_vHFHlJ6nPFFlBfY4iH-vdhHaimH05FVJBh4NZ2O3OjX-BOY7jSqJIZrxo3ENbaRuMaAGhs0gSysTEHW86ByTldo79q2_Ss9j3xPL_HIhfG1AMb3kEWD8x1cXrIuklgHUvnfrTLhjVTZlfj8M_mt-0gB_tMa8MjFB-uQCGF1RVpjS6eXw83bQz75TsooAP2SrCTztWbzq1C7CjTRICUMdPqtIZbpGD5TUNH2bSy93yytkbNSozBdewm0N7tDwDkMMY6JavXwLgFZunuqwHXGKFMDW6a2DZC0wnv0LH9gfCVEgkehGV9B0jplQiK0TmJOJo2VDqtEmcqyZQonBI8I4SDCGG3CyMlvSoLEgGVACcID4_zP4rwjRozzGQnD138nsBDaWziItkXjQVXgsNWiJAHDAeneVVgxzqE402b0SB9BkV_MzEFFkEoCpVaw0AjTCa3P4PDkVMDI9OlXEFCoMIP_U0c0vQ6C5b-w_CGNWhjH8l9SeCI8My-kaynMyOOdVf-tiXItiPDfJVkUKIq2vxLth6BlYnnlhmv0-ERAlu52RpILDKgA2toXD1q9IBn4ZDtNMePUMbr9L3aMFjgdopOi464uxVqjjA8o5FBwvqfaVNb-r9r8Z1SbT0P1e6PvX1RHviwj_5V15DdLCeliDWg8IW2BPaiCrUCZkhpCH9CUZ1B98goj9NkrT1I14oUQXgXwaLwKlPPBwomA-CbRZxO0_z-9SDUD7kHjETVVC2dlV6K7RYCYYVq4OiaWoTK1671rAlynMgDA83PRKR2UeZ5y0RBa_0IJtGH5SMd43jpRNwJKLUxNYrbQGWe1ZnwtlReFxjF1ASqC_P71PjVTinNa3sNyHteM71n-wN-KQ_9atthPWbB4iNdXF0lGkg8LzkB-LXjvxo-ceW-bVmmUcFLhQH1Bgo0KCSETJH_NIanToeLXGMg3XjVKC0cu69t3EIU94g-AcOlt50qcgPg9AMdCa40-X1Iy57dQHJk-d8aIBuWzkJKsnaefQ_Q7gM75TwP06GPGF2nk-g1fAxiD9YUtGUgt598B43-Ugx-CvTLyKJyfqeMF9ZfzP0T9y7WZwdfwRQXILvg_ohbxv2Yx3E4nqHNOnJV8_QpwI15_ALo97-yLzn3kTltCEzZO0MlvW6uPZJ16rPwz3fhnKs1_Xqf8i0IxsX-n1K2nbmvIRxryq3DPPqsmH11c8puykv1cXelBhtK_1MLh56k0JHQPXHnW3xIhOFV0Af2QzNQQrPZgbOWQIMJh2TlPK382ZWRyUkZCg411Z8JDVzfYsHzX40iP-aIs0XtVkPOuzzbQnQKhNnWdjTKJxlro5IhlsC45KRkOjPM4H_GU2lHGubFJcKJtlamTRlwRBNfhQOODKF-S1tnQcyq6qkKXePUNJ_L1QBuoSoWkbLvp6HW9TJbzt-cVCkJJPxExvi8bS96j1eu6X1Sv3vWrpnntF97jtOD96nW9Grl3Bt-8XaNBp8p4HH351iXZ5JKm86F1tnbo-zZa60KULxdXvXXQSWntMHTOXHz1lWM-rFb_OKjyAKIsrZNxTLQwjK3UGiiJJqhKxbHztiA9dqYMyhp6ZqxB-Q44tAQZ6GJ3kvUFwKuAPqbENLoSv01M8917OLrdnd_KfjVvqkDitrbXnLQYZp9h8Olbh2U6TCzLtK-x_fQ0DqbUQB3i4FTghdflZiFcvOnhhFrPgMYvVQ0CePBWH1HCE9QdOXCawqiXG4SaZnxqyyKA-bGh658YrbhMIaAPUAqP04PDRB4fEwE0Ch-GNrEzlXWhMyJcPXAPpZWxxdP2hA4l9WqWWo5IIi16w_gqgBdB-eoM_QA3tpajZNRUDlyH0X2w7XtNCJy8qKKmDq2TGNs16wBfsewCEsdWOKE1asY3M9iHU_R2NTR944eK2AeeEKSNTdJyPkVU_-hBeJhG2nvwY_-sBoWQAiNqQxwLDCeMUzI6QfHqB1P-7bcZ3FsTqBqQm-MM3DpLyUNmi289Mb46IhTEYTCNqUHak_HBoWjAYcxY4guiCujgEEIbw5s_Mv5Yq3DoillpG8YfCbSHH0Kz37EMjD-2HTW8j1m2yZcLmEH8ltOo-hAoeqxBMlscBsg6bfftm444XHQBHAo9CU0DxDA_jA6TzrbwYuxJo6wpFG0XIur6E0FSL_GfrG1_Cw5NfQi_Io0AM3gC3_kWyzBEeDW4P1r4XXoVWFE1Jr8lLt4n8cZvE8r3HjmIGBNk6jeUj77EY4KvrTDxszeFj_DW3Agbv11EPBWBvEBk3pZq8Oqd3OZyk2_EHW6zVb7K-Hy13NwdtmK9nPMiX2wWqw2fy_larlerjHNRrFZymaV3astTvkizbJXN8w3fzDJc4XqV5Zs0F5s5Ipun2AilZ7HqWlffKe873GY8z-ebu1jAffykz3n0cb6zbVCN-tbLRtVg8XDnttHzRVd7quDKB3_hGFTQuH0USg9I_AGGGWuSKbAvCCKiQe86p7c_HHxREU_h1-ty3PJ_BgAA__8WWYBT">