This is an archive of the discontinued LLVM Phabricator instance.

[Transform][MemCpyOpt] Add missing DebugLoc to %tmpbitcast
ClosedPublic

Authored by Pierre-vh on Feb 26 2020, 6:13 AM.

Details

Summary

This is a fix for https://bugs.llvm.org/show_bug.cgi?id=37967

I need some help to be sure that this fix is correct, even though it's trivial, I am not sure I fixed this in the best possible way.

  • Is this a good fix for this issue, or is it just working around it?
  • Is the test I wrote good enough? I just tested for the output of -debugify-each, but perhaps it'd be better to check the LLVM IR directly?

Diff Detail

Event Timeline

Pierre-vh created this revision.Feb 26 2020, 6:13 AM
Herald added a project: Restricted Project. · View Herald TranscriptFeb 26 2020, 6:13 AM
vsk added a comment.Feb 26 2020, 8:22 AM

Thanks, this is in good shape. A few minor comments inline.

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
1305

nit, we generally ask contributors to clang-format (just) their diffs, e.g. with

https://github.com/llvm-mirror/clang/blob/master/tools/clang-format/clang-format-diff.py

I personally hook this up to git via .gitconfig:

[alias]
  fmt = ! git diff -U0 --no-color HEAD~1 | ~/src/llvm-project-master/clang/tools/clang-format/clang-format-diff.py -i -p1

& run 'git fmt' before committing.

llvm/test/Transforms/MemCpyOpt/pr37967.ll
4

This check line makes for a nice regression test.

5

Could you change this to a positive test? e.g.

; CHECK-LABEL: define {{.*}} @_Z3bar3FooS_RiS_
; CHECK: [[firstAlloca:%.*]] = alloca %struct.Foo
; CHECK: bitcast i8* [[firstAlloca]] to %struct.Foo*, !dbg

As-written, it might stop being a useful test if the structure of the IR emitted by the pass changes slightly (seems likely, as the bitcast is a no-op?), or if (for some reason) the -check-debugify output changes.

vsk added inline comments.Feb 26 2020, 8:25 AM
llvm/test/Transforms/MemCpyOpt/pr37967.ll
5

Ah, oops. %1 has a different type after 'opt' runs, so the check line for 'firstAlloca' needs to be fixed up.

Hi, thanks for this. The test case look very verbose and can probably be reduced. At least all unnecessary meta-information should be removed, e.g. does it really need all these function attributes?

Pierre-vh updated this revision to Diff 246889.Feb 27 2020, 1:31 AM

Hello,

I updated the code, it should be correctly formatted now.

About the test, I don't know how to simplify it further as I am still pretty new to LLVM IR, if you have suggestions/explanations I'd love to hear them.
Also, I can't write the test you suggested as the output does not have a !dbg attribute (the exact line looks like this, but debugify accept it: internally, it seems to have a DebugInfo node, it's just empty)

%tmpcast = bitcast i8* %1 to %struct.Foo*
Pierre-vh marked 2 inline comments as done.Feb 27 2020, 1:33 AM
Pierre-vh added inline comments.
llvm/test/Transforms/MemCpyOpt/pr37967.ll
5

I can't write the test like that as the resulting line looks like this:

%tmpcast = bitcast i8* %1 to %struct.Foo*

It doesn't have a !dbg attribute (but, since debugify doesn't complain, it seems to have a non-null DebugLoc node, my guess is just that it's empty)

vsk added a comment.Feb 27 2020, 4:34 PM

@Pierre-vh you can run opt with -debug-pass=Structure to see what it's doing. In this case, it's stripping out all the debug metadata right before printing module IR:

ModulePass Manager
  FunctionPass Manager
    [snip ...]
    Attach debug info to a function
    Phi Values Analysis
    Memory Dependence Analysis
    MemCpy Optimization
    Check debug info from -debugify-function
    Attach debug info to a function
    Module Verifier
    Check debug info from -debugify-function
  Print Module IR

