Skip to content

Commit

Permalink
[DebugInfo] Clone dbg.values in SimplifyCFG like normal instructions (#…
Browse files Browse the repository at this point in the history
…72526)

The code in the CloneInstructionsIntoPredec... function modified by this
patch has a long history that dates back to 2011, see d715ec8.
There, when folding branches, all dbg.value intrinsics seen when folding
would be saved and then re-inserted at the end of whatever was folded. Over
the last 12 years this behaviour has been preserved.

However, IMO it's bad behaviour. If we have:

  inst1
  dbg.value1
  inst2
  dbg.value2

And we fold that sequence into a different block, then we would want the
instructions and variable assignments to appear in the same order. However
because of this old behaviour, the dbg.values are sunk, and we get:

  inst1
  inst2
  dbg.value1
  dbg.value2

This clustering of dbg.values can make assignments to the same variable
invisible, as well as reducing the coverage of other assignments.

This patch relaxes the CloneInstructions... function and allows it to clone
and update dbg.values in-place, causing them to appear in the original
order in the destination block. I've added some extra dbg.values to the
updated test: without the changes to the pass, the dbg.values sink into a
blob ahead of the select. The RemoveDIs code can't cope with this right now
so I've removed the "--try..." flag, restored in a commit to land in a
couple of hours.

(Metadata changes to make the LLVM-IR parser not drop the debug-info for it
being out of date. The RemoveDIs related RUN line has been removed because
it was spuriously passing due to the debug-info being dropped).
  • Loading branch information
jmorse committed Nov 24, 2023
1 parent e8cd401 commit 84f6e1d
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 27 deletions.
21 changes: 8 additions & 13 deletions llvm/lib/Transforms/Utils/SimplifyCFG.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1101,12 +1101,13 @@ static void CloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
// Note that there may be multiple predecessor blocks, so we cannot move
// bonus instructions to a predecessor block.
for (Instruction &BonusInst : *BB) {
if (isa<DbgInfoIntrinsic>(BonusInst) || BonusInst.isTerminator())
if (BonusInst.isTerminator())
continue;

Instruction *NewBonusInst = BonusInst.clone();

if (PTI->getDebugLoc() != NewBonusInst->getDebugLoc()) {
if (!isa<DbgInfoIntrinsic>(BonusInst) &&
PTI->getDebugLoc() != NewBonusInst->getDebugLoc()) {
// Unless the instruction has the same !dbg location as the original
// branch, drop it. When we fold the bonus instructions we want to make
// sure we reset their debug locations in order to avoid stepping on
Expand All @@ -1116,7 +1117,6 @@ static void CloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(

RemapInstruction(NewBonusInst, VMap,
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
VMap[&BonusInst] = NewBonusInst;

// If we speculated an instruction, we need to drop any metadata that may
// result in undefined behavior, as the metadata might have been valid
Expand All @@ -1126,8 +1126,13 @@ static void CloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
NewBonusInst->dropUBImplyingAttrsAndMetadata();

NewBonusInst->insertInto(PredBlock, PTI->getIterator());

if (isa<DbgInfoIntrinsic>(BonusInst))
continue;

NewBonusInst->takeName(&BonusInst);
BonusInst.setName(NewBonusInst->getName() + ".old");
VMap[&BonusInst] = NewBonusInst;

// Update (liveout) uses of bonus instructions,
// now that the bonus instruction has been cloned into predecessor.
Expand Down Expand Up @@ -3749,16 +3754,6 @@ static bool performBranchToCommonDestFolding(BranchInst *BI, BranchInst *PBI,
PBI->setCondition(
createLogicalOp(Builder, Opc, PBI->getCondition(), BICond, "or.cond"));

// Copy any debug value intrinsics into the end of PredBlock.
for (Instruction &I : *BB) {
if (isa<DbgInfoIntrinsic>(I)) {
Instruction *NewI = I.clone();
RemapInstruction(NewI, VMap,
RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
NewI->insertBefore(PBI);
}
}

++NumFoldBranchToCommonDest;
return true;
}
Expand Down
35 changes: 21 additions & 14 deletions llvm/test/Transforms/SimplifyCFG/branch-fold-dbg.ll
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s
; RUN: opt -passes=simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s --try-experimental-debuginfo-iterators | FileCheck %s

%0 = type { ptr, ptr }

Expand All @@ -9,23 +8,26 @@
define i1 @foo(i32) nounwind ssp !dbg !0 {
; CHECK-LABEL: @foo(
; CHECK-NEXT: Entry:
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0:%.*]], 0
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP0]], 4
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TMP1]], [[TMP2]]
; CHECK-NEXT: br i1 [[OR_COND]], label [[COMMON_RET:%.*]], label [[BB2:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[TMP0:%.*]], 0, !dbg [[DBG7:![0-9]+]]
; CHECK-NEXT: [[TMP2:%.*]] = icmp sgt i32 [[TMP0]], 4, !dbg [[DBG7]]
; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[TMP1]], [[TMP2]], !dbg [[DBG7]]
; CHECK-NEXT: br i1 [[OR_COND]], label [[COMMON_RET:%.*]], label [[BB2:%.*]], !dbg [[DBG7]]
; CHECK: BB2:
; CHECK-NEXT: [[TMP3:%.*]] = shl i32 1, [[TMP0]]
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 31
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0
; CHECK-NEXT: [[TMP3:%.*]] = shl i32 1, [[TMP0]], !dbg [[DBG7]]
; CHECK-NEXT: [[TMP4:%.*]] = and i32 [[TMP3]], 31, !dbg [[DBG7]]
; CHECK-NEXT: [[TMP5:%.*]] = icmp eq i32 [[TMP4]], 0, !dbg [[DBG7]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr null, metadata [[META8:![0-9]+]], metadata !DIExpression()), !dbg [[DBG13:![0-9]+]]
; CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [5 x %0], ptr @[[GLOB0:[0-9]+]], i32 0, i32 [[TMP0]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[TMP6]], metadata [[META8]], metadata !DIExpression()), !dbg [[DBG13]]
; CHECK-NEXT: [[TMP7:%.*]] = icmp eq ptr [[TMP6]], null
; CHECK-NEXT: [[OR_COND2:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP7]]
; CHECK-NEXT: call void @llvm.dbg.value(metadata ptr [[TMP6]], metadata [[META8]], metadata !DIExpression()), !dbg [[DBG13]]
; CHECK-NEXT: [[OR_COND2:%.*]] = select i1 [[TMP5]], i1 true, i1 [[TMP7]], !dbg [[DBG7]]
; CHECK-NEXT: [[TMP8:%.*]] = icmp slt i32 [[TMP0]], 0
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 [[TMP8]]
; CHECK-NEXT: br label [[COMMON_RET]]
; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[OR_COND2]], i1 false, i1 [[TMP8]], !dbg [[DBG7]]
; CHECK-NEXT: br label [[COMMON_RET]], !dbg [[DBG7]]
; CHECK: common.ret:
; CHECK-NEXT: [[COMMON_RET_OP:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[SPEC_SELECT]], [[BB2]] ]
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]]
; CHECK-NEXT: ret i1 [[COMMON_RET_OP]], !dbg [[DBG14:![0-9]+]]
;
Entry:
%1 = icmp slt i32 %0, 0, !dbg !5
Expand All @@ -43,9 +45,11 @@ BB2: ; preds = %BB1


