<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/91555>91555</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [flang] Debug information with MLIR inlining
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            flang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          vzakhari
      </td>
    </tr>
</table>

<pre>
    This affects the design for debug information generation in Flang: https://github.com/llvm/llvm-project/blob/main/flang/docs/DebugGeneration.md

Right now, the `AddDebugInfo` pass is run pretty late in the pipeline.  The MLIR inliner pass runs before it.  Even though the MLIR inlining is not fully functional, there is a way to force inlining for some simple functions and demonstrate the problem.

Reproducer:
```
     1  subroutine test(x, y)
     2    real :: x, y
     3    x = x + y ! may alias
 4    call inner(x, y)
     5  contains
     6    subroutine inner(x, y)
     7      real :: x, y
     8      x = x + y ! may not alias
 9    end subroutine inner
    10  end subroutine test
```

Compile with: `flang-new -g -O3 alias.f90 -c -mmlir -mlir-print-ir-after-all -mmlir -inline-all=true -mmlir -mlir-print-debuginfo -v -mllvm -print-after-all -mllvm -print-module-scope`

Here is the location information that is attached to the operations after MLIR inliner pass:
```
#loc1 = loc("/path/alias.f90":1:1)
module attributes {dlti.dl_spec = #dlti.dl_spec<#dlti.dl_entry<i32, dense<32> : vector<2xi64>>, #dlti.dl_entry<f64, dense<64> : vector<2xi64>>, #dlti.dl_entry<f128, dense<128> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr<270>, dense<32> : vector<4xi64>>, #dlti.dl_entry<f16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i1, dense<8> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr, dense<64> : vector<4xi64>>, #dlti.dl_entry<i16, dense<16> : vector<2xi64>>, #dlti.dl_entry<i8, dense<8> : vector<2xi64>>, #dlti.dl_entry<i128, dense<128> : vector<2xi64>>, #dlti.dl_entry<f80, dense<128> : vector<2xi64>>, #dlti.dl_entry<!llvm.ptr<272>, dense<64> : vector<4xi64>>, #dlti.dl_entry<!llvm.ptr<271>, dense<32> : vector<4xi64>>, #dlti.dl_entry<i64, dense<64> : vector<2xi64>>, #dlti.dl_entry<"dlti.endianness", "little">, #dlti.dl_entry<"dlti.stack_alignment", 128 : i64>>, fir.defaultkind = "a1c4d8i4l4r4", fir.kindmap = "", fir.target_cpu = "x86-64", llvm.data_layout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128", llvm.target_triple = "x86_64-unknown-linux-gnu"} {
  func.func @_QPtest(%arg0: !fir.ref<f32> {fir.bindc_name = "x"} loc("/path/alias.f90":1:1), %arg1: !fir.ref<f32> {fir.bindc_name = "y"} loc("/path/alias.f90":1:1)) {
    %0 = fir.dummy_scope : !fir.dscope loc(#loc1)
    %1 = fir.declare %arg0 dummy_scope %0 {uniq_name = "_QFtestEx"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc2)
 %2 = fir.declare %arg1 dummy_scope %0 {uniq_name = "_QFtestEy"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc3)
    %3 = fir.load %1 : !fir.ref<f32> loc(#loc4)
    %4 = fir.load %2 : !fir.ref<f32> loc(#loc4)
    %5 = arith.addf %3, %4 fastmath<contract> : f32 loc(#loc4)
    fir.store %5 to %1 : !fir.ref<f32> loc(#loc4)
    %6 = fir.dummy_scope : !fir.dscope loc(#loc11)
    %7 = fir.declare %1 dummy_scope %6 {uniq_name = "_QFtestFinnerEx"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc12)
    %8 = fir.declare %2 dummy_scope %6 {uniq_name = "_QFtestFinnerEy"} : (!fir.ref<f32>, !fir.dscope) -> !fir.ref<f32> loc(#loc13)
    %9 = fir.load %7 : !fir.ref<f32> loc(#loc14)
    %10 = fir.load %8 : !fir.ref<f32> loc(#loc14)
    %11 = arith.addf %9, %10 fastmath<contract> : f32 loc(#loc14)
    fir.store %11 to %7 : !fir.ref<f32> loc(#loc14)
 return loc(#loc10)
  } loc(#loc1)
} loc(#loc)
#loc = loc("/path/alias.f90":0:0)
#loc2 = loc("/path/alias.f90":2:11)
#loc3 = loc("/path/alias.f90":2:14)
#loc4 = loc("/path/alias.f90":3:3)
#loc5 = loc("/path/alias.f90":6:3)
#loc6 = loc("/path/alias.f90":4:3)
#loc7 = loc("/path/alias.f90":7:13)
#loc8 = loc("/path/alias.f90":7:16)
#loc9 = loc("/path/alias.f90":8:5)
#loc10 = loc("/path/alias.f90":10:1)
#loc11 = loc(callsite(#loc5 at #loc6))
#loc12 = loc(callsite(#loc7 at #loc6))
#loc13 = loc(callsite(#loc8 at #loc6))
#loc14 = loc(callsite(#loc9 at #loc6))
```

