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.