This is a prototype implementation of what was discussed in http://lists.llvm.org/pipermail/llvm-dev/2020-September/144990.html
So, given the following input compiled with clang -g -O3 lsrdbg.c -mllvm -print-after-all
#pragma donotinline void foo(unsigned char *p) { #pragma clang loop unroll(disable) for (unsigned char i = 0; i < 32; i++) { p += 3; *p = i; } }
the IR shows that after LSR two llvm.dbg.value have been updated to reference %lsr.iv instead of the deleted %p.addr.05 and %add.ptr. Also note the compensation in one of the DIExpression.
*** IR Dump After Canonicalize Freeze Instructions in Loops *** ; Preheader: entry: call void @llvm.dbg.value(metadata i8* %p, metadata <0x10159f90>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x101530a0>) call void @llvm.dbg.value(metadata i8 0, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) br label %for.body, !dbg !DILocation(line: 4, column: 3, scope: <0x1015b6c0>) ; Loop: for.body: ; preds = %entry, %for.body %i.06 = phi i8 [ 0, %entry ], [ %inc, %for.body ] %p.addr.05 = phi i8* [ %p, %entry ], [ %add.ptr, %for.body ] call void @llvm.dbg.value(metadata i8 %i.06, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) call void @llvm.dbg.value(metadata i8* %p.addr.05, metadata <0x10159f90>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x101530a0>) %add.ptr = getelementptr inbounds i8, i8* %p.addr.05, i64 3, !dbg !DILocation(line: 5, column: 7, scope: <0x1015cd00>) call void @llvm.dbg.value(metadata i8* %add.ptr, metadata <0x10159f90>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x101530a0>) store i8 %i.06, i8* %add.ptr, align 1, !dbg !DILocation(line: 6, column: 8, scope: <0x1015cd00>), !tbaa <0x1015c2f8> %inc = add nuw nsw i8 %i.06, 1, !dbg !DILocation(line: 4, column: 38, scope: <0x1015c580>) call void @llvm.dbg.value(metadata i8 %inc, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) %exitcond.not = icmp eq i8 %inc, 32, !dbg !DILocation(line: 4, column: 31, scope: <0x1015c580>) br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !DILocation(line: 4, column: 3, scope: <0x1015b6c0>), !llvm.loop <0x1015d820> ; Exit blocks for.cond.cleanup: ; preds = %for.body ret void, !dbg !DILocation(line: 8, column: 1, scope: <0x101530a0>) The following llvm.dbg.value needs to be updated: {(3 + %p)<nsw>,+,3}<nuw><%for.body> : call void @llvm.dbg.value(metadata i8* %add.ptr, metadata !13, metadata !DIExpression()), !dbg !16 {(3 + %p)<nsw>,+,3}<nuw><%for.body> : %lsr.iv = phi i8* [ %scevgep, %entry ], [ %scevgep7, %for.body ] Match with offset 0 {%p,+,3}<nuw><%for.body> : call void @llvm.dbg.value(metadata i8* %p.addr.05, metadata !13, metadata !DIExpression()), !dbg !16 {(3 + %p)<nsw>,+,3}<nuw><%for.body> : %lsr.iv = phi i8* [ %scevgep, %entry ], [ %scevgep7, %for.body ] Match with offset -3 *** IR Dump After Loop Strength Reduction *** ; Preheader: entry: call void @llvm.dbg.value(metadata i8* %p, metadata <0x10159f90>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x101530a0>) call void @llvm.dbg.value(metadata i8 0, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) %scevgep = getelementptr i8, i8* %p, i64 3, !dbg !DILocation(line: 4, column: 3, scope: <0x1015b6c0>) br label %for.body, !dbg !DILocation(line: 4, column: 3, scope: <0x1015b6c0>) ; Loop: for.body: ; preds = %entry, %for.body %lsr.iv = phi i8* [ %scevgep, %entry ], [ %scevgep7, %for.body ] %i.06 = phi i8 [ 0, %entry ], [ %inc, %for.body ] call void @llvm.dbg.value(metadata i8 %i.06, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata <0x10159f90>, metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg !DILocation(line: 0, scope: <0x101530a0>) call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata <0x10159f90>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x101530a0>) store i8 %i.06, i8* %lsr.iv, align 1, !dbg !DILocation(line: 6, column: 8, scope: <0x1015cd00>), !tbaa <0x1015c2f8> %inc = add nuw nsw i8 %i.06, 1, !dbg !DILocation(line: 4, column: 38, scope: <0x1015c580>) call void @llvm.dbg.value(metadata i8 %inc, metadata <0x1015bb70>, metadata !DIExpression()), !dbg !DILocation(line: 0, scope: <0x1015b6c0>) %scevgep7 = getelementptr i8, i8* %lsr.iv, i64 3, !dbg !DILocation(line: 4, column: 31, scope: <0x1015c580>) %exitcond.not = icmp eq i8 %inc, 32, !dbg !DILocation(line: 4, column: 31, scope: <0x1015c580>) br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !DILocation(line: 4, column: 3, scope: <0x1015b6c0>), !llvm.loop <0x1015d820> ; Exit blocks for.cond.cleanup: ; preds = %for.body ret void, !dbg !DILocation(line: 8, column: 1, scope: <0x101530a0>)
nit: Probably cleaner to move this declaration up into the public section, now when it is made available in the public API.