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

    <tr>
        <th>Summary</th>
        <td>
            SimplifyCFG removes return statement
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            bug,
            miscompilation,
            llvm:transforms
      </td>
    </tr>

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

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

<pre>
    We're seeing a miscompile from Rust, but the IR seems valid, and the bug only occurs while lowering LLVM IR.

I've somewhat reduced the case down, but I haven't run llvm-reduce over it yet.

The folowing diff shows that after simplifycfg we drop the return branch altogether.

```diff
❯ diff /tmp/lto.small.ll /tmp/lto.small.bad.strip.ll
1c1
< ; ModuleID = '/tmp/lto.strip.ll'
---
> ; ModuleID = '/tmp/lto.small.ll'
17c17
<   br label %4
---
>   br label %3
19,29c19,23
< 3:                                                ; preds = %4
<   ret void
<
< 4:                                                ; preds = %6, %0
<   %5 = phi i8 [ %7, %6 ], [ -3, %0 ]
<   br i1 false, label %3, label %6
<
< 6:                                                ; preds = %4
<   %7 = add nuw nsw i8 %5, 1
<   call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef %5) #4
<   br label %4
---
> 3:                                                ; preds = %3, %0
>   %4 = phi i8 [ %5, %3 ], [ -3, %0 ]
>   %5 = add nuw nsw i8 %4, 1
>   call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef %4) #4
>   br label %3
```

For completeness I'm including the IR before and after simplifycfg:

**Before simplifycfg**
```
; ModuleID = '/tmp/lto.strip.ll'
source_filename = "lto_hang.577eccc79634c19c-cgu.0"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-fuchsia"

; Function Attrs: nounwind optsize shadowcallstack uwtable
declare hidden fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias nocapture noundef align 8 dereferenceable(24), i8 noundef) unnamed_addr #0

; Function Attrs: noinline nounwind optsize shadowcallstack uwtable
define hidden fastcc void @_RNvCs7vJBeK7brjY_8lto_hang11do_the_test() unnamed_addr #1 {
  %1 = alloca [24 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %1)
  %2 = getelementptr inbounds i8, ptr %1, i64 16
  store i16 -32640, ptr %2, align 8, !alias.scope !6
  call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %1, i8 0, i64 16, i1 false), !alias.scope !6
  call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef -4) #4
  br label %4

3:                                                ; preds = %4
  ret void

4:                                                ; preds = %6, %0
  %5 = phi i8 [ %7, %6 ], [ -3, %0 ]
  br i1 false, label %3, label %6

6:                                                ; preds = %4
  %7 = add nuw nsw i8 %5, 1
  call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef %5) #4
  br label %4
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3

attributes #0 = { nounwind optsize shadowcallstack uwtable "frame-pointer"="all" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+crc,+aes,+neon,+fp-armv8,+neon,+fp-armv8,+sha2" }
attributes #1 = { noinline nounwind optsize shadowcallstack uwtable "frame-pointer"="all" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+crc,+aes,+neon,+fp-armv8,+neon,+fp-armv8,+sha2" }
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nounwind }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"PIE Level", i32 2}
!2 = !{i32 4, !"EnableSplitLTOUnit", i32 1}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"rustc version 1.84.0-nightly (583b25d8d 2024-11-12)"}
!6 = !{!7}
!7 = distinct !{!7, !8, !"_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3new: argument 0"}
!8 = distinct !{!8, !"_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3new"}
````

**After simplifycfg:**
```
; ModuleID = '/tmp/lto.small.ll'
source_filename = "lto_hang.577eccc79634c19c-cgu.0"
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "aarch64-unknown-fuchsia"

; Function Attrs: nounwind optsize shadowcallstack uwtable
declare hidden fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias nocapture noundef align 8 dereferenceable(24), i8 noundef) unnamed_addr #0

; Function Attrs: noinline nounwind optsize shadowcallstack uwtable
define hidden fastcc void @_RNvCs7vJBeK7brjY_8lto_hang11do_the_test() unnamed_addr #1 {
  %1 = alloca [24 x i8], align 8
  call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %1)
  %2 = getelementptr inbounds i8, ptr %1, i64 16
  store i16 -32640, ptr %2, align 8, !alias.scope !6
  call void @llvm.memset.p0.i64(ptr noundef nonnull align 8 dereferenceable(16) %1, i8 0, i64 16, i1 false), !alias.scope !6
  call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef -4) #4
  br label %3

