[PATCH] D56151: [DebugInfo] PR40010: Avoid register coalesing altering DBG_VALUE valuations

Bjorn Pettersson via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 27 03:03:15 PDT 2019


bjope added a comment.

I'll try to describe one "regression" that I've seen.

Before ISel we've got

  ...
  %0 = tail call %struct. @llvm.phx.divm.u16.s_struct.s(i16 %a, i16 %b), !dbg !708
  %.fca.0.extract = extractvalue %struct. %0, 0, !dbg !708
  call void @llvm.dbg.value(metadata i16 %.fca.0.extract, metadata !686, metadata !DIExpression(DW_OP_LLVM_fragment, 0, 16)), !dbg !709
  %.fca.1.extract = extractvalue %struct. %0, 1, !dbg !708
  call void @llvm.dbg.value(metadata i16 %.fca.1.extract, metadata !686, metadata !DIExpression(DW_OP_LLVM_fragment, 16, 16)), !dbg !709
  ...
  use %.fca.0.extract
  use %.fca.1.extract
  ...

After ISel it looks like this

  ...
  %14:anh_0_7, %15:anh_0_7 = divm16_pseudo killed %13:anh_0_7, %7:anh_0_7, implicit-def dead $ccreg, debug-location !708; 
  DBG_VALUE %14:anh_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 0, 16), debug-location !709;
  %0:anh_rn = COPY %15:anh_0_7, debug-location !708;
  DBG_VALUE %15:anh_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  ...
  use %14:anh_0_7
  use %0:anh:rn
  ...

//Maybe ISel should have put the COPY to %0 after the last DBG_VALUE (now we got a dbg-use of %15 after the last non-dbg-use of %15). Or maybe it should have used %0 instead of %15 in that DBG_VALUE. Or maybe there should be one DBG_VALUE before the COPY using %15 and one after using %0.//

Before simple register coalescing we get this (some more COPY instructions after expanding the pseudo that is using some hard coded physical registers):

  ...
  208B	  divm16 0, $noreg, 0, implicit-def $a4_40, implicit-def dead $af4, implicit-def dead $ccreg, implicit-def $a5_40, implicit $a4h, implicit $a5h, debug-location !708;
  224B	  %42:an40_0_7 = COPY $a4_40, debug-location !708;
  240B	  %14:anh_0_7 = COPY %42.hi16:an40_0_7, debug-location !708;
  256B	  %43:an40_0_7 = COPY $a5_40, debug-location !708;
  272B	  %15:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  	  DBG_VALUE %14:anh_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 0, 16), debug-location !709;
  288B	  %0:anh_0_7 = COPY %15:anh_0_7, debug-location !708;
  	  DBG_VALUE %15:anh_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  ...
            use %14:anh_0_7
            use %0:anh_0_7
  ...

Without this patch we get

  ...
  208B	  divm16 0, $noreg, 0, implicit-def $a4_40, implicit-def dead $af4, implicit-def dead $ccreg, implicit-def $a5_40, implicit $a4h, implicit $a5h, debug-location !708;
  224B	  %42:an40_0_7 = COPY $a4_40, debug-location !708;
  256B	  %43:an40_0_7 = COPY $a5_40, debug-location !708;
  	  DBG_VALUE %42.hi16:an40_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 0, 16), debug-location !709;
  	  DBG_VALUE %43.hi16:an40_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  ...
            use %42.hi16:an40_0_7
            use %43.hi16:an40_0_7
  ...

With the patch the last DBG_VALUE is changed into using %noreg, so instead we get

  ...
  208B	  divm16 0, $noreg, 0, implicit-def $a4_40, implicit-def dead $af4, implicit-def dead $ccreg, implicit-def $a5_40, implicit $a4h, implicit $a5h, debug-location !708;
  224B	  %42:an40_0_7 = COPY $a4_40, debug-location !708;
  256B	  %43:an40_0_7 = COPY $a5_40, debug-location !708;
  	  DBG_VALUE %42.hi16:an40_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 0, 16), debug-location !709;
  	  DBG_VALUE %noreg.hi16, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  ...
            use %42.hi16:an40_0_7
            use %43.hi16:an40_0_7
  ...

It is when analyzing the COPY to %0 that we detect that the DBG_VALUE is unsound:

  272B	%15:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  	Considering merging to aN40_0_7 with %15 in %43:hi16
  		RHS = %15 [272r,288r:0)  0 at 272r weight:0.000000e+00
  		LHS = %43 [256r,272r:0)  0 at 256r weight:0.000000e+00
  		merge %15:0 at 272r into %43:0 at 256r --> @256r
  		erased:	272r	%15:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  		updated: 288B	%0:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  		updated: DBG_VALUE %43.hi16:an40_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  Shrink: %43 [256r,288r:0)  0 at 256r weight:0.000000e+00
  Shrunk: %43 [256r,288r:0)  0 at 256r weight:0.000000e+00
  	Success: %15:hi16 -> %43
  	Result = %43 [256r,288r:0)  0 at 256r weight:0.000000e+00
  
  288B	%0:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  	Considering merging to aN40_0_7 with %0 in %43:hi16
  		RHS = %0 [288r,928r:0)  0 at 288r weight:0.000000e+00
  		LHS = %43 [256r,288r:0)  0 at 256r weight:0.000000e+00
  		merge %0:0 at 288r into %43:0 at 256r --> @256r
  		erased:	288r	%0:anh_0_7 = COPY %43.hi16:an40_0_7, debug-location !708;
  		updated: 928B	%54:anh_0_7 = subs_a16_a16_a16 %40:anh_0_7, %43.hi16:an40_0_7, 0, $noreg, 0, implicit-def dead $ccreg, implicit $cuc, debug-location !758;
  Update of %43.hi16:an40_0_7 would be unsound, setting undef

So we have already merged  `aN40_0_7 with %15 in %43:hi16` and updated the DBG_VALUE to use %43:hi16 before we find it unsound. So in the past this coalescing made the DBG_VALUE sound (as it extended the live range for %43 to cover the DBG_VALUE). But with this patch we instead detect the DBG_VALUE as being unsound.

Inside mergingChangesDbgValue I can see

  DbgV->dump() =>   DBG_VALUE %43.hi16:an40_0_7, $noreg, !"cycleDiv", !DIExpression(DW_OP_LLVM_fragment, 16, 16), debug-location !709;
  DbgReg = 2147483691 (%43)
  DstReg = 2147483691 (%43)
  SrcReg = 2147483648 (%0)
  SrcLive = true
  DstLive = false

That is basically how far I've analysed this scenario at the moment.

Some thoughts:

- Should this be seen as a fault in ISel? We could probably get a better result if ISel worked differently. But in general I think we allow dbg-uses outside the non-dbg-live-interval, so I do not think it really is a fault.
- A late dbg-use (for an otherwise killed reg) is only unsound if the register allocator is using the allocated physical register for some other purpose. Isn't it a little bit early to detect that in the register coalescer? Maybe we need to take the register allocation into account if we want to make a better solution. Isn't LiveDebugVariables supposed to handle this?
- Is this patch really supposed to detect this DBG_VALUE as unsound? (we are not updating %43 here, we are only extending the live range to cover the DBG_VALUE that already is using %43). Should perhaps mergingChangesDbgValue return false also when `(SrcLive && DstReg == DbgReg)`, or could this be unsound?




CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D56151/new/

https://reviews.llvm.org/D56151





More information about the llvm-commits mailing list