<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">