Skip to content

Commit f8de161

Browse files
authored
[KeyInstr][SimplifyCFG] Remap atoms when folding br to common succ into pred (#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 aec3929 commit f8de161

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
@@ -170,6 +170,16 @@ namespace llvm {
170170
LLVMContext &Ctx,
171171
DenseMap<const MDNode *, MDNode *> &Cache);
172172

173+
/// Return true if the source locations match, ignoring isImplicitCode and
174+
/// source atom info.
175+
bool isSameSourceLocation(const DebugLoc &Other) const {
176+
if (get() == Other.get())
177+
return true;
178+
return ((bool)*this == (bool)Other) && getLine() == Other.getLine() &&
179+
getCol() == Other.getCol() && getScope() == Other.getScope() &&
180+
getInlinedAt() == Other.getInlinedAt();
181+
}
182+
173183
unsigned getLine() const;
174184
unsigned getCol() const;
175185
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"
@@ -1129,13 +1130,17 @@ static void cloneInstructionsIntoPredecessorBlockAndUpdateSSAUses(
11291130

11301131
Instruction *NewBonusInst = BonusInst.clone();
11311132

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

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

11871205
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)