The MLIR inliner implementation produces a callsite location for each operation inlined from `inner`.  After conversion to LLVM IR it looks like this:
```
define void @test_(ptr %0, ptr %1) #0 !dbg !5 {
  %3 = load float, ptr %0, align 4, !dbg !9, !tbaa !10
  %4 = load float, ptr %1, align 4, !dbg !9, !tbaa !16
  %5 = fadd contract float %3, %4, !dbg !9
  store float %5, ptr %0, align 4, !dbg !9, !tbaa !10
  %6 = load float, ptr %0, align 4, !dbg !18, !tbaa !10
  %7 = load float, ptr %1, align 4, !dbg !18, !tbaa !16
  %8 = fadd contract float %6, %7, !dbg !18
  store float %8, ptr %0, align 4, !dbg !18, !tbaa !10
  ret void, !dbg !19
}
!3 = distinct !DICompileUnit(language: DW_LANG_Fortran95, file: !4, producer: "flang version 19.0.0 (ssh://git@gitlab-master.nvidia.com:12051/fortran/llvm-project-mirror.git e08863ed78aa96096f04f0856069da8645944ab1)", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug)
!4 = !DIFile(filename: "alias.f90", directory: "/path")
!5 = distinct !DISubprogram(name: "test_", linkageName: "test_", scope: !4, file: !4, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !3)
!6 = !DISubroutineType(cc: DW_CC_normal, types: !7)
!7 = !{!8, !8}
!8 = !DIBasicType(name: "real", size: 32, encoding: DW_ATE_float)
!9 = !DILocation(line: 3, column: 3, scope: !5)
!18 = !DILocation(line: 4, column: 3, scope: !5)
```

So all instructions inlined from `inner` end up on the same line as the call site.  This is a problem for debugging. 
Compare it with LLVM inlining in this example: https://godbolt.org/z/x81d5vsxo - the inlined instructions inherit their line number information from the callee (look for the last instance of `; *** IR Dump After InlinerPass on (test) ***`).

I believe the problem is that the MLIR Location attached to the operations of `inner` *before* MLIR inlining do not have proper `LLVM::DILocalScopeAttr` attached to them.  So there is no scope attribute on the callee Locations in the callsite Locations created by MLIR inliner.  One can trace the call chain from https://github.com/llvm/llvm-project/blob/f958a7348fcb27c3c6b07f1c8bdb902c7525b845/mlir/lib/Target/LLVMIR/DebugTranslation.cpp#L418 to https://github.com/llvm/llvm-project/blob/f958a7348fcb27c3c6b07f1c8bdb902c7525b845/mlir/lib/Target/LLVMIR/DebugTranslation.cpp#L426, which results in the callsite Locations to be translated to LLVM debug metadata that corresponds to the call operation location.  I think instead, the callee Locations inside the callsite Locations should follow the call chain from https://github.com/llvm/llvm-project/blob/f958a7348fcb27c3c6b07f1c8bdb902c7525b845/mlir/lib/Target/LLVMIR/DebugTranslation.cpp#L418 to https://github.com/llvm/llvm-project/blob/f958a7348fcb27c3c6b07f1c8bdb902c7525b845/mlir/lib/Target/LLVMIR/DebugTranslation.cpp#L437, so that the callee's Locations are used for the cloned operations with proper scope.

It seems to mean that before MLIR inliner we have to have Locations with proper scope (e.g. `LLVM::DISubprogramAttr`) attached to them. This cannot be achieved with the current ordering of the MLIR inliner and `AddDebugInfo` passes.

