Skip to content

Commit 7ba2ca7

Browse files
committed
[KeyInstr][SimplifyCFG] Remap atoms when folding br to common succ into pred (llvm#133482)
SimplifyCFG folds `d` into preds `b` and `c`. +---------------+ | | +--> b --+ | | v v --> a d --> e --> f --> | ^ ^ +--> c --+ | | | +---------------+ Remap source atoms so that the duplicated instructions are analysed independently to determine is_stmt positions. The pull request contains a discussion covering various edge cases here: https://github.com/llvm/llvm-project/pull/133482/files#r2039519348 The summary of the discussion is that we could avoid remapping when there's a single pred, but we decided that it's still a trade off, and not worth the additional complexity right now. RFC: https://discourse.llvm.org/t/rfc-improving-is-stmt-placement-for-better-interactive-debugging/82668
1 parent f21aefc commit 7ba2ca7

File tree

3 files changed

+126
-7
lines changed

3 files changed

+126
-7
lines changed

llvm/include/llvm/IR/DebugLoc.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,16 @@ namespace llvm {
7676
LLVMContext &Ctx,
7777
DenseMap<const MDNode *, MDNode *> &Cache);
7878

79+
/// Return true if the source locations match, ignoring isImplicitCode and
80+
/// source atom info.
81+
bool isSameSourceLocation(const DebugLoc &Other) const {
82+
if (get() == Other.get())
83+
return true;
84+
return ((bool)*this == (bool)Other) && getLine() == Other.getLine() &&
85+
getCol() == Other.getCol() && getScope() == Other.getScope() &&
86+
getInlinedAt() == Other.getInlinedAt();
87+
}
88+
7989
unsigned getLine() const;
8090
unsigned getCol() const;
8191
MDNode *getScope() const;

llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
#include "llvm/Support/MathExtras.h"
7474
#include "llvm/Support/raw_ostream.h"
7575
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
76+
#include "llvm/Transforms/Utils/Cloning.h"
7677
#include "llvm/Transforms/Utils/Local.h"
7778
#include "llvm/Transforms/Utils/LockstepReverseIterator.h"
7879
#include "llvm/Transforms/Utils/ValueMapper.h"
@@ -1127,13 +1128,17 @@ static void cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
11271128

11281129
Instruction *NewBonusInst = BonusInst.clone();
11291130

1130-
if (!isa<DbgInfoIntrinsic>(BonusInst) &&
1131-
PTI->getDebugLoc() != NewBonusInst->getDebugLoc()) {
1132-
// Unless the instruction has the same !dbg location as the original
1133-
// branch, drop it. When we fold the bonus instructions we want to make
1134-
// sure we reset their debug locations in order to avoid stepping on
1135-
// dead code caused by folding dead branches.
1136-
NewBonusInst->setDebugLoc(DebugLoc());
1131+
if (!isa<DbgInfoIntrinsic>(BonusInst)) {
1132+
if (!NewBonusInst->getDebugLoc().isSameSourceLocation(
1133+
PTI->getDebugLoc())) {
1134+
// Unless the instruction has the same !dbg location as the original
1135+
// branch, drop it. When we fold the bonus instructions we want to make
1136+
// sure we reset their debug locations in order to avoid stepping on
1137+
// dead code caused by folding dead branches.
1138+
NewBonusInst->setDebugLoc(DebugLoc());
1139+
} else if (const DebugLoc &DL = NewBonusInst->getDebugLoc()) {
1140+
mapAtomInstance(DL, VMap);
1141+
}
11371142
}
11381143

11391144
RemapInstruction(NewBonusInst, VMap,
@@ -1180,6 +1185,19 @@ static void cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
11801185
U.set(NewBonusInst);
11811186
}
11821187
}
1188+
1189+
// Key Instructions: We may have propagated atom info into the pred. If the
1190+
// pred's terminator already has atom info do nothing as merging would drop
1191+
// one atom group anyway. If it doesn't, propagte the remapped atom group
1192+
// from BB's terminator.
1193+
if (auto &PredDL = PTI->getDebugLoc()) {
1194+
auto &DL = BB->getTerminator()->getDebugLoc();
1195+
if (!PredDL->getAtomGroup() && DL && DL->getAtomGroup() &&
1196+
PredDL.isSameSourceLocation(DL)) {
1197+
PTI->setDebugLoc(DL);
1198+
RemapSourceAtom(PTI, VMap);
1199+
}
1200+
}
11831201
}
11841202