3:                                                ; preds = %3, %0
  %4 = phi i8 [ %5, %3 ], [ -3, %0 ]
  %5 = add nuw nsw i8 %4, 1
  call fastcc void @_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3add(ptr noalias noundef nonnull align 8 dereferenceable(24) %1, i8 noundef %4) #4
  br label %3
}

; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: write)
declare void @llvm.memset.p0.i64(ptr nocapture writeonly, i8, i64, i1 immarg) #2

; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
declare void @llvm.lifetime.start.p0(i64 immarg, ptr nocapture) #3

attributes #0 = { nounwind optsize shadowcallstack uwtable "frame-pointer"="all" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+crc,+aes,+neon,+fp-armv8,+neon,+fp-armv8,+sha2" }
attributes #1 = { noinline nounwind optsize shadowcallstack uwtable "frame-pointer"="all" "probe-stack"="inline-asm" "target-cpu"="generic" "target-features"="+v8a,+crc,+aes,+neon,+fp-armv8,+neon,+fp-armv8,+sha2" }
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: write) }
attributes #3 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
attributes #4 = { nounwind }

!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}

!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"PIE Level", i32 2}
!2 = !{i32 4, !"EnableSplitLTOUnit", i32 1}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"rustc version 1.84.0-nightly (583b25d8d 2024-11-12)"}
!6 = !{!7}
!7 = distinct !{!7, !8, !"_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3new: argument 0"}
!8 = distinct !{!8, !"_RNvMCs7vJBeK7brjY_8lto_hangNtB2_4Test3new"}
```

The after module was generated w/ `opt -passes=simplifycfg < before.ll -S`

Unfortunately, this issue originates from Rust (Fuchsia's toolchain, which uses a different cadence for release process than upstream), and it isn't clear when this behavior was introduced in the LLVM used by `rustc`, so we'll probably need to bisect quite a ways back. I did reproduce this with ToT LLVM, though, so its still an issue on the LLVM side.

If no one has a thought on the underlying issue, I'll pick up the investigation again tomorrow, reduce the test further, and try to kick of a bisect to run this down a bit more.

CC: @nikic @tmandry
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsGl1z27jx18AvO9SQIClRD36QP9Rxm1w7Se46ffKA4JLEBQRYABSr_voOQEqWHMdxcn5I53zji0hgv7HYD2mZtaJRiJckvyL5zQUbXKvNpZB6h724KHW1v_wnEroyCBZRqAYYdMJy3fVCItRGd_BhsI7QaygHB65FuPvgYTsLOyZF5XeYqsJOOTSgldyD5nwwFsbWE5F6RONJv3v323u4-7Ag8YbEmztCVzsEqzscW-bAYDVwnAhxZhEqPaoD3zto2Q4VoSsHZlAg5a6LJgzQOzQgHOzRzaQ_tQi1lnr0XCtR12BbPVpwng-rHRqwouulqPe8bmBEqIzuA2eDbjAKSsMUb4FJpxt0LZqZMlnG05-n6t9vKVnfkM12YkPo1nU9oVvp9MJ2TMqFlE-tlqxaWGdEv5CSxJuEJ55Yeg0kvYL3uhok3t0ASW-A0NU5_gGLrki8iaIoIN6-AHEWZ0JMVjxZzTwBSgOSlehFzbMzsud7qcdcE3pN13z6TGcaKUk38J3_eZF7g5Wd5Q2sJ4EMOthpUU0L83L2GjyW3qUIzeMjL0LzPOz2rQBRAMmv_NpqBlwCyW_Cc34FUXpAD6sn9hMJ1Exa9Psn9jp9W55ps3xdi3mJwyqrKlDDCMqOQRua516K5AjJmZRQM-s4DzYGksX3H37Zvb-2q91fr_Bvq9L8_q_7Qjp93zLV_OKu6H32Ca1LWVURWvTOgNJMCmZB6UFVWIPSSg1SApOiUVBAhQZrNKg4slIioQXNCF17cRIvjiiOqJOEfivNXuCRr-Jp6ZkX3E72y57wgnwGTL_hBbenjvTlEWQPR3D7cx5BdnYET138Y-ybQuFWG_B5QqJDhdaCD-gdCMXlUPnAO-eKEmttMOSIL0IvSTdzXKX-72oCPQUI64-Zf1-MtHowHO9rIVGxDmcMerDtIl-tkHO-Wi_TjCdrHvFmWMSEUhJvHDMNOqiYY5Lt9eAO2Bh1JN1gJAqSbvz_KY1E4u90-Me_LX28WmaRSKgHSGgRqZROax_929a_nrLxYsujgIwZ3i6zaFCflR5VVA-8tYJNGLMZtoPiTmgFG-eM9TfDH-koVAW6d1b8F8G2rNKj9zjrGP8Mw-iCO8SbCrlkBqEVVYXqFf2Rs94NBo_u9Q2PPHdG74eD8idV3bOqMt4p4-c1FkoKhd-neu0xvq75VxRPkkrfuxbvHfqiqHhK2ATI6orEmxAQkikgSKk587GDZvAfEMUcTGbDBOAQEw4i-PpmIUWNTnS4sI4Zt-hjQguxzICGaDKZfLry05VeH5jSwLRBhxI7VM6DClV6-1rPfMY-BoJlBskyIFvnL6BIlhCldJnFJ6D0VOAQ_pJw3gvLdY_-dfkVPTrsLHr5F_5OHJzlpUErWT4KWvGJzP7pmHjX3xTrJwq50WnA_TLfkXjzaiXVeTkVb169jvqDNdR31U_x5tUKp5cVTT-f6zwqmJ5wntXN8wHTa1T6iKh0bfAkco5CyrkF6rDTZk9owUzToc92MBrhcIozh9zxgot-yAYB27eHkzrzLZ6vsOg6ZppZq28kuC-lt3vFX6qEQVZ9S5GvRd6DlIfoO6s2i51OYjPnjCgHhzakrsnjVlcvTk8-99eGdRj1WiiHxmf89MZXBL6koX6_N7rEKKAdd6csGDHbzUBTVRHxfjjCNKjQCH4OUCPzWtgjFKFXu4IRek3oFTd8emAewD8o1Gp6qvuImW5XPL9uW0YDw-CV59ZJTqzznVn8z2QmemKmP3h3n6SfPkv_R2_Xk6yyL-_DQ7iiyRRHQnG_qCVrDgE78TUVTeI5xSfzJ50_55SSZDOtmZCoULlzCvkpt_hkT6T0WNgQSv9xdw3vcIcyHPQ1-G16pJ48QlydIt4-g0gfIWYPiLfKu_XHXgr37tPff1XCnVBIjhTSRxToA4WbkZkafkNjhfexI_KDVbJnkLEcGrhTtX6CQnqkkJ-bk1BqBus47CYcSBZFtogjJZrWyT0QWuRFWtK8KiqgMc2iJIn8sa099QPR5TnR1XFjys6VsE4o7k4hJrlPDuyFGVnh6P2UmWbwpTHEp3IUX2H3Y2yOhI-966F3ntrazVPt8I81vGff7b01vG8N71vD-9bw_lxdyzMNb_qKDW_6uC_98W91X_aN7s9n6Uff5j5h67f-8K0__L9ofN76w7f-8K0_fOsP_yT94XF6ZfqldPJzGJmFEHGYwwpGQrdAlrHuHUQ9sxYtSW9O51lIej3_6rqQEqKPR8q_qlobNyjmcMqyrhUWhLUDgjaiEX7HPkz9-NPZHpqwlQWnteQtE2EsZ2wFb2GwaIGF6RdfnDjgrPI1CtTagEGJzCL0RnO0Yf5GwdBbZ5B1c_nKVAXCgbDTcA-XyAyMLapJuBJbthPaBCMI5YyepoSECr8vh5GiwWIF5d4bJfia15deg9UwIqErKb0AJSvlHhRiBU5DKSxyB_8ehENgMLK9BR_UFnAHlajAYD9xmqQYhWvhk_4U-E2G00PTzlyEs2Cd8MWaOljzRDwrKjzMPPm6DrRvxJg320TGHcB9-WbkXqhmIuPp380aCJ_ZphkloXZonWhYKHxYw7wxdKeN0aNHmeeiPKjv2qAejGt9_psntczem-Czp6hrYAdjOB1Gq4LClR5V2HHQeT-axL--9leDZLESnwX3D65jqjL7i-oyrdbpml3gZbJK04ymeba-aC-XRV7xel0v62KJdUbL9arGKuNpFudFxrILcekvfULjPClSSteLZVqnnNUsSXmKWZ2SLMaOCbkIAVub5iKY5jJJiiLPL0Jda8N8G6Xl0EwxiVB6nGILVjoueyok3TjDlK216UK2zm8uzGUYKSuHxvoiT1hnHzg64SRefpyv2PX2L2Cw0zu0h3Ex65gLjefFYORl61xvw3c5W0K3jXDtUC647gjdBvbTR9Qb_TtyR-g2aGQJ3c5K7S7p_wIAAP__c3-6lQ">