@kiranchandramohan, @abidh, @jeanPerier, @VijayKandiah, FYI.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzsWt9z47aP_2uYF449EvXD8kMevMm6l-m23Xb32rmnDCVBNhuK1JFUEu9ffwNKsuQfcZPsduYevplYtijiAxAEAZAQt1ZsFMA1ST6Q5PaKt26rzfXjN_6w5UZc5brcXX_dCkt5VUHhLHVboCUgFa20oSXk7YYKVWlTcye0ohtQYLqfQtG15GpDohXdOtdYEq0IWxO23gi3bfN5oWvC1lI-Dl-zxui_oXCErXOpc8LWNReKsHXlcdi61IUlbH2LbH_ac5rXJQluSbDqrn-IzdZRpZ8Iu_ECkzRYlaUnulOVJmlAG24tFZaaVtHGgHM7KrkDlBkpGtGAFArmlH7dAv3l090fVChsMR2paZWlOVTaABVuTunHR0BS3W62HmEkEWqDnJR2tGql3NGqVQWKzWUvIGJYyukT31GnUbEFjLSoZ6troFbUjYQ9uaVclbSEWivrDArvJTc6l1DPDxQCjdFlW4DBGegepEH_728p_oWU2jY3unVCAXVgHWHZM8q4I2w56cjwYoBLinjRivadxh4RXp4piW7xyj7QHSUspDXfUS4Ft33XGLsVXEoqlALzAruE0kIrx4Wyk9YULxN5LyEs_PWyyFnX57zQOHlTwZfYFVR5KsAeMAxOeniVnlN_d73RdSMk0CfhtigiSQNv9zMFT3S2obPfok6IebUM6Kygs7qWwtAZXmeNEcrNhJnxyoGZoVKH553lYhOJbp1p4RylX8q4kunsER_Ix5r2j6aI0_Zal62EmS10A0dj-a_eqNEkpS4GhzD6Cbflzlu9c7zYQomGj5110y9q9DkOzOnae8mGCYukLkI_f1IXhGWEMcLWDXdbwtZ7zWFrtAr9Z7CSbiQojBF568BSsvhQSifmpby3DRQelbBo2kaim0kLKGd2JLoREUPTKkFZINFNxEj0EY2OPkLhtCHRDXsWaUyij_jPbugZjCqNpxi-95sxQlTACIK3b0chLMQZnzfO918EfdcLw4tfIVp6IFn6DsFEOIX43qFdVvY_j0j8iBFl3zsi8UOmvMqCH2837Mhu3qXlY9DwRxij-AFrjTDmm0CVgisF1nrXg32ZFM5J8E7nn8it48XDPZdio2pQrscIWeblORCiEmZeQsVb6R6EKnv3xHhYxGUmYhmbuCfHntil5s3Qa_LEcbMBd1807fDwOUtn6UDs1V1yx-8l3-nWDZ1gVpNoBbPGe4QVKn4VMbwND2_xF8q9SuOZ2P_wNrUKWTZDY-t-Kd-UDuRpPPsS9i68l6OX1RmBadAo7n0az1r1oPSTmkmh2ufZRrVIuLhFNz6EZMyb5nihJA7uf__cJziEJdxsAh9wWYg6MVDhMuitafEB23KhyuJe8Xpk3HN4Q6jxs4_cwjdz272D23I6eoqsAw_nbaet6929j9x0IkzZtQxcfEA9SKUIS8IRBArJDfSDCugBqOe2-NAq8b8HI7n_fY2a_zjor-OendFGp6-JXDikmVfTGdVNZWajzIQl7AWBw7cJvPsXBY6OlRztZZaal4PazxvNFCg-BopPgNj7gBIPxI1w2zkvy8pL2Zt0TCtuXY32GN1grm544QY_WkXsAjIKYZ3uJiXBLPD9Y03fY94n9r04Zy4ntpJespW13wv8qyYesmO5s3Nys_fI_W9aenhi6ssTC128avrDk_kPgxOo7L1Q4RlzHzx4GLzF3sMLBh-GvcW_fcgGXGvU4eNgwmkaLQ79-PGT8YG_feUGKvCfQ1L2Slofp8Ij4ugtxPERcfxK4sh_DmmTV9KmZ2jTV9LGZ2gXr6Rd4ICPibO3EKdHxMtXEmNKlhzR9ovsFYlIcLDFHtzthLrgUlrhYG-JCeWO9ortUpgDWnaJdnGZNrpEm12mjS_RLl-iPXfEc3KY6I_0MNnvTkX6czpLOR0YjccnlTYUeLEdz0h6mJJWRteUpEF3BpUGc0pX_vSk0OoRjPUnLpp--vTnLxS5Oyq1frBUigegbitePFQpoRIK6KMWJabNGCTuCcsaZ3zChA6x_x36hJNFAXqxMt_gVzLNQPdZjffNldTcTcg9lN_60LiPLj1I73VDl3OO32EwQYxfRgxfj5hOEDtvUPGypINn76APEp5jwJ6-c-z77sn3DzB9j8rC7BLk4j06O4WcKi27pLS0V9riBPG81rLvHaMB5y32iGAMf8Pq7r1CKawTqkDm4e1dfwz730rg9lBytWn5BjA83_51_2n160_3a22c4WqZdLtoCX3s9hJOjtoxs_InuHRYg-FyHsxxhWTWbqflEBIHG-Ekz2c1tw7MXD2KUnBfIsH9cYBTs646xkfVklktjNFmvhGOQpBlaQTlIuN8mQbLtAriKsiSNEiXJc_SOFnGMc-7DaLfWgv7W-NELb5BiSI70wI2m1Y5UcOfneD4xE8F1MJiw89C-e7rVkpfWJn4zN5femWuUTssQyVhvtkr5SBSsBtaCuMPW3b9831MYVPY5MxkfWnzxuiN4TVh2YRD76i6wwOhHvgGfj3_tEtfJxN4PKHoYfHerw2323dO99Sfpj1ss5Z8Y7293H35jDe36ESFd9hkcbNvHvXObmiL5tYBT0N9mI66_LKvJHxFKVhWFL1V3tzcK23qvqC0a8D2UIsp1GKAQqfM9usnmy6IbGT3gVtR9JwmmjWAbDrViW--tTvxBlXoUnTlvtu_7ldfP9737mUUYTnCf-rDGq6xXn_euxZatrXa306nZ5qKhFNRz2DFr8c6F6i_aNqVpawzbV9ueynY-jJP21Dd1Q4t7quwJ-Vd_cMXuDCU-2qisF2xry_UjWXUjVCbOR1LQdyXFn01qAvcYzVR-ZhN4Zlj-nCmvqrLXEs312ZD2PobYevnLCyTR_us6czLNIzlaIBbMMJhB2G6Iai2zjFNmVRu_PCHcQFuYzJMJvxAfLmHW-dxuSqA6gpVRaIPlLBV948ZyG1bN32KctelQp-5tahCwrLuZG45UiACWx7UNO9oDlLA40HVs6s4cTdWYAfLuFRn6kTczyZhq66wi6IelnFL7SuBW_7oWTZgkBInp6sqdpYov6CdrZzzcEeM6zmlX_RY9VW6M8ux9jTYUa_eYQR2qE3vE8PxSWGAOyhpvjvILueU_qaQQFEMyTBaY7Hlop_J91bmq2WS8UUUZ1WRs0URFWkeLKqwyPIyXwasWCQsybM4IWxdS2EQRyDdV3-KS9ga1Xb3x1DN_2q4srIr5xdNQ1j0KQ4zVNr_YwGZjwFPW1FsqQHbSndplpymOeBMeJzOIvzC7t6iqMHxkjveWXChjQHbaFXawWT9zI25_7AvmFN6h_5APfhVB7wc3ns4Y0FWlPCSfHarW1nSSkupn_5jKz9YwMinv1aPDqqbHsIWdjIJ6PVbi1Gmd6eF1OioJ_7KR4Te_XjfcegYHbUAtbeaGnhfae9fVTnYez5B58lQb_g9CnHCAb0yzDE8Hbq7Mf3q3R267VOP56NewRU6zxwoL7boucuOjx9kawwoR7UpwaCn1dXRWzRg_OsuL7zKA_ZAByQOHoThqthyVRpe6y0mzTe4g-W5KLf977-Bq89gBJi-4U_xN9_9zFUpuO-z_p-7-VV5HZXLaMmv4DpchAljWZwEV9vrarGM2bICHqR8GUQ8S_JlXnAoOK-qZLm8EtcsYHGQBMsgZkESzAHKLMggr7KwKNIISBxAzYWc-_KWNpsrYW0L18swSZIryXOQ1r-a1W8jMO1Kbq_MtTfivN1YEgdSWGdHBCec9O9zdRTJLb09eUfLq_0gsl21Rl6_efF4aS1hay_w_wUAAP__vHE1AQ">