So that's why the 'CHECK' line doesn't match !dbg, it got stripped out. If you change your RUN line to do opt -instcombine -debugify -memcpyopt -check-debugify, opt will produce IR you can write a positive test against.

As for reducing the test, you can try to find a simpler way to trigger this code path in MemCpyOpt. llvm/test/Transforms/MemCpyOpt/memcpy.ll has lots of tidy examples, perhaps running one of those examples through -debugify-each would hit the same bug.

Pierre-vh updated this revision to Diff 247188.Feb 28 2020, 1:42 AM

Hello,

  • I made the test as small as I could
  • I added 2 run lines, one checks for the correctness of the LLVM IR, the other checks that debugify passes
vsk added a comment.Feb 28 2020, 5:49 AM

I’m not sure I understand why two run lines are needed, and neither are what I’d expect. The test has nothing to do with instcombine afaict, and running debugify /after/ memcpyopt is too late (that won’t test anything, as the real pass has already finished before we try attaching debug metadata).

Istm you just need one run line: opt -debugify -memcpyopt -check-debugify

In D75173#1897944, @vsk wrote:

I’m not sure I understand why two run lines are needed, and neither are what I’d expect. The test has nothing to do with instcombine afaict, and running debugify /after/ memcpyopt is too late (that won’t test anything, as the real pass has already finished before we try attaching debug metadata).

Istm you just need one run line: opt -debugify -memcpyopt -check-debugify

You are right, I just misunderstood how opt worked (I didn't know the passes were run in order of appearance).
Would this better?

; RUN: opt -instcombine -debugify -memcpyopt -check-debugify -S < %s 2>&1 | FileCheck %s

; CHECK: CheckModuleDebugify: PASS

; CHECK-LABEL: define {{.*}} @_Z3bar3Foo
; CHECK: [[target:%.*]] = load i8*, i8** bitcast (%struct.Foo** @a to i8**), align 8, !dbg
; CHECK: %tmpcast = bitcast i8* [[target]] to %struct.Foo*, !dbg

Note that I need -instcombine or else the test does not pass.

vsk added a comment.Feb 28 2020, 6:51 AM
In D75173#1897944, @vsk wrote:

I’m not sure I understand why two run lines are needed, and neither are what I’d expect. The test has nothing to do with instcombine afaict, and running debugify /after/ memcpyopt is too late (that won’t test anything, as the real pass has already finished before we try attaching debug metadata).

Istm you just need one run line: opt -debugify -memcpyopt -check-debugify

You are right, I just misunderstood how opt worked (I didn't know the passes were run in order of appearance).
Would this better?

; RUN: opt -instcombine -debugify -memcpyopt -check-debugify -S < %s 2>&1 | FileCheck %s

; CHECK: CheckModuleDebugify: PASS

; CHECK-LABEL: define {{.*}} @_Z3bar3Foo
; CHECK: [[target:%.*]] = load i8*, i8** bitcast (%struct.Foo** @a to i8**), align 8, !dbg
; CHECK: %tmpcast = bitcast i8* [[target]] to %struct.Foo*, !dbg

That looks perfect, except

Note that I need -instcombine or else the test does not pass.

Hm, it looks like instcombine needs to massage the IR a bit before memcpyopt can "kick in". There's room in llvm for integration tests, but generally we try to make tests for transforms as narrow as possible (typically you don't want a change in instcombine breaking your test that's really for memcpyopt -- but sometimes you do). You can do that here with

opt -S -instcombine pr37967.ll > simplified.ll

Then your test should fully work with 'opt -debugify -memcpyopt -check-debugify'.

Pierre-vh updated this revision to Diff 247257.Feb 28 2020, 7:04 AM

Thank you very much for your comments. This should be good I think.

vsk accepted this revision.Feb 28 2020, 7:14 AM

Lgtm, thanks! I appreciate your patience on this one.

This revision is now accepted and ready to land.Feb 28 2020, 7:14 AM
This revision was automatically updated to reflect the committed changes.