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

    <tr>
        <th>Summary</th>
        <td>
            [UBSan][Clang][CodeGen] Improve memory effect modeling of ubsan handlers
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:codegen,
            missed-optimization
      </td>
    </tr>

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

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

<pre>
    Consider the following case: https://godbolt.org/z/zxxn3oG1z
```
; bin/clang -O3 -fsanitize=undefined -S -emit-llvm -o -
int test(int &a, short &c) {
    a += c;
    return c;
}
```
```
@.src = private unnamed_addr constant [17 x i8] c"/app/example.cpp\00", align 1
@0 = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" }
@1 = private unnamed_addr global { { ptr, i32, i32 }, ptr } { { ptr, i32, i32 } { ptr @.src, i32 2, i32 7 }, ptr @0 }

define dso_local noundef range(i32 -32768, 32768) i32 @test(int&, short&)(ptr noundef nonnull align 4 captures(none) dereferenceable(4) %a, ptr noundef nonnull readonly align 2 captures(none) dereferenceable(2) %c) local_unnamed_addr #0 {
entry:
  %0 = load i16, ptr %c, align 2
  %conv = sext i16 %0 to i32
  %1 = load i32, ptr %a, align 4
  %2 = tail call { i32, i1 } @llvm.sadd.with.overflow.i32(i32 %1, i32 %conv)
  %3 = extractvalue { i32, i1 } %2, 1
  br i1 %3, label %handler.add_overflow, label %cont

handler.add_overflow:
  %4 = zext i32 %1 to i64
  %5 = zext i32 %conv to i64
  tail call void @__ubsan_handle_add_overflow(ptr nonnull @1, i64 %4, i64 %5) #3
  %.pre = load i16, ptr %c, align 2
  %.pre3 = sext i16 %.pre to i32
  br label %cont

cont:
  %conv1.pre-phi = phi i32 [ %.pre3, %handler.add_overflow ], [ %conv, %entry ]
  %6 = extractvalue { i32, i1 } %2, 0
  store i32 %6, ptr %a, align 4
  ret i32 %conv1.pre-phi
}

declare { i32, i1 } @llvm.sadd.with.overflow.i32(i32, i32) #1

declare void @__ubsan_handle_add_overflow(ptr, i64, i64) local_unnamed_addr #2

attributes #0 = { mustprogress nounwind 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 speculatable willreturn memory(none) }
attributes #2 = { uwtable }
attributes #3 = { nounwind }
```
If we mark `__ubsan_handle_add_overflow(_abort)` as `memory(argmem: read, inaccessiblemem: readwrite)`, we can avoid reloading `c` after the call to `__ubsan_handle_add_overflow`.

TBH this example doesn't demonstrate a performance issue since we only optimize code in the cold path. However, it would allow more aggressive LICM in the hot path, which improves the performance of fuzzers like AFL.


</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJyUV12P6ygS_TXkpeTIhthJP-Sh063MXGlW-zC7zxGGssNeDBbgJN2_fgX-SPrevjM9UrdcMYc6RXEoytx71RrEPSkPpHxd8SGcrdvLIG7vb9dVbeXb_sUaryQ6CGeExmptr8q0ILhHwp7hHELvCXsm9EjosbWytjqsrWsJPb7H_9vNMPtb8U7yZ1Ll01_-TNgBamUIPQrNTQvZvxlkjedGBfWOhL0ORmKjDErI_oQMOxUyrS8dZBYykj8rEyCgD4TuokloxQl9AX-2Lv0ShD4B2R5I_gwAwIHQA2GvIAib3zkMgzPzG7J9_THER3uTr70TEF30Tl14QBiM4R3KE5fSgbDGBx4jKQ_FFm6gdqSMdJQSeuR9T-gRb7zrNa5F35PyJc_T2AtwrVoDxciSf4ViewBVVHHu9CDloVo4yfZ1hkA-gaAofsKNsW2VCYRu54BgysMmL34dSattzXUiif99cImG0emRnNCXOLBE80vgPAJTjuehBbP94C6laIwxfx4lAtLbk7aCazA26QYcNy1GbTAKGaPbahcdTMbTSL3J7wIitFrkk-wnQneRb3ZorDGD1tNmbUDwPgwOPaE7Yw1GpxIdNujQCOS1juybJEJa8jn6H7055NIa_Ta5pV9zSye3SeNp3acP20MoyyftownuLR7PKHlCy1Fe2nI5SyclNfmalUhnsLDmkvAebyGpKHkINu3gBCoePI77Onnkd4-bGUwTOHClQXA9KmhWQzGKYZPHY772XMr1VYXz2l7QNdpe1wmYdjTSLgoa44w7NpGwRIK34LgIF64H_IyHlulnkWbVLr2nJYvvNK9Rx19nbqRGt-ZSnuYwPgCENWFU4qfQe943Kab3lMdpASmP1ZKa8idESv8D6J62i1UyZup0GmrPzWkkP30Mc5LvKLR4ntPqq00K58EuRzUxNkey7h3-E5lEPPtJJ8nLg1Rq91naknVPU1xyEWdm_VmN9eesxnyUh4UrVbLPdwdI-ToVursyEjqdhDQ8cVX_RCZ5muWDdThvT_VXWnf4YRuXNd0vmli8hObuU9YvHIKlkKbNKz66_LJAJh0sj1_VEzr65yE4VQ8B_VRk2Fi-u8GH3tnWofepyF2VkTBcQ6xYQCjtlMk0tlxnFxTBuuyqZDjHC4i9EkrHm4dSY7PgeN8r02YdfwAEN-CE8YGL71nvbBg91UPToMt8bBtm-G7CBu5aDJnoh2XotquyuNLH8Qb5VHUnEKEH0dkonWjddqPR3Lwbra67jYb3uBh0tG677ex9MPiBu0WDTon7Nfsxn8Wv8hkPfc3FdzC2cYhgrH8z4p5o36MYNB-zfVVaT61Nh511bw93yWesdGFd9usTFFtQC-vPHdO3Bq4IHXffgVR_I74Tr9Nd-0SqHLiPE5ZwuWs77GJ7GS_IJE7DhUDvVa3xYejqVMDRR0RdEQQ3wJP8Hcb6FXtVUuUisTRh6mNTFQ3276Ks8vWo-_8cfodwVh6mFg6kRW8I3QaQ2MW-zMUmiUOPrrGu40YgKO8HBK-ifUVI97ztg-rUO4KwEkGZMRqrJfQ8nNfwu73iBcdjGeBqBy2Bx54bulh6eJskoS4If3x7-dfs4GxDmp9ycFbiDKrrnb2gT8OPQdkGmuH9HZ0Hrb4jPB__mNa4knsmn9gTX-G-2G4KWm1KylbnPcei2G7EU8VkI2gjGSsY0qYpC4YbWRUrtac5LXOWVwVlJc3XMt9sc17woqrZrqSSbHLsuNLrVNWsa1cpN_uC5fkTW6V7waePEErT5wBhzzFBLZqxR04VxHuU2ZRAHpRNY-Xryu2j26weWh8Lp_LB34mCCjp93_z38Cc3sfyXh5dEMZpW4m8Y38O3MWXToQFsGhQBOitRRxHZBpJQYLp2_Gpwev_D548K56FeC9sReowhTI9Yrf6HIhB6TAv3hB6ntV_29P8BAAD__x7rD90">