forked from OSchip/llvm-project
Reland [DebugInfo] Improve dbg preservation in LSR.
Use SCEV to salvage additional @llvm.dbg.value that have turned into referencing undef after transformation (and traditional salvageDebugInfo). Before rewrite (but after introduction of new induction variables) use SCEV to compute an equivalent set of values for each @llvm.dbg.value in the loop body (among the loop header PHI-nodes). After rewrite (and dead PHI elimination) update those @llvm.dbg.value now referencing undef by picking a remaining value from its equivalence set. Allow match with offset by inserting compensation code in the DIExpression. Fixes : PR38815 Differential Revision: https://reviews.llvm.org/D87494
This commit is contained in:
parent
2664f5d436
commit
2a6782bb9f
|
@ -1163,6 +1163,15 @@ public:
|
||||||
const SCEV *S, const Loop *L,
|
const SCEV *S, const Loop *L,
|
||||||
SmallPtrSetImpl<const SCEVPredicate *> &Preds);
|
SmallPtrSetImpl<const SCEVPredicate *> &Preds);
|
||||||
|
|
||||||
|
/// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
|
||||||
|
/// constant, and None if it isn't.
|
||||||
|
///
|
||||||
|
/// This is intended to be a cheaper version of getMinusSCEV. We can be
|
||||||
|
/// frugal here since we just bail out of actually constructing and
|
||||||
|
/// canonicalizing an expression in the cases where the result isn't going
|
||||||
|
/// to be a constant.
|
||||||
|
Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
|
||||||
|
|
||||||
/// Update no-wrap flags of an AddRec. This may drop the cached info about
|
/// Update no-wrap flags of an AddRec. This may drop the cached info about
|
||||||
/// this AddRec (such as range info) in case if new flags may potentially
|
/// this AddRec (such as range info) in case if new flags may potentially
|
||||||
/// sharpen it.
|
/// sharpen it.
|
||||||
|
@ -1884,15 +1893,6 @@ private:
|
||||||
bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R,
|
bool splitBinaryAdd(const SCEV *Expr, const SCEV *&L, const SCEV *&R,
|
||||||
SCEV::NoWrapFlags &Flags);
|
SCEV::NoWrapFlags &Flags);
|
||||||
|
|
||||||
/// Compute \p LHS - \p RHS and returns the result as an APInt if it is a
|
|
||||||
/// constant, and None if it isn't.
|
|
||||||
///
|
|
||||||
/// This is intended to be a cheaper version of getMinusSCEV. We can be
|
|
||||||
/// frugal here since we just bail out of actually constructing and
|
|
||||||
/// canonicalizing an expression in the cases where the result isn't going
|
|
||||||
/// to be a constant.
|
|
||||||
Optional<APInt> computeConstantDifference(const SCEV *LHS, const SCEV *RHS);
|
|
||||||
|
|
||||||
/// Drop memoized information computed for S.
|
/// Drop memoized information computed for S.
|
||||||
void forgetMemoizedResults(const SCEV *S);
|
void forgetMemoizedResults(const SCEV *S);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
#include "llvm/IR/BasicBlock.h"
|
#include "llvm/IR/BasicBlock.h"
|
||||||
#include "llvm/IR/Constant.h"
|
#include "llvm/IR/Constant.h"
|
||||||
#include "llvm/IR/Constants.h"
|
#include "llvm/IR/Constants.h"
|
||||||
|
#include "llvm/IR/DebugInfoMetadata.h"
|
||||||
#include "llvm/IR/DerivedTypes.h"
|
#include "llvm/IR/DerivedTypes.h"
|
||||||
#include "llvm/IR/Dominators.h"
|
#include "llvm/IR/Dominators.h"
|
||||||
#include "llvm/IR/GlobalValue.h"
|
#include "llvm/IR/GlobalValue.h"
|
||||||
|
@ -5774,6 +5775,62 @@ void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.addPreserved<MemorySSAWrapperPass>();
|
AU.addPreserved<MemorySSAWrapperPass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using EqualValues = SmallVector<std::tuple<WeakVH, int64_t, DIExpression *>, 4>;
|
||||||
|
using EqualValuesMap = DenseMap<DbgValueInst *, EqualValues>;
|
||||||
|
|
||||||
|
static void DbgGatherEqualValues(Loop *L, ScalarEvolution &SE,
|
||||||
|
EqualValuesMap &DbgValueToEqualSet) {
|
||||||
|
for (auto &B : L->getBlocks()) {
|
||||||
|
for (auto &I : *B) {
|
||||||
|
auto DVI = dyn_cast<DbgValueInst>(&I);
|
||||||
|
if (!DVI)
|
||||||
|
continue;
|
||||||
|
auto V = DVI->getVariableLocation();
|
||||||
|
if (!V || !SE.isSCEVable(V->getType()))
|
||||||
|
continue;
|
||||||
|
auto DbgValueSCEV = SE.getSCEV(V);
|
||||||
|
EqualValues EqSet;
|
||||||
|
for (PHINode &Phi : L->getHeader()->phis()) {
|
||||||
|
if (V->getType() != Phi.getType())
|
||||||
|
continue;
|
||||||
|
if (!SE.isSCEVable(Phi.getType()))
|
||||||
|
continue;
|
||||||
|
auto PhiSCEV = SE.getSCEV(&Phi);
|
||||||
|
if (Optional<APInt> Offset =
|
||||||
|
SE.computeConstantDifference(DbgValueSCEV, PhiSCEV))
|
||||||
|
EqSet.emplace_back(std::make_tuple(
|
||||||
|
&Phi, Offset.getValue().getSExtValue(), DVI->getExpression()));
|
||||||
|
}
|
||||||
|
DbgValueToEqualSet[DVI] = std::move(EqSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void DbgApplyEqualValues(EqualValuesMap &DbgValueToEqualSet) {
|
||||||
|
for (auto A : DbgValueToEqualSet) {
|
||||||
|
auto DVI = A.first;
|
||||||
|
// Only update those that are now undef.
|
||||||
|
if (!isa_and_nonnull<UndefValue>(DVI->getVariableLocation()))
|
||||||
|
continue;
|
||||||
|
for (auto EV : A.second) {
|
||||||
|
auto V = std::get<WeakVH>(EV);
|
||||||
|
if (!V)
|
||||||
|
continue;
|
||||||
|
auto DbgDIExpr = std::get<DIExpression *>(EV);
|
||||||
|
auto Offset = std::get<int64_t>(EV);
|
||||||
|
auto &Ctx = DVI->getContext();
|
||||||
|
DVI->setOperand(0, MetadataAsValue::get(Ctx, ValueAsMetadata::get(V)));
|
||||||
|
if (Offset) {
|
||||||
|
SmallVector<uint64_t, 8> Ops;
|
||||||
|
DIExpression::appendOffset(Ops, Offset);
|
||||||
|
DbgDIExpr = DIExpression::prependOpcodes(DbgDIExpr, Ops, true);
|
||||||
|
}
|
||||||
|
DVI->setOperand(2, MetadataAsValue::get(Ctx, DbgDIExpr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
||||||
DominatorTree &DT, LoopInfo &LI,
|
DominatorTree &DT, LoopInfo &LI,
|
||||||
const TargetTransformInfo &TTI,
|
const TargetTransformInfo &TTI,
|
||||||
|
@ -5789,6 +5846,11 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
||||||
Changed |=
|
Changed |=
|
||||||
LSRInstance(L, IU, SE, DT, LI, TTI, AC, TLI, MSSAU.get()).getChanged();
|
LSRInstance(L, IU, SE, DT, LI, TTI, AC, TLI, MSSAU.get()).getChanged();
|
||||||
|
|
||||||
|
// Debug preservation - before we start removing anything create equivalence
|
||||||
|
// sets for the llvm.dbg.value intrinsics.
|
||||||
|
EqualValuesMap DbgValueToEqualSet;
|
||||||
|
DbgGatherEqualValues(L, SE, DbgValueToEqualSet);
|
||||||
|
|
||||||
// Remove any extra phis created by processing inner loops.
|
// Remove any extra phis created by processing inner loops.
|
||||||
Changed |= DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
|
Changed |= DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
|
||||||
if (EnablePhiElim && L->isLoopSimplifyForm()) {
|
if (EnablePhiElim && L->isLoopSimplifyForm()) {
|
||||||
|
@ -5806,6 +5868,9 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
|
||||||
DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
|
DeleteDeadPHIs(L->getHeader(), &TLI, MSSAU.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DbgApplyEqualValues(DbgValueToEqualSet);
|
||||||
|
|
||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
; ASM: popl %ebx
|
; ASM: popl %ebx
|
||||||
; ASM: [[EPILOGUE]]: # %return
|
; ASM: [[EPILOGUE]]: # %return
|
||||||
; ASM: retl $8
|
; ASM: retl $8
|
||||||
; ASM: Ltmp10:
|
; ASM: Ltmp11:
|
||||||
; ASM: .cv_fpo_endproc
|
; ASM: .cv_fpo_endproc
|
||||||
|
|
||||||
; Note how RvaStart advances 7 bytes to skip the shrink-wrapped portion.
|
; Note how RvaStart advances 7 bytes to skip the shrink-wrapped portion.
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
; RUN: opt < %s -loop-reduce -S | FileCheck %s
|
||||||
|
|
||||||
|
; Test that LSR preserves debug-info for induction variables.
|
||||||
|
|
||||||
|
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
|
||||||
|
|
||||||
|
define dso_local void @foo(i8* nocapture %p) local_unnamed_addr !dbg !7 {
|
||||||
|
; CHECK-LABEL: @foo(
|
||||||
|
entry:
|
||||||
|
call void @llvm.dbg.value(metadata i8* %p, metadata !13, metadata !DIExpression()), !dbg !16
|
||||||
|
call void @llvm.dbg.value(metadata i8 0, metadata !14, metadata !DIExpression()), !dbg !17
|
||||||
|
br label %for.body, !dbg !18
|
||||||
|
|
||||||
|
for.cond.cleanup: ; preds = %for.body
|
||||||
|
ret void, !dbg !19
|
||||||
|
|
||||||
|
for.body: ; preds = %entry, %for.body
|
||||||
|
; CHECK-LABEL: 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 !14, metadata !DIExpression()), !dbg !17
|
||||||
|
call void @llvm.dbg.value(metadata i8* %p.addr.05, metadata !13, metadata !DIExpression()), !dbg !16
|
||||||
|
; CHECK-NOT: call void @llvm.dbg.value(metadata i8* undef
|
||||||
|
; CHECK: call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata ![[MID_p:[0-9]+]], metadata !DIExpression(DW_OP_constu, 3, DW_OP_minus, DW_OP_stack_value)), !dbg !16
|
||||||
|
%add.ptr = getelementptr inbounds i8, i8* %p.addr.05, i64 3, !dbg !20
|
||||||
|
call void @llvm.dbg.value(metadata i8* %add.ptr, metadata !13, metadata !DIExpression()), !dbg !16
|
||||||
|
; CHECK-NOT: call void @llvm.dbg.value(metadata i8* undef
|
||||||
|
; CHECK: call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata ![[MID_p]], metadata !DIExpression()), !dbg !16
|
||||||
|
store i8 %i.06, i8* %add.ptr, align 1, !dbg !23, !tbaa !24
|
||||||
|
%inc = add nuw nsw i8 %i.06, 1, !dbg !27
|
||||||
|
call void @llvm.dbg.value(metadata i8 %inc, metadata !14, metadata !DIExpression()), !dbg !17
|
||||||
|
%exitcond.not = icmp eq i8 %inc, 32, !dbg !28
|
||||||
|
br i1 %exitcond.not, label %for.cond.cleanup, label %for.body, !dbg !18, !llvm.loop !29
|
||||||
|
}
|
||||||
|
|
||||||
|
declare void @llvm.dbg.value(metadata, metadata, metadata)
|
||||||
|
|
||||||
|
!llvm.dbg.cu = !{!0}
|
||||||
|
!llvm.module.flags = !{!3, !4, !5}
|
||||||
|
!llvm.ident = !{!6}
|
||||||
|
|
||||||
|
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 12.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
|
||||||
|
!1 = !DIFile(filename: "lsrdbg.c", directory: "/")
|
||||||
|
!2 = !{}
|
||||||
|
!3 = !{i32 7, !"Dwarf Version", i32 4}
|
||||||
|
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||||
|
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||||
|
!6 = !{!"clang version 12.0.0"}
|
||||||
|
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !8, scopeLine: 2, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !12)
|
||||||
|
!8 = !DISubroutineType(types: !9)
|
||||||
|
!9 = !{null, !10}
|
||||||
|
!10 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !11, size: 64)
|
||||||
|
!11 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
|
||||||
|
!12 = !{!13, !14}
|
||||||
|
!13 = !DILocalVariable(name: "p", arg: 1, scope: !7, file: !1, line: 2, type: !10)
|
||||||
|
; CHECK: ![[MID_p]] = !DILocalVariable(name: "p", arg: 1, scope: !7, file: !1, line: 2, type: !10)
|
||||||
|
!14 = !DILocalVariable(name: "i", scope: !15, file: !1, line: 4, type: !11)
|
||||||
|
!15 = distinct !DILexicalBlock(scope: !7, file: !1, line: 4, column: 3)
|
||||||
|
!16 = !DILocation(line: 0, scope: !7)
|
||||||
|
!17 = !DILocation(line: 0, scope: !15)
|
||||||
|
!18 = !DILocation(line: 4, column: 3, scope: !15)
|
||||||
|
!19 = !DILocation(line: 8, column: 1, scope: !7)
|
||||||
|
!20 = !DILocation(line: 5, column: 7, scope: !21)
|
||||||
|
!21 = distinct !DILexicalBlock(scope: !22, file: !1, line: 4, column: 42)
|
||||||
|
!22 = distinct !DILexicalBlock(scope: !15, file: !1, line: 4, column: 3)
|
||||||
|
!23 = !DILocation(line: 6, column: 8, scope: !21)
|
||||||
|
!24 = !{!25, !25, i64 0}
|
||||||
|
!25 = !{!"omnipotent char", !26, i64 0}
|
||||||
|
!26 = !{!"Simple C/C++ TBAA"}
|
||||||
|
!27 = !DILocation(line: 4, column: 38, scope: !22)
|
||||||
|
!28 = !DILocation(line: 4, column: 31, scope: !22)
|
||||||
|
!29 = distinct !{!29, !18, !30, !31}
|
||||||
|
!30 = !DILocation(line: 7, column: 3, scope: !15)
|
||||||
|
!31 = !{!"llvm.loop.unroll.disable"}
|
Loading…
Reference in New Issue