<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/77415>77415</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[GVNSink] GVNSink fails to optimize LLVM IR produced by clang with -g flag
</td>
</tr>
<tr>
<th>Labels</th>
<td>
clang
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
Apochens
</td>
</tr>
</table>
<pre>
Here is the source code:
```c
int fun(int a, int b) {
int ret;
if (b > 10) {
int a1 = a + 1;
int a2 = a1 ^ 1;
ret = a2;
} else {
int b1 = b + 1;
int b2 = b1 ^ 1;
ret = b2;
}
return ret;
}
```
The clang and opt used are the latest version built from the source code:
```bash
hs@amdsu:~/llvm-test$ clang --version
clang version 18.0.0git (https://github.com/llvm/llvm-project.git 5dfcb3e5d1d16bb4f8fce52b3c089119ed977e7f)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /home/hs/llvm/usr/local/bin
hs@amdsu:~/llvm-test$ opt --version
LLVM (http://llvm.org/):
LLVM version 18.0.0git
Optimized build with assertions.
Default target: x86_64-unknown-linux-gnu
Host CPU: znver2
```
First, GVNSink is performed on LLVM IR without debug info
```bash
$ clang -S -emit-llvm -Xclang -disable-O0-optnone main.c -o main.ll
$ opt -S -passes=mem2reg,gvn-sink main.ll -o main-sink.ll
```
Then we have the following LLVM IR:
```llvm ir
; ModuleID = 'main.ll'
source_filename = "main.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @fun(i32 noundef %a, i32 noundef %b) #0 {
entry:
%cmp = icmp sgt i32 %b, 10
br i1 %cmp, label %if.then, label %if.else
if.then: ; preds = %entry
br label %if.end
if.else: ; preds = %entry
br label %if.end
if.end: ; preds = %if.else, %if.then
%a.sink = phi i32 [ %a, %if.then ], [ %b, %if.else ]
%add = add nsw i32 %a.sink, 1
%xor = xor i32 %add, 1
ret i32 %xor
}
attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" "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" }
!llvm.module.flags = !{!0, !1, !2, !3, !4}
!llvm.ident = !{!5}
!0 = !{i32 1, !"wchar_size", i32 4}
!1 = !{i32 8, !"PIC Level", i32 2}
!2 = !{i32 7, !"PIE Level", i32 2}
!3 = !{i32 7, !"uwtable", i32 2}
!4 = !{i32 7, !"frame-pointer", i32 2}
!5 = !{!"clang version 18.0.0git (https://github.com/llvm/llvm-project.git 5dfcb3e5d1d16bb4f8fce52b3c089119ed977e7f)"}
```
Then, we perform GVNSink on LLVM IR with debug info:
```bash
$ clang -S -emit-llvm -g -Xclang -disable-O0-optnone main.c -o main-dbg.ll
$ opt -S -passes=mem2reg,gvn-sink main-dbg.ll -o main-dbg-sink.ll
```
We will get the following IR:
```LLVM IR
; ModuleID = 'main-dbg.ll'
source_filename = "main.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: noinline nounwind uwtable
define dso_local i32 @fun(i32 noundef %a, i32 noundef %b) #0 !dbg !10 {
entry:
tail call void @llvm.dbg.value(metadata i32 %a, metadata !15, metadata !DIExpression()), !dbg !16
tail call void @llvm.dbg.value(metadata i32 %b, metadata !17, metadata !DIExpression()), !dbg !16
%cmp = icmp sgt i32 %b, 10, !dbg !18
br i1 %cmp, label %if.then, label %if.else, !dbg !20
if.then: ; preds = %entry
%add = add nsw i32 %a, 1, !dbg !21
tail call void @llvm.dbg.value(metadata i32 %add, metadata !23, metadata !DIExpression()), !dbg !24
%xor = xor i32 %add, 1, !dbg !25
tail call void @llvm.dbg.value(metadata i32 %xor, metadata !26, metadata !DIExpression()), !dbg !24
tail call void @llvm.dbg.value(metadata i32 %xor, metadata !27, metadata !DIExpression()), !dbg !16
br label %if.end, !dbg !28
if.else: ; preds = %entry
%add1 = add nsw i32 %b, 1, !dbg !29
tail call void @llvm.dbg.value(metadata i32 %add1, metadata !31, metadata !DIExpression()), !dbg !32
%xor2 = xor i32 %add1, 1, !dbg !33
tail call void @llvm.dbg.value(metadata i32 %xor2, metadata !34, metadata !DIExpression()), !dbg !32
tail call void @llvm.dbg.value(metadata i32 %xor2, metadata !27, metadata !DIExpression()), !dbg !16
br label %if.end
if.end: ; preds = %if.else, %if.then
%ret.0 = phi i32 [ %xor, %if.then ], [ %xor2, %if.else ], !dbg !35
tail call void @llvm.dbg.value(metadata i32 %ret.0, metadata !27, metadata !DIExpression()), !dbg !16
ret i32 %ret.0, !dbg !36
}
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
attributes #0 = { noinline nounwind uwtable "frame-pointer"="all" "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 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!2, !3, !4, !5, !6, !7, !8}
!llvm.ident = !{!9}
!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang version 18.0.0git (https://github.com/llvm/llvm-project.git 5dfcb3e5d1d16bb4f8fce52b3c089119ed977e7f)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None)
!1 = !DIFile(filename: "main.c", directory: "/home/hs/llvm-test", checksumkind: CSK_MD5, checksum: "68c28c3d0877bed08ff43db70c573802")
!2 = !{i32 7, !"Dwarf Version", i32 5}
!3 = !{i32 2, !"Debug Info Version", i32 3}
!4 = !{i32 1, !"wchar_size", i32 4}
!5 = !{i32 8, !"PIC Level", i32 2}
!6 = !{i32 7, !"PIE Level", i32 2}
!7 = !{i32 7, !"uwtable", i32 2}
!8 = !{i32 7, !"frame-pointer", i32 2}
!9 = !{!"clang version 18.0.0git (https://github.com/llvm/llvm-project.git 5dfcb3e5d1d16bb4f8fce52b3c089119ed977e7f)"}
!10 = distinct !DISubprogram(name: "fun", scope: !1, file: !1, line: 1, type: !11, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !14)
!11 = !DISubroutineType(types: !12)
!12 = !{!13, !13, !13}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !{}
!15 = !DILocalVariable(name: "a", arg: 1, scope: !10, file: !1, line: 1, type: !13)
!16 = !DILocation(line: 0, scope: !10)
!17 = !DILocalVariable(name: "b", arg: 2, scope: !10, file: !1, line: 1, type: !13)
!18 = !DILocation(line: 3, column: 11, scope: !19)
!19 = distinct !DILexicalBlock(scope: !10, file: !1, line: 3, column: 9)
!20 = !DILocation(line: 3, column: 9, scope: !10)
!21 = !DILocation(line: 4, column: 20, scope: !22)
!22 = distinct !DILexicalBlock(scope: !19, file: !1, line: 3, column: 17)
!23 = !DILocalVariable(name: "a1", scope: !22, file: !1, line: 4, type: !13)
!24 = !DILocation(line: 0, scope: !22)
!25 = !DILocation(line: 5, column: 21, scope: !22)
!26 = !DILocalVariable(name: "a2", scope: !22, file: !1, line: 5, type: !13)
!27 = !DILocalVariable(name: "ret", scope: !10, file: !1, line: 2, type: !13)
!28 = !DILocation(line: 7, column: 5, scope: !22)
!29 = !DILocation(line: 8, column: 20, scope: !30)
!30 = distinct !DILexicalBlock(scope: !19, file: !1, line: 7, column: 12)
!31 = !DILocalVariable(name: "b1", scope: !30, file: !1, line: 8, type: !13)
!32 = !DILocation(line: 0, scope: !30)
!33 = !DILocation(line: 9, column: 21, scope: !30)
!34 = !DILocalVariable(name: "b2", scope: !30, file: !1, line: 9, type: !13)
!35 = !DILocation(line: 0, scope: !19)
!36 = !DILocation(line: 12, column: 5, scope: !10)
```
Apparently, in the main-dbg-sink.ll (compiled with `-g`), the instructions (`add` and `xor`) in the if.then block and the if.else block are not sunk to the if.end block.
This is caused by the mishandle of LLVM Debug Intrinsics in GVNSink. When reversely traversing the current basic block's predecessors to find instructions to sink, GVNSink does not exclude LLVM Debug Intrinsics, which cannot be sunk, resulting in an empty candidate vector.
I have a patch for this issue. A pull request will be made later.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWktz27iT_zT0BUUVCYoUdfDBtuIZ12QyqXUm2ZsLJJoU1iDABUA_5rCffQsAKZF6RY5T_5nDpFIWCPQLPzTQjSaJ1qwWAJdBeh2kqwvSmbVUl1etLNcg9EUh6evlr6AAMY3MGpCWnSoBlZJCkFwF0SqIhr9Z5P-X_pkJg6pOBDi3LRLgG2QbRYCXKFhceyKEkOtVYIJk3FehAOcFCpIPKI72WAY2EqMgWSGCAnyN4omEDQn2JDEK0g8HaBQYT4AnQ8FihYBrOKy38HqLXb1uzCssvqew2FO4fVBgOiUmqGzGNziPwf-yBlRyImpEBEWyNajTQBFR4FaNEwPaoCdQmkmBio5xgyolm3PXtCB67bvWOphHpKG6C5Kr_wvwLedPTWjFB3je2xCGvSbP4jsH5XE-i2ZRzYxd4bUxrbZK8W2Ab2tm1l0xK2XTyx3Et0r-D5RmZrlSWpVFAimNaZwVxbzKqxJSXCRllC_jeAl0uVjAogrwsseGqNoCeYVe8uwhm4edeBTyWYScie4lrEU3YKiAUNRICtxSt1KzFz90J7QhnANdMWWHAny7lg3YH701tdPKPsiS8ADfFkyMoTyNm12xHdQ-fvz6-wDRBiHLNJOqdk_LzWoh5Kj3IO5H_2gNa9hfQN3KU_TMzBoRrUEZJoWeDUJWUJGOG2TORAyhX6U26Obzn5b2L_EECp9w0lum7Gxv0C9fP90z8WjPlBZUJVUDFEnhJ3H3X84-2RlEoehqxEQlv-OUI9e7RyE0zIQWKRT-d99LmSYFh_CPKJStEVIAaggTsxKF0rc434pyq3GPwtZipINk1UCDFdQBvqmfRKit7T3TwO86t0KO7FGBngGtyZPflZXkXD4zUQ8TP7b73FyY6nuTa_S7pB2Hu5U7SAK8GGaAF57G7-iHinEQpIGeDPspB7hfJL_MiBJDOHm1gPd0EDZBcgVhixdRkFwl2P2xj_H00bayufsTsk0jxnmQXMU4D6s86lvCdWUDezYP7y3ZjilGsZZvzD3qfAPXFpDbTpTWl9GVMcoeKEhIJjgTgITsxDMTFHXPxvqAZ6JQ2UGq5YPbsIglGAXzqI9YCXZ8FGwcSn3wmvb5OIaTaBshQBj1OtqTAU7LpnWzYbaha-PVOO4bG9h6ykIhFvf0doSTArh9ZtXMrEHs9tnINIZgILNHU3KNWgVU9yim3qqtookcQXfEOMk_QYygB6UMGvDNeHZeqgV65vaWJW7XzIOVXm-WYMuCgnTlevxosR31QTtdjRaBUOpDPKVI6OdhDbwytxAj4hepHLH9HQgpnVDZCN4PvUi1G57dX2KMYkVnQPc-Yqe_uD7uldbfK0UaCFvJhAFlnTxZBRgTu6-x275MhBxqwsMnKI1U4TOjZr0hjHoyIUOjSNsyUYcNGREY1UFPow0pH21YNV5S0VUVqFCzv2BDnve0fm-GZdtthl7yLMzm0_EKiOkU6A1RgK_LRj4F-Ma2XnLfqF5slLStpnnxDe0cwjewb73ki0F6J2CiuwYBipVueAp6gGMXHxt3Os4qTurB8WK7SbHNJK2fxHH_i_vfpP-dbyX2shgFYaZC0n210YjCesYgP8D4uVwT9TAA258jEz3xDnO-Zf58d4M-whPwES8e8-Id3sWY98Np3uQ473BUHuGcH-fc8-FD_OkU0ADjvy9FxPi7mbU7fp9hyFU26ctOxjJOV76bRh_NWOo3JC0hLeofSlx6xrGcMxKYb4CeGefIRepJ_nI8dRkym5OpyzCPf9OXvyN9wTEtancqnshlDGEclYRz9CQZtarc8WgX7olwG1fyBgyxi7EJm1btptPKT3d7VncfXloF2t16LJ5L9_9mbFT2DhOKPRMW7zLhjIxuypm_K8ObyMLRD2V8J_Ifn9RMlQxJzo-st0-TxuDi5AfgxvMz07EpV_oOP7Fp3K7p2btM_0lGvM9dD6TpU3PzI9n_2f_O8b34kPMVh5Zw-Z7ThtJ4F6xkr-cM-BI8dT98wP_iA9YnyfvWHu9ZP3-X9T_Jip_vgj_lpqjAzKJDF8V-Fx29Kg5z3LktTkF8z1niLPvJKI5unBvxI3Ozg3fQY4mFnU5BykckZKXAZhj6VZTbREO3UHac-GupTfj6anQDjVSvAc5tJrqprlIoOVGwj08_MEJoDMG07VKR-B9k_O7ivsX0f-_-_9G7_xTueAT3z_KVY3UG6yhlt1th2K0gHK9G7Fcf_G_a_2b973C9zs-pTiyPVSco04aJ0vjD50Y2LePwp2AmwLm9b3akdrF_9e3h49WnXx5ufJXEXsL8Kw__3CpJuxL61yB_78XdXmv05uWGtagifcxQnTCsga_9G5XkCrlDExrmTtzfmA87tx3nK3ttt4O65cy4pzu7UZmoJyLtVfSL9ZWB-dP4KBkXclZ3txY1nA832B6s7QUW3yDKlNt_r_3ggXdK_eshR16uoXzUXfPYK7-5_-3h91U6HuoFZXmJ8zKhUb5YFECjvKrmCS0WUZkukjzCTuDynBLS6pmoCg0Ybos56akyEh7xu4LInajkASHJqYrSmwpo6TsKaNk7CmiLHy6g5e8soC3_oQU0X0PYO2zuu6JVslaksYfqdj-4aoWboS5lOzlmdo8dGzjts3swr1vieMP-cUzijlt3nN3dclJ_VtJIy0b9Rr_dDt9_tg8rqJhgxrnoDerssegVuGNDgSFMAP0kKehB83yy90eb_74rlOwME_DFGopzq3jDNtl8k91nn4dYMG6M4U22aq6JZmWvYQQqE8OR4fZMcoUS9wSilLQ_01bfHq6-fHhw337QiT3jjThRnG4Vf7SR9StRzLv4WDnpVRNVb5ZisrbRmxY3mdiWTU3wi5UPzNEhXSPuxVkTKKYT2HfO90wgPzkBt-Kl5F3j4lW8D95yIm15YKd9hBdWEn7NZfkY4Px8y3eUTzTh6C12L0-vA45PCptPheG9Vd0JXviNICzfAIJNvEaqkvN2QHzgSPM9x9TOT3oNnr_N7XcASk9ypztw7_ncjrTsPAzwmzFIT2Nw3uZVYA7Fk5OOj08rPr1lF1P40u-gtzwpLP-e6yeTjZQcirQ_7Po7M5lGqSQ-7-w85PrJSfTzk-gn-G2uvwNQcpJ7-T3X35E2Pw-DQ65_GoPlaQxOb-D9qDc5upPTMdNfQU848PjsPvRK8KptiQJh-KvLU4V7L7j7StEmoaW_b_bfngVZFNZWlC95WSYmtFGdq_fYi3weZBGhNMgi90VjkEUvUnmOQc1Q3yusszuqvtcV9fpeZa_9BulOPCIjNxSCeoIZmr7rZRoxjUrivp4sXv10mF4TQTkgWfkXvsO9xigmNCu1tah_KTxD36xNCmwqDvwVGUVcVi5qJ6zslMULFTZ58zYEeKFd7RNK0FoqbQ2tmKBTTIxEw_cqwwtoKkG76cFLyTsKh62zHM9rVq5RSYSlLsDh4RNb3XFjjWMCEYGgac2rpaOMEgPIF5tmY5Du_AdsBLXElGtUSYWMx013MENXqO04Rwr-twNt_AvjwvoE9Z-hDsIu6GVCl8mSXMBlvIjmixzHy-xifYlJRgpSLeK0yEhV0KyKl1USZcuqSBZ5ml2wSxzheRRHyyhLsiSbERrNy6wsMBSQJ2USzCNoCOOz4WvJC2fb5WIxj9MLV47W7oPn_tpkd2y6ulCX7h5UdLUO5hFn2uitBMMMd19J99gH6WqzDBVh3K2P7EsRm88C-mKJcyV_Q3PuH9bufnLRKX75tttZgG_dXHSAb910_j8AAP__8hrTeg">