@@ -5914,15 +5914,17 @@ void LoopStrengthReduce::getAnalysisUsage(AnalysisUsage &AU) const {
5914
5914
namespace {
5915
5915
struct SCEVDbgValueBuilder {
5916
5916
SCEVDbgValueBuilder () = default ;
5917
- SCEVDbgValueBuilder (const SCEVDbgValueBuilder &Base) {
5917
+ SCEVDbgValueBuilder (const SCEVDbgValueBuilder &Base) { clone (Base); }
5918
+
5919
+ void clone (const SCEVDbgValueBuilder &Base) {
5918
5920
Values = Base.Values ;
5919
5921
Expr = Base.Expr ;
5920
5922
}
5921
5923
5922
5924
// / The DIExpression as we translate the SCEV.
5923
5925
SmallVector<uint64_t , 6 > Expr;
5924
5926
// / The location ops of the DIExpression.
5925
- SmallVector<llvm::ValueAsMetadata *, 2 > Values;
5927
+ SmallVector<Value *, 2 > Values;
5926
5928
5927
5929
void pushOperator (uint64_t Op) { Expr.push_back (Op); }
5928
5930
void pushUInt (uint64_t Operand) { Expr.push_back (Operand); }
@@ -5931,14 +5933,13 @@ struct SCEVDbgValueBuilder {
5931
5933
// / in the set of values referenced by the expression.
5932
5934
void pushValue (llvm::Value *V) {
5933
5935
Expr.push_back (llvm::dwarf::DW_OP_LLVM_arg);
5934
- auto *It =
5935
- std::find (Values.begin (), Values.end (), llvm::ValueAsMetadata::get (V));
5936
+ auto *It = std::find (Values.begin (), Values.end (), V);
5936
5937
unsigned ArgIndex = 0 ;
5937
5938
if (It != Values.end ()) {
5938
5939
ArgIndex = std::distance (Values.begin (), It);
5939
5940
} else {
5940
5941
ArgIndex = Values.size ();
5941
- Values.push_back (llvm::ValueAsMetadata::get (V) );
5942
+ Values.push_back (V );
5942
5943
}
5943
5944
Expr.push_back (ArgIndex);
5944
5945
}
@@ -6028,52 +6029,6 @@ struct SCEVDbgValueBuilder {
6028
6029
return Success;
6029
6030
}
6030
6031
6031
- void setFinalExpression (llvm::DbgValueInst &DI, const DIExpression *OldExpr) {
6032
- // Re-state assumption that this dbg.value is not variadic. Any remaining
6033
- // opcodes in its expression operate on a single value already on the
6034
- // expression stack. Prepend our operations, which will re-compute and
6035
- // place that value on the expression stack.
6036
- assert (!DI.hasArgList ());
6037
- auto *NewExpr =
6038
- DIExpression::prependOpcodes (OldExpr, Expr, /* StackValue*/ true );
6039
- DI.setExpression (NewExpr);
6040
-
6041
- auto ValArrayRef = llvm::ArrayRef<llvm::ValueAsMetadata *>(Values);
6042
- DI.setRawLocation (llvm::DIArgList::get (DI.getContext (), ValArrayRef));
6043
- }
6044
-
6045
- // / If a DVI can be emitted without a DIArgList, omit DW_OP_llvm_arg and the
6046
- // / location op index 0.
6047
- void setShortFinalExpression (llvm::DbgValueInst &DI,
6048
- const DIExpression *OldExpr) {
6049
- assert ((Expr[0 ] == llvm::dwarf::DW_OP_LLVM_arg && Expr[1 ] == 0 ) &&
6050
- " Expected DW_OP_llvm_arg and 0." );
6051
- DI.replaceVariableLocationOp (
6052
- 0u , llvm::MetadataAsValue::get (DI.getContext (), Values[0 ]));
6053
-
6054
- // See setFinalExpression: prepend our opcodes on the start of any old
6055
- // expression opcodes.
6056
- assert (!DI.hasArgList ());
6057
- llvm::SmallVector<uint64_t , 6 > FinalExpr (llvm::drop_begin (Expr, 2 ));
6058
- auto *NewExpr =
6059
- DIExpression::prependOpcodes (OldExpr, FinalExpr, /* StackValue*/ true );
6060
- DI.setExpression (NewExpr);
6061
- }
6062
-
6063
- // / Once the IV and variable SCEV translation is complete, write it to the
6064
- // / source DVI.
6065
- void applyExprToDbgValue (llvm::DbgValueInst &DI,
6066
- const DIExpression *OldExpr) {
6067
- assert (!Expr.empty () && " Unexpected empty expression." );
6068
- // Emit a simpler form if only a single location is referenced.
6069
- if (Values.size () == 1 && Expr[0 ] == llvm::dwarf::DW_OP_LLVM_arg &&
6070
- Expr[1 ] == 0 ) {
6071
- setShortFinalExpression (DI, OldExpr);
6072
- } else {
6073
- setFinalExpression (DI, OldExpr);
6074
- }
6075
- }
6076
-
6077
6032
// / Return true if the combination of arithmetic operator and underlying
6078
6033
// / SCEV constant value is an identity function.
6079
6034
bool isIdentityFunction (uint64_t Op, const SCEV *S) {
@@ -6122,6 +6077,44 @@ struct SCEVDbgValueBuilder {
6122
6077
return true ;
6123
6078
}
6124
6079
6080
+ // / Create an expression that is an offset from a value (usually the IV).
6081
+ void createOffsetExpr (int64_t Offset, Value *OffsetValue) {
6082
+ pushValue (OffsetValue);
6083
+ DIExpression::appendOffset (Expr, Offset);
6084
+ LLVM_DEBUG (
6085
+ dbgs () << " scev-salvage: Generated IV offset expression. Offset: "
6086
+ << std::to_string (Offset) << " \n " );
6087
+ }
6088
+
6089
+ // / Combine a translation of the SCEV and the IV to create an expression that
6090
+ // / recovers a location's value.
6091
+ void createIterCountExpr (const SCEV *S,
6092
+ const SCEVDbgValueBuilder &IterationCount,
6093
+ ScalarEvolution &SE) {
6094
+ // SCEVs for SSA values are most frquently of the form
6095
+ // {start,+,stride}, but sometimes they are ({start,+,stride} + %a + ..).
6096
+ // This is because %a is a PHI node that is not the IV. However, these
6097
+ // SCEVs have not been observed to result in debuginfo-lossy optimisations,
6098
+ // so its not expected this point will be reached.
6099
+ if (!isa<SCEVAddRecExpr>(S))
6100
+ return ;
6101
+
6102
+ LLVM_DEBUG (dbgs () << " scev-salvage: Value to salvage SCEV: " << *S << ' \n ' );
6103
+
6104
+ const auto *Rec = cast<SCEVAddRecExpr>(S);
6105
+ if (!Rec->isAffine ())
6106
+ return ;
6107
+
6108
+ if (S->getExpressionSize () > MaxSCEVSalvageExpressionSize)
6109
+ return ;
6110
+
6111
+ // Initialise a new builder with the iteration count expression. In
6112
+ // combination with the value's SCEV this enables recovery.
6113
+ clone (IterationCount);
6114
+ if (!SCEVToValueExpr (*Rec, SE))
6115
+ return ;
6116
+ }
6117
+
6125
6118
// / Convert a SCEV of a value to a DIExpression that is pushed onto the
6126
6119
// / builder's expression stack. The stack should already contain an
6127
6120
// / expression for the iteration count, so that it can be multiplied by
@@ -6153,6 +6146,8 @@ struct SCEVDbgValueBuilder {
6153
6146
}
6154
6147
};
6155
6148
6149
+ // / Holds all the required data to salvage a dbg.value using the pre-LSR SCEVs
6150
+ // / and DIExpression.
6156
6151
struct DVIRecoveryRec {
6157
6152
DbgValueInst *DVI;
6158
6153
DIExpression *Expr;
@@ -6161,60 +6156,80 @@ struct DVIRecoveryRec {
6161
6156
};
6162
6157
} // namespace
6163
6158
6164
- static void RewriteDVIUsingIterCount (DVIRecoveryRec CachedDVI,
6165
- const SCEVDbgValueBuilder &IterationCount,
6166
- ScalarEvolution &SE) {
6167
- // LSR may add locations to previously single location-op DVIs which
6168
- // are currently not supported.
6169
- if (CachedDVI.DVI ->getNumVariableLocationOps () != 1 )
6170
- return ;
6171
-
6172
- // SCEVs for SSA values are most frquently of the form
6173
- // {start,+,stride}, but sometimes they are ({start,+,stride} + %a + ..).
6174
- // This is because %a is a PHI node that is not the IV. However, these
6175
- // SCEVs have not been observed to result in debuginfo-lossy optimisations,
6176
- // so its not expected this point will be reached.
6177
- if (!isa<SCEVAddRecExpr>(CachedDVI.SCEV ))
6178
- return ;
6159
+ // / Write the new expression and new location ops for the dbg.value. Emit as
6160
+ // / short a expression as possible based on checks of the expression length and
6161
+ // / number of location ops.
6162
+ static void UpdateDbgValueInst (DVIRecoveryRec &DVIRec,
6163
+ SmallVectorImpl<Value *> &NewLocationOps,
6164
+ SmallVectorImpl<uint64_t > &NewExpr) {
6165
+
6166
+ // If there is only a single location op, the {DW_OP_LLVM_arg, 0} sequence
6167
+ // can be omitted from the expression. Also, DIArglist() can be ommitted from
6168
+ // the first argument of the dbg.value.
6169
+ if (NewLocationOps.size () == 1 && NewExpr[0 ] == dwarf::DW_OP_LLVM_arg &&
6170
+ NewExpr[1 ] == 0 ) {
6171
+ DVIRec.DVI ->replaceVariableLocationOp (0u , NewLocationOps[0 ]);
6172
+ llvm::SmallVector<uint64_t , 6 > ShortExpr (llvm::drop_begin (NewExpr, 2 ));
6173
+ auto *FinalExpr = DIExpression::prependOpcodes (DVIRec.Expr , ShortExpr,
6174
+ /* StackValue*/ true );
6175
+ DVIRec.DVI ->setExpression (FinalExpr);
6176
+ } else {
6177
+ SmallVector<ValueAsMetadata *, 3 > MetadataLocs;
6178
+ for (Value *V : NewLocationOps)
6179
+ MetadataLocs.push_back (ValueAsMetadata::get (V));
6180
+ auto ValArrayRef = llvm::ArrayRef<llvm::ValueAsMetadata *>(MetadataLocs);
6181
+ DVIRec.DVI ->setRawLocation (
6182
+ llvm::DIArgList::get (DVIRec.DVI ->getContext (), ValArrayRef));
6183
+ auto *FinalExpr =
6184
+ DIExpression::prependOpcodes (DVIRec.Expr , NewExpr, /* StackValue*/ true );
6185
+ DVIRec.DVI ->setExpression (FinalExpr);
6186
+ }
6187
+ }
6188
+
6189
+ static bool SalvageDVI (llvm::Loop *L, ScalarEvolution &SE,
6190
+ llvm::PHINode *LSRInductionVar, DVIRecoveryRec &DVIRec,
6191
+ const SCEV *SCEVInductionVar,
6192
+ SCEVDbgValueBuilder IterCountExpr) {
6193
+ if (!DVIRec.DVI ->isUndef ())
6194
+ return false ;
6179
6195
6180
- LLVM_DEBUG (dbgs () << " scev-salvage: Value to salvage SCEV: "
6181
- << *CachedDVI.SCEV << ' \n ' );
6196
+ // Some DVIs that were single location-op when cached are now multi-op,
6197
+ // due to LSR optimisations. However, multi-op salvaging is not yet
6198
+ // supported by SCEV salvaging. The expression applies to a single
6199
+ // location op, so the DIAarglist must be replaced by the original location,
6200
+ // which is now undef.
6201
+ if (DVIRec.DVI ->hasArgList ()) {
6202
+ if (DVIRec.DVI ->getNumVariableLocationOps () == 0 ||
6203
+ !DVIRec.DVI ->getVariableLocationOp (0 ))
6204
+ return false ;
6205
+ llvm::Type *Ty = DVIRec.DVI ->getVariableLocationOp (0 )->getType ();
6206
+ DVIRec.DVI ->setRawLocation (llvm::ValueAsMetadata::get (UndefValue::get (Ty)));
6207
+ DVIRec.DVI ->setExpression (DVIRec.Expr );
6208
+ }
6182
6209
6183
- const auto *Rec = cast<SCEVAddRecExpr>(CachedDVI.SCEV );
6184
- if (!Rec->isAffine ())
6185
- return ;
6210
+ LLVM_DEBUG (dbgs () << " scev-salvage: attempt to salvage: " << *DVIRec.DVI
6211
+ << ' \n ' );
6186
6212
6187
- if (CachedDVI.SCEV ->getExpressionSize () > MaxSCEVSalvageExpressionSize)
6188
- return ;
6213
+ SCEVDbgValueBuilder SalvageExpr;
6189
6214
6190
- // Initialise a new builder with the iteration count expression. In
6191
- // combination with the value's SCEV this enables recovery.
6192
- SCEVDbgValueBuilder RecoverValue (IterationCount);
6193
- if (!RecoverValue.SCEVToValueExpr (*Rec, SE))
6194
- return ;
6215
+ // Create an offset-based salvage expression if possible, as it requires
6216
+ // less DWARF ops than an iteration count-based expression.
6217
+ if (Optional<APInt> Offset =
6218
+ SE.computeConstantDifference (DVIRec.SCEV , SCEVInductionVar)) {
6219
+ if (Offset.getValue ().getMinSignedBits () <= 64 )
6220
+ SalvageExpr.createOffsetExpr (Offset.getValue ().getSExtValue (),
6221
+ LSRInductionVar);
6222
+ } else
6223
+ SalvageExpr.createIterCountExpr (DVIRec.SCEV , IterCountExpr, SE);
6195
6224
6196
- LLVM_DEBUG (dbgs () << " scev-salvage: Updating: " << *CachedDVI.DVI << ' \n ' );
6197
- RecoverValue.applyExprToDbgValue (*CachedDVI.DVI , CachedDVI.Expr );
6198
- LLVM_DEBUG (dbgs () << " scev-salvage: to: " << *CachedDVI.DVI << ' \n ' );
6199
- }
6225
+ UpdateDbgValueInst (DVIRec, SalvageExpr.Values , SalvageExpr.Expr );
6200
6226
6201
- static void RewriteDVIUsingOffset (DVIRecoveryRec &DVIRec, llvm::PHINode &IV,
6202
- int64_t Offset) {
6203
- assert (!DVIRec.DVI ->hasArgList () && " Expected single location-op dbg.value." );
6204
- DbgValueInst *DVI = DVIRec.DVI ;
6205
- SmallVector<uint64_t , 8 > Ops;
6206
- DIExpression::appendOffset (Ops, Offset);
6207
- DIExpression *Expr = DIExpression::prependOpcodes (DVIRec.Expr , Ops, true );
6208
- LLVM_DEBUG (dbgs () << " scev-salvage: Updating: " << *DVIRec.DVI << ' \n ' );
6209
- DVI->setExpression (Expr);
6210
- llvm::Value *ValIV = dyn_cast<llvm::Value>(&IV);
6211
- DVI->replaceVariableLocationOp (
6212
- 0u , llvm::MetadataAsValue::get (DVI->getContext (),
6213
- llvm::ValueAsMetadata::get (ValIV)));
6214
- LLVM_DEBUG (dbgs () << " scev-salvage: updated with offset to IV: "
6215
- << *DVIRec.DVI << ' \n ' );
6227
+ LLVM_DEBUG (dbgs () << " scev-salvage: Updated DVI: " << *DVIRec.DVI << " \n " );
6228
+ return true ;
6216
6229
}
6217
6230
6231
+ // / Obtain an expression for the iteration count, then attempt to salvage the
6232
+ // / dbg.value intrinsics.
6218
6233
static void
6219
6234
DbgRewriteSalvageableDVIs (llvm::Loop *L, ScalarEvolution &SE,
6220
6235
llvm::PHINode *LSRInductionVar,
@@ -6231,6 +6246,7 @@ DbgRewriteSalvageableDVIs(llvm::Loop *L, ScalarEvolution &SE,
6231
6246
if (!IVAddRec->isAffine ())
6232
6247
return ;
6233
6248
6249
+ // Prevent translation using excessive resources.
6234
6250
if (IVAddRec->getExpressionSize () > MaxSCEVSalvageExpressionSize)
6235
6251
return ;
6236
6252
@@ -6243,37 +6259,9 @@ DbgRewriteSalvageableDVIs(llvm::Loop *L, ScalarEvolution &SE,
6243
6259
LLVM_DEBUG (dbgs () << " scev-salvage: IV SCEV: " << *SCEVInductionVar
6244
6260
<< ' \n ' );
6245
6261
6246
- // Needn't salvage if the location op hasn't been undef'd by LSR.
6247
6262
for (auto &DVIRec : DVIToUpdate) {
6248
- if (!DVIRec.DVI ->isUndef ())
6249
- continue ;
6250
-
6251
- // Some DVIs that were single location-op when cached are now multi-op,
6252
- // due to LSR optimisations. However, multi-op salvaging is not yet
6253
- // supported by SCEV salvaging. But, we can attempt a salvage by restoring
6254
- // the pre-LSR single-op expression.
6255
- if (DVIRec.DVI ->hasArgList ()) {
6256
- if (!DVIRec.DVI ->getVariableLocationOp (0 ))
6257
- continue ;
6258
- llvm::Type *Ty = DVIRec.DVI ->getVariableLocationOp (0 )->getType ();
6259
- DVIRec.DVI ->setRawLocation (
6260
- llvm::ValueAsMetadata::get (UndefValue::get (Ty)));
6261
- DVIRec.DVI ->setExpression (DVIRec.Expr );
6262
- }
6263
-
6264
- LLVM_DEBUG (dbgs () << " scev-salvage: value to recover SCEV: "
6265
- << *DVIRec.SCEV << ' \n ' );
6266
-
6267
- // Create a simple expression if the IV and value to salvage SCEVs
6268
- // start values differ by only a constant value.
6269
- if (Optional<APInt> Offset =
6270
- SE.computeConstantDifference (DVIRec.SCEV , SCEVInductionVar)) {
6271
- if (Offset.getValue ().getMinSignedBits () <= 64 )
6272
- RewriteDVIUsingOffset (DVIRec, *LSRInductionVar,
6273
- Offset.getValue ().getSExtValue ());
6274
- } else {
6275
- RewriteDVIUsingIterCount (DVIRec, IterCountExpr, SE);
6276
- }
6263
+ SalvageDVI (L, SE, LSRInductionVar, DVIRec, SCEVInductionVar,
6264
+ IterCountExpr);
6277
6265
}
6278
6266
}
6279
6267
}
0 commit comments