11851203
bool SimplifyCFGOpt::performValueComparisonIntoPredecessorFolding(
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt %s -S -passes=simplifycfg -bonus-inst-threshold=2 | FileCheck %s
3+
4+
;; +---------------+
5+
;; | |
6+
;; +--> b --+ |
7+
;; | v v
8+
;; --> a d --> e --> f -->
9+
;; | ^ ^
10+
;; +--> c --+ |
11+
;; | |
12+
;; +---------------+
13+
14+
;; Block d gets folded into preds b and c. Check the cloned instructions get
15+
;; remapped DILocation atomGroup numbers in each of the preds. Additionally
16+
;; check that the branches each inherit the atomGroup of the folded branch.
17+
18+
declare i32 @g(...)
19+
define void @f(i1 %c0, i1 %c1, i1 %c2, i32 %x, i32 %y) !dbg !17 {
20+
; CHECK-LABEL: define void @f(
21+
; CHECK-SAME: i1 [[C0:%.*]], i1 [[C1:%.*]], i1 [[C2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) !dbg [[DBG6:![0-9]+]] {
22+
; CHECK-NEXT: [[A:.*:]]
23+
; CHECK-NEXT: br i1 [[C0]], label %[[B:.*]], label %[[C:.*]]
24+
; CHECK: [[B]]:
25+
; CHECK-NEXT: [[AND_OLD:%.*]] = and i32 [[X]], [[Y]], !dbg [[DBG8:![0-9]+]]
26+
; CHECK-NEXT: [[CMP_OLD:%.*]] = icmp eq i32 [[AND_OLD]], 0, !dbg [[DBG9:![0-9]+]]
27+
; CHECK-NEXT: [[OR_COND1:%.*]] = select i1 [[C1]], i1 true, i1 [[CMP_OLD]], !dbg [[DBG10:![0-9]+]]
28+
; CHECK-NEXT: br i1 [[OR_COND1]], label %[[F:.*]], label %[[E:.*]], !dbg [[DBG11:![0-9]+]]
29+
; CHECK: [[C]]:
30+
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[Y]], !dbg [[DBG12:![0-9]+]]
31+
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], 0, !dbg [[DBG13:![0-9]+]]
32+
; CHECK-NEXT: [[OR_COND:%.*]] = select i1 [[C2]], i1 true, i1 [[CMP]], !dbg [[DBG10]]
33+
; CHECK-NEXT: br i1 [[OR_COND]], label %[[F]], label %[[E]], !dbg [[DBG14:![0-9]+]]
34+
; CHECK: [[E]]:
35+
; CHECK-NEXT: [[TMP0:%.*]] = tail call i32 (...) @g()
36+
; CHECK-NEXT: br label %[[F]]
37+
; CHECK: [[F]]:
38+
; CHECK-NEXT: ret void
39+
;
40+
a:
41+
br i1 %c0, label %b, label %c
42+
43+
b:
44+
br i1 %c1, label %f, label %d, !dbg !18
45+
46+
c:
47+
br i1 %c2, label %f, label %d, !dbg !18
48+
49+
d:
50+
%and = and i32 %x, %y, !dbg !19
51+
%cmp = icmp eq i32 %and, 0, !dbg !20
52+
br i1 %cmp, label %f, label %e, !dbg !21
53+
54+
e:
55+
%7 = tail call i32 (...) @g()
56+
br label %f
57+
58+
f:
59+
ret void
60+
}
61+
62+
!llvm.dbg.cu = !{!0}
63+
!llvm.debugify = !{!3, !4}
64+
!llvm.module.flags = !{!5}
65+
66+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
67+
!1 = !DIFile(filename: "a.ll", directory: "/")
68+
!2 = !{}
69+
!3 = !{i32 9}
70+
!4 = !{i32 0}
71+
!5 = !{i32 2, !"Debug Info Version", i32 3}
72+
!7 = !DISubroutineType(types: !2)
73+
!17 = distinct !DISubprogram(name: "f", scope: null, file: !1, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2)
74+
!18 = !DILocation(line: 10, column: 10, scope: !17)
75+
!19 = !DILocation(line: 10, column: 10, scope: !17, atomGroup: 1, atomRank: 2)
76+
!20 = !DILocation(line: 10, column: 10, scope: !17, atomGroup: 2, atomRank: 2)
77+
!21 = !DILocation(line: 10, column: 10, scope: !17, atomGroup: 2, atomRank: 1)
78+
;.
79+
; CHECK: [[META0:![0-9]+]] = distinct !DICompileUnit(language: DW_LANG_C, file: [[META1:![0-9]+]], producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: [[META2:![0-9]+]])
80+
; CHECK: [[META1]] = !DIFile(filename: "a.ll", directory: {{.*}})
81+
; CHECK: [[META2]] = !{}
82+
; CHECK: [[DBG6]] = distinct !DISubprogram(name: "f", scope: null, file: [[META1]], line: 1, type: [[META7:![0-9]+]], scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: [[META0]], retainedNodes: [[META2]])
83+
; CHECK: [[META7]] = !DISubroutineType(types: [[META2]])
84+
; CHECK: [[DBG8]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 5, atomRank: 2)
85+
; CHECK: [[DBG9]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 6, atomRank: 2)
86+
; CHECK: [[DBG10]] = !DILocation(line: 10, column: 10, scope: [[DBG6]])
87+
; CHECK: [[DBG11]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 6, atomRank: 1)
88+
; CHECK: [[DBG12]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 3, atomRank: 2)
89+
; CHECK: [[DBG13]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 4, atomRank: 2)
90+
; CHECK: [[DBG14]] = !DILocation(line: 10, column: 10, scope: [[DBG6]], atomGroup: 4, atomRank: 1)
91+
;.

0 commit comments

Comments
 (0)