[llvm] [DebugInfo][SimpleLoopUnswitch] Fix missing debug location updates (PR #97662)
Shan Huang via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 8 08:18:55 PDT 2024
================
@@ -0,0 +1,75 @@
+; RUN: opt -passes='simple-loop-unswitch<nontrivial>' -S < %s | FileCheck %s
+
+define i32 @basic(i32 %N, i1 %cond, i32 %select_input) !dbg !5 {
+; CHECK-LABEL: define i32 @basic(
+
+; Check that SimpleLoopUnswitch's unswitchNontrivialInvariants() drops the
+; debug location of the hoisted terminator and doesn't give any debug location
+; to the new freeze, since it's inserted in a hoist block.
+; Also check that in unswitchNontrivialInvariants(), the new br instruction
+; inherits the debug location of the old terminator in the same block.
+
+; CHECK: entry:
+; CHECK-NEXT: [[COND_FR:%.*]] = freeze i1 [[COND:%.*]]{{$}}
+; CHECK-NEXT: br i1 [[COND_FR]], label %[[ENTRY_SPLIT_US:.*]], label %[[ENTRY_SPLIT:.*]]{{$}}
----------------
Apochens wrote:
This transformation is corresponding to the code change `TI.dropLocation()`. I traced the originality of `TI`:
(1) it the argument of function `unswitchNontrivialInvariants()`;
```cpp
static void unswitchNontrivialInvariants(
Loop &L, Instruction &TI, ...)
```
(2) The function `unswitchNontrivialInvariants()` is called in function `unswitchBestCondition()`, and the `TI` argument takes `*Best.TI`. `Best` is the result of the function call to `findBestNonTrivialUnswitchCandidate()`, which return the best candidate from `UnswitchCandidates`. And `UnswitchCandidates` are collected by calling the function `collectUnswitchCandidates()`;
```cpp
static bool unswitchBestCondition(...) {
...
collectUnswitchCandidates(UnswitchCandidates, ...);
...
NonTrivialUnswitchCandidate Best =
findBestNonTrivialUnswitchCandidate(UnswitchCandidates, ...);
...
-> unswitchNontrivialInvariants(L, *Best.TI, ... );
}
```
(3) In function `collectUnswitchCandidates()`, instructions satisfying certain conditions will be added into `UnswitchCandidates`. According to the code, instructions added into `UnswitchCandidates` are all in the loop, including instructions in the header of the loop (the code it too long to paste it here, see [L2912-2964](https://github.com/llvm/llvm-project/blob/385118644ccabe27a634804c7db60734746c170f/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp#L2912)).
To sum up, the conditional branch is essentially the hoisted instruction in the loop (it could be a `select`, a `branch`, or a `switch` according to the code).
> Glancing at the IR, the old behaviour (new cond branch gets uncond branch location) looks fine
Acctually, the new cond branch did not get the location of uncond branch. Before the dropping, there is no location propagation from the uncond branch to the new cond branch. See the following snippets ([godbolt](https://godbolt.org/z/3qa8PxoTc)). (Hope I understand `the old branch` right.)
```LLVM IR
entry:
br label %for.cond, !dbg !8
!8 = !DILocation(line: 1, column: 1, scope: !5)
```
```LLVM IR
entry:
%cond.fr = freeze i1 %cond
br i1 %cond.fr, label %entry.split.us, label %entry.split, !dbg !8
!8 = !DILocation(line: 6, column: 1, scope: !5)
```
https://github.com/llvm/llvm-project/pull/97662
More information about the llvm-commits
mailing list