Index: docs/SourceLevelDebugging.rst =================================================================== --- docs/SourceLevelDebugging.rst +++ docs/SourceLevelDebugging.rst @@ -77,8 +77,8 @@ .. _intro_debugopt: -Debugging optimized code ------------------------- +Debug information and optimizations +----------------------------------- An extremely high priority of LLVM debugging information is to make it interact well with optimizations and analysis. In particular, the LLVM debug @@ -1464,3 +1464,91 @@ records, constructing a C++ test case that makes MSVC emit those records, dumping the records, understanding them, and then generating equivalent records in LLVM's backend. + +Debugging optimized code +======================== + +The following paragraphs are an introduction to the debugify utility +and examples of how to use it in regression tests to check debug info +preservation after optimizations. + +The ``debugify`` utility +------------------------ + +The ``debugify`` synthetic debug info testing utility consists of two +main parts. The ``debugify`` pass and the ``check-debugify`` one. They are +meant to be used with ``opt`` for development purposes. + +The first applies synthetic debug information to each non null instruction +in the module, while the latter checks that this DI is still available after +an optimization has occurred, reporting any errors/warnings while doing so. + +For example: + +.. code-block:: bash + + $ opt -debugify-each -loop-vectorize llvm/test/Transforms/LoopVectorize/i8-induction.ll -disable-output + ERROR: Instruction with empty DebugLoc in function f -- %index = phi i32 [ 0, %vector.ph ], [ %index.next, %vector.body ] + ERROR: Instruction with empty DebugLoc in function f -- %vec.phi = phi <4 x i8> [ , %vector.ph ], [ %5, %vector.body ] + ERROR: Instruction with empty DebugLoc in function f -- %index.next = add i32 %index, 4 + ERROR: Instruction with empty DebugLoc in function f -- %9 = icmp eq i32 %index.next, 16 + ERROR: Instruction with empty DebugLoc in function f -- br i1 %9, label %middle.block, label %vector.body, !llvm.loop !32 + ERROR: Instruction with empty DebugLoc in function f -- %cmp.n = icmp eq i32 16, 16 + ERROR: Instruction with empty DebugLoc in function f -- %bc.merge.rdx = phi i8 [ 0, %scalar.ph ], [ %10, %middle.block ] + ERROR: Instruction with empty DebugLoc in function f -- %mul.lcssa = phi i8 [ %mul, %for.body ], [ %10, %middle.block ] + + +Using ``debugify`` +^^^^^^^^^^^^^^^^^^ + +In order for ``check-debugify`` to work, the DI must be coming from +``debugify``. Thus, modules with existing DI will be skipped. + +The most straightforward way to use ``debugify`` is as follows:: + + $ opt -debugify -pass-to-test -check-debugify sample.ll + +This will inject synthetic DI to ``sample.ll`` run the ``pass-to-test`` +and then check for missing DI. + +Some other ways to run debugify are avaliable: + +.. code-block:: bash + + # same as the above example + $ opt -enable-debugify -pass-to-test sample.ll + + # Suppresses verbose debugify output + $ opt -enable-debugify -debugify-quiet -pass-to-test sample.ll + + # prepend -debugify before and append -check-debugify after + # each pass on the pipeline (similar to -verify-each) + $ opt -debugify-each -O2 sample.ll + +``debugify`` in regression tests +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The first pass that applies synthetic DI is especially helpful when it comes +to testing that a given pass preserves DI while transforming the module. +For this to work, the ``-debugify`` output must be stable enough to use in +regression tests. There might be occasional bug-fixes but they are not allowed +to break existing tests or alter their meaning. + +It allows us to test for DI loss in the same tests we check that the +transformation is actually doing what it should. + +.. code-block:: llvm + + ; RUN: opt < %s -debugify -pass-to-test -S | FileCheck %s --check-prefix=DEBUGLOC + + define i8 @f(i8 %x, i8 %y) { + ; DEBUGLOC-LABEL: define void @f( + ; DEBUGLOC: {{.*}} = mul {{.*}}, !dbg ![[DbgLoc:[0-9]+]] + + %z = mul i8 %x, %y + ret i8 %z + } + ; DEBUGLOC: ![[DbgLoc]] = DILocation(line: 2 + +In the above example we are testing that the mul instruction has a debug location +after the pass and it corresponds to line 2.