1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[DeadArgElim] Fixes for dbg.values using dead arg/return values

Summary:
When eliminating a dead argument or return value in a function with
local linkage, all uses, including in dbg.value intrinsics, would be
replaced with null constants. This would mean that, for example for an
integer argument, the debug info would incorrectly express that the
value is 0. Instead, replace all uses with undef to indicate that the
argument/return value is optimized out.

Also, make sure that metadata uses of return values are rewritten even
if there are no non-metadata uses of the value.

As a bit of historical curiosity, the code that emitted null constants
was introduced in the initial check-in of the pass in 2003, before
'undef' values even existed in LLVM.

This fixes PR23260.

Reviewers: dblaikie, aprantl, vsk, djtodoro

Reviewed By: aprantl

Subscribers: llvm-commits

Tags: #debug-info

Differential Revision: https://reviews.llvm.org/D55513

llvm-svn: 348837
This commit is contained in:
David Stenberg 2018-12-11 10:33:38 +00:00
parent 68f8736aef
commit d17978836b
2 changed files with 74 additions and 8 deletions

View File

@ -24,7 +24,6 @@
#include "llvm/IR/Attributes.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
@ -954,16 +953,16 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
ArgAttrVec.clear();
Instruction *New = NewCS.getInstruction();
if (!Call->use_empty()) {
if (!Call->use_empty() || Call->isUsedByMetadata()) {
if (New->getType() == Call->getType()) {
// Return type not changed? Just replace users then.
Call->replaceAllUsesWith(New);
New->takeName(Call);
} else if (New->getType()->isVoidTy()) {
// Our return value has uses, but they will get removed later on.
// Replace by null for now.
// If the return value is dead, replace any uses of it with undef
// (any non-debug value uses will get removed later on).
if (!Call->getType()->isX86_MMXTy())
Call->replaceAllUsesWith(Constant::getNullValue(Call->getType()));
Call->replaceAllUsesWith(UndefValue::get(Call->getType()));
} else {
assert((RetTy->isStructTy() || RetTy->isArrayTy()) &&
"Return type changed, but not into a void. The old return type"
@ -1023,10 +1022,10 @@ bool DeadArgumentEliminationPass::RemoveDeadStuffFromFunction(Function *F) {
I2->takeName(&*I);
++I2;
} else {
// If this argument is dead, replace any uses of it with null constants
// (these are guaranteed to become unused later on).
// If this argument is dead, replace any uses of it with undef
// (any non-debug value uses will get removed later on).
if (!I->getType()->isX86_MMXTy())
I->replaceAllUsesWith(Constant::getNullValue(I->getType()));
I->replaceAllUsesWith(UndefValue::get(I->getType()));
}
// If we change the return value of the function we must rewrite any return

View File

@ -0,0 +1,67 @@
; RUN: opt -deadargelim -S < %s | FileCheck %s
; Verify that the dbg.value intrinsics that use the dead argument and return
; value are marked as undef to indicate that the values are optimized out.
; Reproducer for PR23260.
; CHECK-LABEL: define internal void @bar()
; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata ![[LOCAL1:[0-9]+]]
; CHECK: call void @sink()
; Function Attrs: alwaysinline nounwind uwtable
define internal i32 @bar(i32 %deadarg) #1 !dbg !10 {
entry:
call void @llvm.dbg.value(metadata i32 %deadarg, metadata !15, metadata !DIExpression()), !dbg !17
call void @sink(), !dbg !17
ret i32 123, !dbg !17
}
; CHECK-LABEL: define void @foo()
; CHECK: call void @bar()
; CHECK: call void @llvm.dbg.value(metadata i32 undef, metadata ![[LOCAL2:[0-9]+]]
; CHECK: call void @bar()
; Function Attrs: nounwind uwtable
define void @foo() #0 !dbg !6 {
entry:
%deadret = call i32 @bar(i32 0), !dbg !9
call void @llvm.dbg.value(metadata i32 %deadret, metadata !16, metadata !DIExpression()), !dbg !9
call i32 @bar(i32 1), !dbg !9
ret void, !dbg !9
}
declare void @sink() local_unnamed_addr
; Function Attrs: nounwind readnone speculatable
declare void @llvm.dbg.value(metadata, metadata, metadata) #2
attributes #0 = { nounwind uwtable }
attributes #1 = { alwaysinline nounwind uwtable }
attributes #2 = { nounwind readnone speculatable }
!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}
!llvm.ident = !{!5}
; CHECK: ![[LOCAL1]] = !DILocalVariable(name: "local1"
; CHECK: ![[LOCAL2]] = !DILocalVariable(name: "local2"
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
!1 = !DIFile(filename: "pr23260.c", directory: "/")
!2 = !{}
!3 = !{i32 2, !"Dwarf Version", i32 4}
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = !{!"clang version 8.0.0"}
!6 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !7, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
!7 = !DISubroutineType(types: !8)
!8 = !{null}
!9 = !DILocation(line: 4, column: 3, scope: !6)
!10 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 2, type: !11, scopeLine: 2, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !14)
!11 = !DISubroutineType(types: !12)
!12 = !{!13, !13}
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!14 = !{!15}
!15 = !DILocalVariable(name: "local1", arg: 1, scope: !10, file: !1, line: 2, type: !13)
!16 = !DILocalVariable(name: "local2", arg: 1, scope: !6, file: !1, line: 2, type: !13)
!17 = !DILocation(line: 2, column: 52, scope: !10)