diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp --- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp +++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp @@ -6126,13 +6126,13 @@ const llvm::SCEV *SCEV; }; -static bool RewriteDVIUsingIterCount(DVIRecoveryRec CachedDVI, +static void RewriteDVIUsingIterCount(DVIRecoveryRec CachedDVI, const SCEVDbgValueBuilder &IterationCount, ScalarEvolution &SE) { // LSR may add locations to previously single location-op DVIs which // are currently not supported. if (CachedDVI.DVI->getNumVariableLocationOps() != 1) - return false; + return; // SCEVs for SSA values are most frquently of the form // {start,+,stride}, but sometimes they are ({start,+,stride} + %a + ..). @@ -6140,48 +6140,64 @@ // SCEVs have not been observed to result in debuginfo-lossy optimisations, // so its not expected this point will be reached. if (!isa(CachedDVI.SCEV)) - return false; + return; LLVM_DEBUG(dbgs() << "scev-salvage: Value to salvage SCEV: " << *CachedDVI.SCEV << '\n'); const auto *Rec = cast(CachedDVI.SCEV); if (!Rec->isAffine()) - return false; + return; // Initialise a new builder with the iteration count expression. In // combination with the value's SCEV this enables recovery. SCEVDbgValueBuilder RecoverValue(IterationCount); if (!RecoverValue.SCEVToValueExpr(*Rec, SE)) - return false; + return; LLVM_DEBUG(dbgs() << "scev-salvage: Updating: " << *CachedDVI.DVI << '\n'); RecoverValue.applyExprToDbgValue(*CachedDVI.DVI, CachedDVI.Expr); LLVM_DEBUG(dbgs() << "scev-salvage: to: " << *CachedDVI.DVI << '\n'); - return true; } -static bool +static void RewriteDVIUsingOffset(DVIRecoveryRec &DVIRec, llvm::PHINode &IV, + int64_t Offset) { + assert(!DVIRec.DVI->hasArgList() && "Expected single location-op dbg.value."); + DbgValueInst *DVI = DVIRec.DVI; + SmallVector Ops; + DIExpression::appendOffset(Ops, Offset); + DIExpression *Expr = DIExpression::prependOpcodes(DVIRec.Expr, Ops, true); + LLVM_DEBUG(dbgs() << "scev-salvage: Updating: " << *DVIRec.DVI << '\n'); + DVI->setExpression(Expr); + llvm::Value *ValIV = dyn_cast(&IV); + DVI->replaceVariableLocationOp( + 0u, llvm::MetadataAsValue::get(DVI->getContext(), + llvm::ValueAsMetadata::get(ValIV))); + LLVM_DEBUG(dbgs() << "scev-salvage: updated with offset to IV: " + << *DVIRec.DVI << '\n'); +} + +static void DbgRewriteSalvageableDVIs(llvm::Loop *L, ScalarEvolution &SE, llvm::PHINode *LSRInductionVar, SmallVector &DVIToUpdate) { if (DVIToUpdate.empty()) - return false; + return; const llvm::SCEV *SCEVInductionVar = SE.getSCEV(LSRInductionVar); assert(SCEVInductionVar && "Anticipated a SCEV for the post-LSR induction variable"); - bool Changed = false; if (const SCEVAddRecExpr *IVAddRec = dyn_cast(SCEVInductionVar)) { if (!IVAddRec->isAffine()) - return false; + return; + // The iteratioun count is required to recover location values. SCEVDbgValueBuilder IterCountExpr; IterCountExpr.pushValue(LSRInductionVar); if (!IterCountExpr.SCEVToIterCountExpr(*IVAddRec, SE)) - return false; + return; LLVM_DEBUG(dbgs() << "scev-salvage: IV SCEV: " << *SCEVInductionVar << '\n'); @@ -6204,10 +6220,21 @@ DVIRec.DVI->setExpression(DVIRec.Expr); } - Changed |= RewriteDVIUsingIterCount(DVIRec, IterCountExpr, SE); + LLVM_DEBUG(dbgs() << "scev-salvage: value to recover SCEV: " + << *DVIRec.SCEV << '\n'); + + // Create a simple expression if the IV and value to salvage SCEVs + // start values differ by only a constant value. + if (Optional Offset = + SE.computeConstantDifference(DVIRec.SCEV, SCEVInductionVar)) { + if (Offset.getValue().getMinSignedBits() <= 64) + RewriteDVIUsingOffset(DVIRec, *LSRInductionVar, + Offset.getValue().getSExtValue()); + } else { + RewriteDVIUsingIterCount(DVIRec, IterCountExpr, SE); + } } } - return Changed; } /// Identify and cache salvageable DVI locations and expressions along with the diff --git a/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll b/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll --- a/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll +++ b/llvm/test/Transforms/LoopStrengthReduce/dbg-preserve-0.ll @@ -1,6 +1,8 @@ -; RUN: opt < %s -loop-reduce -S | FileCheck %s +; RUN: opt -loop-reduce -S %s | FileCheck %s -; Test that LSR preserves debug-info for induction variables. +;; Test that LSR preserves debug-info for induction variables and scev-based +;; salvaging produces short DIExpressions that use a constant offset from the +;; induction variable. target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -21,11 +23,11 @@ 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 !DIArgList(i8* %lsr.iv, i8* %p), metadata ![[MID_p:[0-9]+]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_consts, 3, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_minus, DW_OP_consts, 3, DW_OP_div, DW_OP_consts, 3, DW_OP_mul, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_stack_value)) +; CHECK: all 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)) %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 !DIArgList(i8* %lsr.iv, i8* %p), metadata ![[MID_p]], metadata !DIExpression(DW_OP_LLVM_arg, 0, DW_OP_consts, 3, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_minus, DW_OP_consts, 3, DW_OP_div, DW_OP_consts, 3, DW_OP_mul, DW_OP_consts, 3, DW_OP_LLVM_arg, 1, DW_OP_plus, DW_OP_plus, DW_OP_stack_value)) +; CHECK: call void @llvm.dbg.value(metadata i8* %lsr.iv, metadata ![[MID_p]], metadata !DIExpression()) 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