Last active
October 22, 2020 17:58
-
-
Save OCHyams/29ec463e82b70955c9fc5542f0b69cd7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Here's a walkthrough of the example from https://llvm.org/47946 with IR. | |
$ cat -n test.c | |
1 int g; | |
2 __attribute__((__always_inline__)) | |
3 static void use(int* p) { | |
4 g = *p; | |
5 *p = 0xff; | |
6 } | |
7 __attribute__((__noinline__)) | |
8 void fun(int param) { | |
9 use(¶m); | |
10 } | |
11 int main() { | |
12 fun(5); | |
13 } | |
$ clang test.c -O2 -g -print-after-all -filter-print-funcs=fun | |
# IR for 'fun' before optimisations run. | |
*** IR Dump After Module Verifier *** | |
; Function Attrs: noinline nounwind uwtable | |
define dso_local void @fun(i32 %param) #0 !dbg !11 { | |
entry: | |
%param.addr = alloca i32, align 4 | |
store i32 %param, i32* %param.addr, align 4, !tbaa !16 | |
call void @llvm.dbg.declare(metadata i32* %param.addr, metadata !15, metadata !DIExpression()), !dbg !20 | |
call void @use(i32* %param.addr), !dbg !21 | |
ret void, !dbg !22 | |
} | |
!15 = !DILocalVariable(name: "param", arg: 1, scope: !11, file: !3, line: 8, type: !6) | |
--- snip --- | |
# InstCombine runs LowerDbgDeclare, converting the dbg.declare to a series of | |
# dbg.values. | |
*** IR Dump After Combine redundant instructions *** | |
; Function Attrs: noinline nounwind uwtable | |
define dso_local void @fun(i32 %param) local_unnamed_addr #0 !dbg !11 { | |
entry: | |
%param.addr = alloca i32, align 4 | |
call void @llvm.dbg.value(metadata i32 %param, metadata !15, metadata !DIExpression()), !dbg !16 | |
store i32 %param, i32* %param.addr, align 4, !tbaa !17 | |
call void @llvm.dbg.value(metadata i32* %param.addr, metadata !15, metadata !DIExpression(DW_OP_deref)), !dbg !16 | |
call fastcc void @use(i32* nonnull %param.addr), !dbg !21 | |
ret void, !dbg !22 | |
} | |
!15 = !DILocalVariable(name: "param", arg: 1, scope: !11, file: !3, line: 8, type: !6) | |
--- snip --- | |
# 'use' is inlined into 'fun'. Notice how there is now a store to %param.addr | |
# which doesn't have an assoicated dbg.value. This doesn't matter at the moment | |
# because we still have the dbg.value+deref that was inserted before the (now | |
# inlined) call site. | |
*** IR Dump After Function Integration/Inlining ***; Function Attrs: noinline nounwind uwtable | |
define dso_local void @fun(i32 %param) local_unnamed_addr #0 !dbg !11 { | |
entry: | |
%param.addr = alloca i32, align 4 | |
call void @llvm.dbg.value(metadata i32 %param, metadata !15, metadata !DIExpression()), !dbg !16 | |
store i32 %param, i32* %param.addr, align 4, !tbaa !17 | |
call void @llvm.dbg.value(metadata i32* %param.addr, metadata !15, metadata !DIExpression(DW_OP_deref)), !dbg !16 | |
call void @llvm.dbg.value(metadata i32* %param.addr, metadata !21, metadata !DIExpression()), !dbg !27 | |
%0 = load i32, i32* %param.addr, align 4, !dbg !29, !tbaa !17 | |
store i32 %0, i32* @g, align 4, !dbg !30, !tbaa !17 | |
store i32 255, i32* %param.addr, align 4, !dbg !31, !tbaa !17 | |
ret void, !dbg !32 | |
} | |
!15 = !DILocalVariable(name: "param", arg: 1, scope: !11, file: !3, line: 8, type: !6) | |
!21 = !DILocalVariable(name: "p", arg: 1, scope: !23, file: !3, line: 3, type: !26) | |
--- snip --- | |
# SROA runs mem2reg, which removes the redundant 0xff store and the remaining | |
# store/load pair for %param.addr. The alloca is then removed, and as of D89810, | |
# the dbg.value+deref is too. This will cause us to provide the misleading | |
# location %param for 'param' after the store to 'g', when we would ideally | |
# provide a constant value 0xff. | |
*** IR Dump After SROA *** | |
; Function Attrs: nofree noinline norecurse nounwind uwtable writeonly | |
define dso_local void @fun(i32 %param) local_unnamed_addr #0 !dbg !11 { | |
entry: | |
call void @llvm.dbg.value(metadata i32 %param, metadata !15, metadata !DIExpression()), !dbg !16 | |
call void @llvm.dbg.value(metadata i32* undef, metadata !17, metadata !DIExpression()), !dbg !23 | |
store i32 %param, i32* @g, align 4, !dbg !25, !tbaa !26 | |
ret void, !dbg !30 | |
} | |
!15 = !DILocalVariable(name: "param", arg: 1, scope: !11, file: !3, line: 8, type: !6) | |
!17 = !DILocalVariable(name: "p", arg: 1, scope: !23, file: !3, line: 3, type: !26) | |
-- snip -- | |
The proposed solution would make the following change to the IR after inlining: | |
store i32 %0, i32* @g, align 4, !dbg !30, !tbaa !17 | |
store i32 255, i32* %param.addr, align 4, !dbg !31, !tbaa !17 | |
[+call void @llvm.dbg.value(metadata i32 255, metadata !15, metadata !DIExpression()), !dbg !16+] | |
ret void, !dbg !32 | |
And after SROA we're left with: | |
define dso_local void @fun(i32 %param) local_unnamed_addr #0 !dbg !11 { | |
entry: | |
call void @llvm.dbg.value(metadata i32 %param, metadata !15, metadata !DIExpression()), !dbg !16 | |
call void @llvm.dbg.value(metadata i32* undef, metadata !17, metadata !DIExpression()), !dbg !23 | |
store i32 %param, i32* @g, align 4, !dbg !25, !tbaa !26 | |
[+call void @llvm.dbg.value(metadata i32 255, metadata !15, metadata !DIExpression()), !dbg !16+] | |
ret void, !dbg !30 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment