mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
Add @llvm.dbg.value entries for the phi node created by -mem2reg
When phi nodes are created in the -mem2reg phase, the @llvm.dbg.declare entries are converted to @llvm.dbg.value entries at the place where the store instructions existed. However no entry is created to describe the resulting value of the phi node. The effect of this is especially noticeable in for loops which have a constant for the intial value; the loop control variable's location would be described as the intial constant value in the loop body once the -mem2reg optimization phase was run. This change adds the creation of the @llvm.dbg.value entries to describe variables whose location is the result of a phi node created in -mem2reg. Also when the phi node is finally lowered to a machine instruction it is important that the lowered "load" instruction is placed before the associated DEBUG_VALUE entry describing the value loaded. Differential Revision: https://reviews.llvm.org/D23715 llvm-svn: 281895
This commit is contained in:
parent
07a1bb0354
commit
64915fd385
@ -32,6 +32,7 @@ class BranchInst;
|
||||
class Instruction;
|
||||
class CallInst;
|
||||
class DbgDeclareInst;
|
||||
class DbgValueInst;
|
||||
class StoreInst;
|
||||
class LoadInst;
|
||||
class Value;
|
||||
@ -48,6 +49,8 @@ class LazyValueInfo;
|
||||
|
||||
template<typename T> class SmallVectorImpl;
|
||||
|
||||
typedef SmallVector<DbgValueInst *, 1> DbgValueList;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Local constant propagation.
|
||||
//
|
||||
@ -263,6 +266,11 @@ bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
LoadInst *LI, DIBuilder &Builder);
|
||||
|
||||
/// Inserts a llvm.dbg.value intrinsic after a phi of an alloca'd value
|
||||
/// that has an associated llvm.dbg.decl intrinsic.
|
||||
bool ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
PHINode *LI, DIBuilder &Builder);
|
||||
|
||||
/// Lowers llvm.dbg.declare intrinsics into appropriate set of
|
||||
/// llvm.dbg.value intrinsics.
|
||||
bool LowerDbgDeclare(Function &F);
|
||||
@ -270,6 +278,9 @@ bool LowerDbgDeclare(Function &F);
|
||||
/// Finds the llvm.dbg.declare intrinsic corresponding to an alloca, if any.
|
||||
DbgDeclareInst *FindAllocaDbgDeclare(Value *V);
|
||||
|
||||
/// Finds the llvm.dbg.value intrinsics corresponding to an alloca, if any.
|
||||
void FindAllocaDbgValues(DbgValueList &DbgValues, Value *V);
|
||||
|
||||
/// Replaces llvm.dbg.declare instruction when the address it describes
|
||||
/// is replaced with a new value. If Deref is true, an additional DW_OP_deref is
|
||||
/// prepended to the expression. If Offset is non-zero, a constant displacement
|
||||
|
@ -1053,6 +1053,24 @@ static bool LdStHasDebugValue(DILocalVariable *DIVar, DIExpression *DIExpr,
|
||||
return false;
|
||||
}
|
||||
|
||||
/// See if there is a dbg.value intrinsic for DIVar for the PHI node.
|
||||
static bool PhiHasDebugValue(DILocalVariable *DIVar,
|
||||
DIExpression *DIExpr,
|
||||
PHINode *APN) {
|
||||
// Since we can't guarantee that the original dbg.declare instrinsic
|
||||
// is removed by LowerDbgDeclare(), we need to make sure that we are
|
||||
// not inserting the same dbg.value intrinsic over and over.
|
||||
DbgValueList DbgValues;
|
||||
FindAllocaDbgValues(DbgValues, APN);
|
||||
for (auto DVI : DbgValues) {
|
||||
assert (DVI->getValue() == APN);
|
||||
assert (DVI->getOffset() == 0);
|
||||
if ((DVI->getVariable() == DIVar) && (DVI->getExpression() == DIExpr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Inserts a llvm.dbg.value intrinsic before a store to an alloca'd value
|
||||
/// that has an associated llvm.dbg.decl intrinsic.
|
||||
bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
@ -1120,6 +1138,23 @@ bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Inserts a llvm.dbg.value intrinsic after a phi
|
||||
/// that has an associated llvm.dbg.decl intrinsic.
|
||||
bool llvm::ConvertDebugDeclareToDebugValue(DbgDeclareInst *DDI,
|
||||
PHINode *APN, DIBuilder &Builder) {
|
||||
auto *DIVar = DDI->getVariable();
|
||||
auto *DIExpr = DDI->getExpression();
|
||||
assert(DIVar && "Missing variable");
|
||||
|
||||
if (PhiHasDebugValue(DIVar, DIExpr, APN))
|
||||
return true;
|
||||
|
||||
Instruction *DbgValue = Builder.insertDbgValueIntrinsic(
|
||||
APN, 0, DIVar, DIExpr, DDI->getDebugLoc(), (Instruction *)nullptr);
|
||||
DbgValue->insertBefore(&*APN->getParent()->getFirstInsertionPt());
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Determine whether this alloca is either a VLA or an array.
|
||||
static bool isArray(AllocaInst *AI) {
|
||||
return AI->isArrayAllocation() ||
|
||||
@ -1187,6 +1222,16 @@ DbgDeclareInst *llvm::FindAllocaDbgDeclare(Value *V) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// FindAllocaDbgValues - Finds the llvm.dbg.value intrinsics describing the
|
||||
/// alloca 'V', if any.
|
||||
void llvm::FindAllocaDbgValues(DbgValueList &DbgValues, Value *V) {
|
||||
if (auto *L = LocalAsMetadata::getIfExists(V))
|
||||
if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
|
||||
for (User *U : MDV->users())
|
||||
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
|
||||
DbgValues.push_back(DVI);
|
||||
}
|
||||
|
||||
static void DIExprAddDeref(SmallVectorImpl<uint64_t> &Expr) {
|
||||
Expr.push_back(dwarf::DW_OP_deref);
|
||||
}
|
||||
|
@ -907,6 +907,8 @@ NextIteration:
|
||||
|
||||
// The currently active variable for this block is now the PHI.
|
||||
IncomingVals[AllocaNo] = APN;
|
||||
if (DbgDeclareInst *DDI = AllocaDbgDeclares[AllocaNo])
|
||||
ConvertDebugDeclareToDebugValue(DDI, APN, DIB);
|
||||
|
||||
// Get the next phi node.
|
||||
++PNI;
|
||||
|
76
test/Transforms/Util/mem2reg-dbg.ll
Normal file
76
test/Transforms/Util/mem2reg-dbg.ll
Normal file
@ -0,0 +1,76 @@
|
||||
; RUN: opt -mem2reg -S < %s | FileCheck %s
|
||||
|
||||
; Test that a @llvm.dbg.value node is created to describe the value returned by a phi node when
|
||||
; lowering a @llvm.dbg.declare node
|
||||
|
||||
; Created from the C code, compiled with -O0 -g:
|
||||
;
|
||||
; int func(int a)
|
||||
; {
|
||||
; int c = 1;
|
||||
; if (a < 0 ) {
|
||||
; c = 12;
|
||||
; }
|
||||
; return c;
|
||||
; }
|
||||
|
||||
; Function Attrs: nounwind
|
||||
define i32 @func(i32 %a) #0 !dbg !8 {
|
||||
entry:
|
||||
%a.addr = alloca i32, align 4
|
||||
%c = alloca i32, align 4
|
||||
store i32 %a, i32* %a.addr, align 4
|
||||
call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !12, metadata !13), !dbg !14
|
||||
call void @llvm.dbg.declare(metadata i32* %c, metadata !15, metadata !13), !dbg !16
|
||||
store i32 1, i32* %c, align 4, !dbg !16
|
||||
%0 = load i32, i32* %a.addr, align 4, !dbg !17
|
||||
%cmp = icmp slt i32 %0, 0, !dbg !19
|
||||
br i1 %cmp, label %if.then, label %if.end, !dbg !20
|
||||
|
||||
if.then: ; preds = %entry
|
||||
store i32 12, i32* %c, align 4, !dbg !21
|
||||
br label %if.end, !dbg !23
|
||||
|
||||
if.end: ; preds = %if.then, %entry
|
||||
%1 = load i32, i32* %c, align 4, !dbg !24
|
||||
; CHECK: [[PHI:%.*]] = phi i32 [ 12, {{.*}} ], [ 1, {{.*}} ]
|
||||
; CHECK-NEXT: call void @llvm.dbg.value(metadata i32 [[PHI]], i64 0, metadata !15, metadata !13), !dbg !16
|
||||
ret i32 %1, !dbg !25
|
||||
}
|
||||
|
||||
; Function Attrs: nounwind readnone
|
||||
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
|
||||
|
||||
attributes #1 = { nounwind readnone }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5, !6}
|
||||
!llvm.ident = !{!7}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
|
||||
!1 = !DIFile(filename: "a.c", directory: "/tmp")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{i32 1, !"min_enum_size", i32 4}
|
||||
!7 = !{!"clang"}
|
||||
!8 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 1, type: !9, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2)
|
||||
!9 = !DISubroutineType(types: !10)
|
||||
!10 = !{!11, !11}
|
||||
!11 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
|
||||
!12 = !DILocalVariable(name: "a", arg: 1, scope: !8, file: !1, line: 1, type: !11)
|
||||
!13 = !DIExpression()
|
||||
!14 = !DILocation(line: 1, column: 14, scope: !8)
|
||||
!15 = !DILocalVariable(name: "c", scope: !8, file: !1, line: 3, type: !11)
|
||||
!16 = !DILocation(line: 3, column: 6, scope: !8)
|
||||
!17 = !DILocation(line: 4, column: 6, scope: !18)
|
||||
!18 = distinct !DILexicalBlock(scope: !8, file: !1, line: 4, column: 6)
|
||||
!19 = !DILocation(line: 4, column: 8, scope: !18)
|
||||
!20 = !DILocation(line: 4, column: 6, scope: !8)
|
||||
!21 = !DILocation(line: 5, column: 5, scope: !22)
|
||||
!22 = distinct !DILexicalBlock(scope: !18, file: !1, line: 4, column: 14)
|
||||
!23 = !DILocation(line: 6, column: 2, scope: !22)
|
||||
!24 = !DILocation(line: 7, column: 9, scope: !8)
|
||||
!25 = !DILocation(line: 7, column: 2, scope: !8)
|
||||
|
Loading…
Reference in New Issue
Block a user