This is an archive of the discontinued LLVM Phabricator instance.

[IndVarSimplify][DebugLoc] When widening the IV increment, correctly set the debug loc.
ClosedPublic

Authored by andreadb on Oct 21 2016, 7:34 AM.

Details

Summary

When indvars creates a wide induction variable, the debug location for the loop increment is incorrect (see below):

Example:

extern int foo(int);

int bar(int x, int *a)
  for (int i = 0; i < x; ++i)      // line 4
    a[i] = foo(i);

  return a[0];
}

Before indvars is run, the IV (induction variable) increment is performed in the loop latch at line 4:

%inc = add nsw i32 %i.06, 1, !dbg !13

Where, %i.06 is our IV, and !dbg !13 is a DILocation which refers to line 4, discriminator 2.

After indvars is run, our IV is expanded into:

%indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %for.body.lr.ph]

In particular, %indvars.iv.next is defined by instruction:

%indvars.iv.next = add nuw nsw i64 %indvars.iv, 1, !dbg !9

However, !dbg !9 is the debug loc for line 4, discriminator 1. It should have been line 4, discriminator 2.

This patch fixes the issue by propagating the correct debug location from the original loop increment instruction to the new widened increment.

Please let me know if okay to commit.

Thanks,
Andrea

Diff Detail

Repository
rL LLVM

Event Timeline

andreadb updated this revision to Diff 75424.Oct 21 2016, 7:34 AM
andreadb retitled this revision from to [IndVarSimplify][DebugLoc] When widening the IV increment, correctly set the debug loc..
andreadb updated this object.
andreadb added a subscriber: llvm-commits.

Hi David,

On Fri, Oct 21, 2016 at 3:54 PM, David Blaikie <dblaikie@gmail.com> wrote:

I assume we would see this is a pure debug quality bug if you split the for loop header over multiple lines? (so it wasn't just a discriminator bug)?

You are correct. It is a debug quality issue, and the problem would be more evident if the loop increment is on a different line.

Which instruction/part of the loop header is it taking the line 4/disc 1 from?

It is the SCEVExpander. In particular, it is method SCEVExpander::getAddRecExprPHILiterally().

(sorry for the long explanation. I don't know how to explain it briefly since the logic is quite convoluted...)

What happens is that we delegate to the SCEVExpander the expansion of a IV phi node. We do this by by calling method 'expandCodeFor()' on the SCEVExpander object. When we call it, the normalized SCEV for the reproducible is: {0,+,1}<nuw><nsw><%for.body>.

The SCEVExpander firstly generates code for the expanded 'start' value. In our example, the start value is constant 0, so the expander doesn't have to insert new computation in the loop preheader.
Then SCEVExpander expands the code for the 'step' value. The step value is also a constant, so no extra code is inserted in the loop body. At this point, the algorithm creates a new phi node with no incoming values; the idea is that we populate the new phi node with the "expanded" 'start' value and the widened step instruction.

The logic that populates the phi node is in method 'SCEVExpander::getAddRecExprPHILiterally()' at around lines 1221:1245.
For each loop header predecessor, the algorithm adds a widened incoming value. In the case of the loop latch basic block, the insertion point for the IRBUilder points to the end of the loop latch block (Pred->getTerminator()). That means, the new IV increment will automatically obtain the debug location from Pred->getTerminator().

In our example, Pred->getTerminator() is:

br i1 %cmp, label %for.body, label %for.cond.for.end_crit_edge, !dbg !9

Where !dbg !9 is DILocation(line 4, column 3, scope !8).
!8 is a !DILexicalBlockFile with discriminator 1.

That explains why the widen IV increment is associated to line 4, discriminator 1.

I couldn't find a reasonable way to get the debug loc associated to the original loop increment from inside method getAddRecExprPHILiterally(). So, I eventually opted for this simpler patch.

Again, sorry for the long explanation.
I hope this makes sense.

-Andrea

aprantl accepted this revision.Oct 25 2016, 9:14 AM
aprantl edited edge metadata.

Seems fine to me.

Out of curiosity: Does the SCE debugger make use of DWARF discriminators? Or is this used for profiling?

This revision is now accepted and ready to land.Oct 25 2016, 9:14 AM

Seems fine to me.

Out of curiosity: Does the SCE debugger make use of DWARF discriminators? Or is this used for profiling?

Thanks Adrian and David!

I have asked to the debugger team. They just told me that tehy currently don't use discriminators. We currently use them only for profiling.

This revision was automatically updated to reflect the committed changes.