From: Sam Parker Date: Wed, 8 Mar 2017 09:56:22 +0000 (+0000) Subject: [LoopRotate] Propagate dbg.value intrinsics X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0bf7b18461d86136f19b78d041faa46f567baa67;p=llvm [LoopRotate] Propagate dbg.value intrinsics Recommitting patch which was previously reverted in r297159. These changes should address the casting issues. The original patch enables dbg.value intrinsics to be attached to newly inserted PHI nodes. Differential Review: https://reviews.llvm.org/D30701 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297269 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Scalar/LoopRotation.cpp b/lib/Transforms/Scalar/LoopRotation.cpp index 0d57ce1e827..e5689368de8 100644 --- a/lib/Transforms/Scalar/LoopRotation.cpp +++ b/lib/Transforms/Scalar/LoopRotation.cpp @@ -79,7 +79,8 @@ private: /// to merge the two values. Do this now. static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, BasicBlock *OrigPreheader, - ValueToValueMapTy &ValueMap) { + ValueToValueMapTy &ValueMap, + SmallVectorImpl *InsertedPHIs) { // Remove PHI node entries that are no longer live. BasicBlock::iterator I, E = OrigHeader->end(); for (I = OrigHeader->begin(); PHINode *PN = dyn_cast(I); ++I) @@ -87,7 +88,7 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, // Now fix up users of the instructions in OrigHeader, inserting PHI nodes // as necessary. - SSAUpdater SSA; + SSAUpdater SSA(InsertedPHIs); for (I = OrigHeader->begin(); I != E; ++I) { Value *OrigHeaderVal = &*I; @@ -174,6 +175,38 @@ static void RewriteUsesOfClonedInstructions(BasicBlock *OrigHeader, } } +/// Propagate dbg.value intrinsics through the newly inserted Phis. +static void insertDebugValues(BasicBlock *OrigHeader, + SmallVectorImpl &InsertedPHIs) { + ValueToValueMapTy DbgValueMap; + + // Map existing PHI nodes to their dbg.values. + for (auto &I : *OrigHeader) { + if (auto DbgII = dyn_cast(&I)) { + if (auto *Loc = dyn_cast_or_null(DbgII->getVariableLocation())) + DbgValueMap.insert({Loc, DbgII}); + } + } + + // Then iterate through the new PHIs and look to see if they use one of the + // previously mapped PHIs. If so, insert a new dbg.value intrinsic that will + // propagate the info through the new PHI. + LLVMContext &C = OrigHeader->getContext(); + for (auto PHI : InsertedPHIs) { + for (auto VI : PHI->operand_values()) { + auto V = DbgValueMap.find(VI); + if (V != DbgValueMap.end()) { + auto *DbgII = cast(V->second); + Instruction *NewDbgII = DbgII->clone(); + auto PhiMAV = MetadataAsValue::get(C, ValueAsMetadata::get(PHI)); + NewDbgII->setOperand(0, PhiMAV); + BasicBlock *Parent = PHI->getParent(); + NewDbgII->insertBefore(Parent->getFirstNonPHIOrDbgOrLifetime()); + } + } + } +} + /// Rotate loop LP. Return true if the loop is rotated. /// /// \param SimplifiedLatch is true if the latch was just folded into the final @@ -347,9 +380,18 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // remove the corresponding incoming values from the PHI nodes in OrigHeader. LoopEntryBranch->eraseFromParent(); + + SmallVector InsertedPHIs; // If there were any uses of instructions in the duplicated block outside the // loop, update them, inserting PHI nodes as required - RewriteUsesOfClonedInstructions(OrigHeader, OrigPreheader, ValueMap); + RewriteUsesOfClonedInstructions(OrigHeader, OrigPreheader, ValueMap, + &InsertedPHIs); + + // Attach dbg.value intrinsics to the new phis if that phi uses a value that + // previously had debug metadata attached. This keeps the debug info + // up-to-date in the loop body. + if (!InsertedPHIs.empty()) + insertDebugValues(OrigHeader, InsertedPHIs); // NewHeader is now the header of the loop. L->moveToHeader(NewHeader); diff --git a/test/Transforms/LoopRotate/phi-dbgvalue.ll b/test/Transforms/LoopRotate/phi-dbgvalue.ll new file mode 100644 index 00000000000..aa8ca2f627b --- /dev/null +++ b/test/Transforms/LoopRotate/phi-dbgvalue.ll @@ -0,0 +1,79 @@ +; RUN: opt -S -loop-rotate < %s | FileCheck %s + +;CHECK-LABEL: func +;CHECK-LABEL: entry +;CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 %a +;CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 1, i64 0, metadata !13, metadata !11), !dbg !15 +;CHECK-LABEL: for.body: +;CHECK-NEXT: [[I:%.*]] = phi i32 [ 1, %entry ], [ %inc, %for.body ] +;CHECK-NEXT: tail call void @llvm.dbg.value(metadata i32 [[I]], i64 0, metadata !13, metadata !11), !dbg !15 + +; Function Attrs: noinline nounwind +define void @func(i32 %a) local_unnamed_addr #0 !dbg !6 { +entry: + tail call void @llvm.dbg.value(metadata i32 %a, i64 0, metadata !10, metadata !11), !dbg !12 + tail call void @llvm.dbg.value(metadata i32 1, i64 0, metadata !13, metadata !11), !dbg !15 + br label %for.cond, !dbg !16 + +for.cond: ; preds = %for.body, %entry + %i.0 = phi i32 [ 1, %entry ], [ %inc, %for.body ] + tail call void @llvm.dbg.value(metadata i32 %i.0, i64 0, metadata !13, metadata !11), !dbg !15 + %cmp = icmp slt i32 %i.0, 10, !dbg !17 + br i1 %cmp, label %for.body, label %for.end, !dbg !20 + +for.body: ; preds = %for.cond + %add = add nsw i32 %i.0, %a, !dbg !22 + %call = tail call i32 @func2(i32 %i.0, i32 %add) #3, !dbg !24 + %inc = add nsw i32 %i.0, 1, !dbg !25 + tail call void @llvm.dbg.value(metadata i32 %inc, i64 0, metadata !13, metadata !11), !dbg !15 + br label %for.cond, !dbg !27, !llvm.loop !28 + +for.end: ; preds = %for.cond + ret void, !dbg !31 +} + +declare i32 @func2(i32, i32) local_unnamed_addr + +; Function Attrs: nounwind readnone +declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2 + +attributes #0 = { noinline nounwind } +attributes #2 = { nounwind readnone } +attributes #3 = { nounwind } + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4} +!llvm.ident = !{!5} + +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 5.0.0 (http://llvm.org/git/clang.git 0f3ed908c1f13f83da4b240f7595eb8d05e0a754) (http://llvm.org/git/llvm.git 8e270f5a6b8ceb0f3ac3ef1ffb83c5e29b44ae68)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) +!1 = !DIFile(filename: "debug-phi.c", directory: "/work/projects/src/tests/debug") +!2 = !{} +!3 = !{i32 2, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{!"clang version 5.0.0 (http://llvm.org/git/clang.git 0f3ed908c1f13f83da4b240f7595eb8d05e0a754) (http://llvm.org/git/llvm.git 8e270f5a6b8ceb0f3ac3ef1ffb83c5e29b44ae68)"} +!6 = distinct !DISubprogram(name: "func", scope: !1, file: !1, line: 2, type: !7, isLocal: false, isDefinition: true, scopeLine: 2, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!7 = !DISubroutineType(types: !8) +!8 = !{null, !9} +!9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) +!10 = !DILocalVariable(name: "a", arg: 1, scope: !6, file: !1, line: 2, type: !9) +!11 = !DIExpression() +!12 = !DILocation(line: 2, column: 15, scope: !6) +!13 = !DILocalVariable(name: "i", scope: !14, file: !1, line: 3, type: !9) +!14 = distinct !DILexicalBlock(scope: !6, file: !1, line: 3, column: 3) +!15 = !DILocation(line: 3, column: 11, scope: !14) +!16 = !DILocation(line: 3, column: 7, scope: !14) +!17 = !DILocation(line: 3, column: 20, scope: !18) +!18 = !DILexicalBlockFile(scope: !19, file: !1, discriminator: 1) +!19 = distinct !DILexicalBlock(scope: !14, file: !1, line: 3, column: 3) +!20 = !DILocation(line: 3, column: 3, scope: !21) +!21 = !DILexicalBlockFile(scope: !14, file: !1, discriminator: 1) +!22 = !DILocation(line: 4, column: 15, scope: !23) +!23 = distinct !DILexicalBlock(scope: !19, file: !1, line: 3, column: 31) +!24 = !DILocation(line: 4, column: 5, scope: !23) +!25 = !DILocation(line: 3, column: 27, scope: !26) +!26 = !DILexicalBlockFile(scope: !19, file: !1, discriminator: 2) +!27 = !DILocation(line: 3, column: 3, scope: !26) +!28 = distinct !{!28, !29, !30} +!29 = !DILocation(line: 3, column: 3, scope: !14) +!30 = !DILocation(line: 5, column: 3, scope: !14) +!31 = !DILocation(line: 6, column: 1, scope: !6)