BB3: ; preds = %BB2
call void @llvm.dbg.value(metadata ptr null, metadata !7, metadata !DIExpression()), !dbg !12
%6 = getelementptr inbounds [5 x %0], ptr @0, i32 0, i32 %0, !dbg !6
call void @llvm.dbg.value(metadata ptr %6, metadata !7, metadata !{}), !dbg !12
call void @llvm.dbg.value(metadata ptr %6, metadata !7, metadata !DIExpression()), !dbg !12
%7 = icmp eq ptr %6, null, !dbg !13
call void @llvm.dbg.value(metadata ptr %6, metadata !7, metadata !DIExpression()), !dbg !12
br i1 %7, label %BB5, label %BB4, !dbg !13

BB4: ; preds = %BB3
Expand All @@ -59,12 +63,13 @@ BB5: ; preds = %BB3, %BB2, %BB1, %E
declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone

!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!16, !17}

!0 = distinct !DISubprogram(name: "foo", line: 231, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !2, file: !15, scope: !1, type: !3)
!1 = !DIFile(filename: "a.c", directory: "/private/tmp")
!2 = distinct !DICompileUnit(language: DW_LANG_C99, producer: "clang (trunk 129006)", isOptimized: true, emissionKind: FullDebug, file: !15, enums: !4, retainedTypes: !4)
!3 = !DISubroutineType(types: !4)
!4 = !{null}
!4 = !{}
!5 = !DILocation(line: 131, column: 2, scope: !0)
!6 = !DILocation(line: 134, column: 2, scope: !0)
!7 = !DILocalVariable(name: "bar", line: 232, scope: !8, file: !1, type: !9)
Expand All @@ -76,3 +81,5 @@ declare void @llvm.dbg.value(metadata, metadata, metadata) nounwind readnone
!13 = !DILocation(line: 234, column: 2, scope: !8)
!14 = !DILocation(line: 274, column: 1, scope: !8)
!15 = !DIFile(filename: "a.c", directory: "/private/tmp")
!16 = !{i32 1, !"Debug Info Version", i32 3}
!17 = !{i32 2, !"Dwarf Version", i32 4}

0 comments on commit 84f6e1d

Please sign in to comment.