I’ve been trying to track down a redundant debug line-table entry, and it looks to me like a branch under an ‘if’ statement ends up with the wrong scope.
Here’s my example:
float distance = 1.0f;
int main(void)
{
if (distance > 0.01f)
return 1;
return 0;
}
The thing to notice is that there are two scopes here: there’s the function scope, and then there’s a scope for the ‘if’ statement. Nothing exciting happens in this particular ‘if’ statement but the scope is still there. The problem comes with the IR:
%0 = load float, ptr @distance, align 4, !dbg !18 ; block scope
%cmp = fcmp ogt float %0, 0x3F847AE140000000, !dbg !20 ; block scope
br i1 %cmp, label %if.then, label %if.end, !dbg !21 ; *** function scope ***
if.then: ; preds = %entry
store i32 1, ptr %retval, align 4, !dbg !22 ; block scope
br label %return, !dbg !22
if.end: ; preds = %entry
store i32 0, ptr %retval, align 4, !dbg !23 ; function scope
br label %return, !dbg !23
!14 = distinct !DISubprogram(... the usual stuff ...)
!18 = !DILocation(line: 4, column: 7, scope: !19)
!19 = distinct !DILexicalBlock(scope: !14, file: !3, line: 4, column: 7)
!20 = !DILocation(line: 4, column: 16, scope: !19)
!21 = !DILocation(line: 4, column: 7, scope: !14)
!22 = !DILocation(line: 5, column: 5, scope: !19)
!23 = !DILocation(line: 6, column: 3, scope: !14)
The conditional branch does not have ‘if’-statement scope, it has function scope.
Well, so what? Well, that difference in scope tracks all the way down into LLVM code generation, where it causes a redundant line-table entry:
.Ltmp0:
.loc 0 4 7 prologue_end # tc13837.cpp:4:7
movss distance(%rip), %xmm0 # xmm0 = mem[0],zero,zero,zero
.Ltmp1:
.loc 0 4 7 is_stmt 0 # tc13837.cpp:4:7 # *** redundant ***
movss .LCPI0_0(%rip), %xmm1 # xmm1 = [9.99999977E-3,0.0E+0,0.0E+0,0.0E+0]
.Ltmp2:
.loc 0 4 16 # tc13837.cpp:4:16
ucomiss %xmm1, %xmm0
.Ltmp3:
.loc 0 4 7 # tc13837.cpp:4:7
jbe .LBB0_2
If I hack the scope in the IR metadata, that extra .loc directive goes away.
I’ve been trying to track down where the incorrect dbg metadata gets attached. It’s been easy enough to find CodeGenFunction::EmitIfStmt, which uses CodeGenFunction::EmitBranchOnBoolExpr to do the heavy lifting, which then ends with
Builder.CreateCondBr(CondV, TrueBlock, FalseBlock, Weights, Unpredictable);
which in turn is basically a call to BranchInst::Create
, which… I cannot find.
If someone can tell me where this method is hiding, or (even better) what is likely to be the source of the incorrect scope, that would be lovely.
(The issue is very likely in Clang, not LLVM, but it won’t be possible to figure that out until I can see how the branch gets created and where the !dbg record comes from.)