@@ -4967,46 +4967,224 @@ AllocaInst *SROA::rewritePartition(AllocaInst &AI, AllocaSlices &AS,
4967
4967
return NewAI;
4968
4968
}
4969
4969
4970
- static void insertNewDbgInst (DIBuilder &DIB, DbgDeclareInst *Orig,
4971
- AllocaInst *NewAddr, DIExpression *NewFragmentExpr,
4972
- Instruction *BeforeInst) {
4973
- DIB.insertDeclare (NewAddr, Orig->getVariable (), NewFragmentExpr,
4970
+ // There isn't a shared interface to get the "address" parts out of a
4971
+ // dbg.declare and dbg.assign, so provide some wrappers now for
4972
+ // both debug intrinsics and records.
4973
+ const Value *getAddress (const DbgVariableIntrinsic *DVI) {
4974
+ if (const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
4975
+ return DAI->getAddress ();
4976
+ return cast<DbgDeclareInst>(DVI)->getAddress ();
4977
+ }
4978
+ const Value *getAddress (const DbgVariableRecord *DVR) {
4979
+ assert (DVR->getType () == DbgVariableRecord::LocationType::Declare ||
4980
+ DVR->getType () == DbgVariableRecord::LocationType::Assign);
4981
+ return DVR->getAddress ();
4982
+ }
4983
+ bool isKillAddress (const DbgVariableIntrinsic *DVI) {
4984
+ if (const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
4985
+ return DAI->isKillAddress ();
4986
+ return cast<DbgDeclareInst>(DVI)->isKillLocation ();
4987
+ }
4988
+ bool isKillAddress (const DbgVariableRecord *DVR) {
4989
+ assert (DVR->getType () == DbgVariableRecord::LocationType::Declare ||
4990
+ DVR->getType () == DbgVariableRecord::LocationType::Assign);
4991
+ if (DVR->getType () == DbgVariableRecord::LocationType::Assign)
4992
+ return DVR->isKillAddress ();
4993
+ return DVR->isKillLocation ();
4994
+ }
4995
+ const DIExpression *getAddressExpression (const DbgVariableIntrinsic *DVI) {
4996
+ if (const auto *DAI = dyn_cast<DbgAssignIntrinsic>(DVI))
4997
+ return DAI->getAddressExpression ();
4998
+ return cast<DbgDeclareInst>(DVI)->getExpression ();
4999
+ }
5000
+ const DIExpression *getAddressExpression (const DbgVariableRecord *DVR) {
5001
+ assert (DVR->getType () == DbgVariableRecord::LocationType::Declare ||
5002
+ DVR->getType () == DbgVariableRecord::LocationType::Assign);
5003
+ if (DVR->getType () == DbgVariableRecord::LocationType::Assign)
5004
+ return DVR->getAddressExpression ();
5005
+ return DVR->getExpression ();
5006
+ }
5007
+
5008
+ // / Similar to DIExpression::createFragmentExpression except for 3 important
5009
+ // / distinctions:
5010
+ // / 1. The new fragment isn't relative to an existing fragment.
5011
+ // / 2. There are no checks on the the operation types because it is assumed
5012
+ // / the location this expression is computing is not implicit (i.e., it's
5013
+ // / always safe to create a fragment because arithmetic operations apply
5014
+ // / to the address computation, not to an implicit value computation).
5015
+ // / 3. Existing extract_bits are modified independetly of fragment changes
5016
+ // / using \p BitExtractOffset. A change to the fragment offset or size
5017
+ // / may affect a bit extract. But a bit extract offset can change
5018
+ // / independently of the fragment dimensions.
5019
+ // /
5020
+ // / Returns the new expression, or nullptr if one couldn't be created.
5021
+ // / Ideally this is only used to signal that a bit-extract has become
5022
+ // / zero-sized (and thus the new debug record has no size and can be
5023
+ // / dropped), however, it fails for other reasons too - see the FIXME below.
5024
+ // /
5025
+ // / FIXME: To keep the change that introduces this function NFC it bails
5026
+ // / in some situations unecessarily, e.g. when fragment and bit extract
5027
+ // / sizes differ.
5028
+ static DIExpression *createOrReplaceFragment (const DIExpression *Expr,
5029
+ DIExpression::FragmentInfo Frag,
5030
+ int64_t BitExtractOffset) {
5031
+ SmallVector<uint64_t , 8 > Ops;
5032
+ bool HasFragment = false ;
5033
+ bool HasBitExtract = false ;
5034
+
5035
+ for (auto &Op : Expr->expr_ops ()) {
5036
+ if (Op.getOp () == dwarf::DW_OP_LLVM_fragment) {
5037
+ HasFragment = true ;
5038
+ continue ;
5039
+ }
5040
+ if (Op.getOp () == dwarf::DW_OP_LLVM_extract_bits_zext ||
5041
+ Op.getOp () == dwarf::DW_OP_LLVM_extract_bits_sext) {
5042
+ HasBitExtract = true ;
5043
+ int64_t ExtractOffsetInBits = Op.getArg (0 );
5044
+ int64_t ExtractSizeInBits = Op.getArg (1 );
5045
+
5046
+ // DIExpression::createFragmentExpression doesn't know how to handle
5047
+ // a fragment that is smaller than the extract. Copy the behaviour
5048
+ // (bail) to avoid non-NFC changes.
5049
+ // FIXME: Don't do this.
5050
+ if (Frag.SizeInBits < uint64_t (ExtractSizeInBits))
5051
+ return nullptr ;
5052
+
5053
+ assert (BitExtractOffset <= 0 );
5054
+ int64_t AdjustedOffset = ExtractOffsetInBits + BitExtractOffset;
5055
+
5056
+ // DIExpression::createFragmentExpression doesn't know what to do
5057
+ // if the new extract starts "outside" the existing one. Copy the
5058
+ // behaviour (bail) to avoid non-NFC changes.
5059
+ // FIXME: Don't do this.
5060
+ if (AdjustedOffset < 0 )
5061
+ return nullptr ;
5062
+
5063
+ Ops.push_back (Op.getOp ());
5064
+ Ops.push_back (std::max<int64_t >(0 , AdjustedOffset));
5065
+ Ops.push_back (ExtractSizeInBits);
5066
+ continue ;
5067
+ }
5068
+ Op.appendToVector (Ops);
5069
+ }
5070
+
5071
+ // Unsupported by createFragmentExpression, so don't support it here yet to
5072
+ // preserve NFC-ness.
5073
+ if (HasFragment && HasBitExtract)
5074
+ return nullptr ;
5075
+
5076
+ if (!HasBitExtract) {
5077
+ Ops.push_back (dwarf::DW_OP_LLVM_fragment);
5078
+ Ops.push_back (Frag.OffsetInBits );
5079
+ Ops.push_back (Frag.SizeInBits );
5080
+ }
5081
+ return DIExpression::get (Expr->getContext (), Ops);
5082
+ }
5083
+
5084
+ // / Insert a new dbg.declare.
5085
+ // / \p Orig Original to copy debug loc and variable from.
5086
+ // / \p NewAddr Location's new base address.
5087
+ // / \p NewAddrExpr New expression to apply to address.
5088
+ // / \p BeforeInst Insert position.
5089
+ // / \p NewFragment New fragment (absolute, non-relative).
5090
+ // / \p BitExtractAdjustment Offset to apply to any extract_bits op.
5091
+ static void
5092
+ insertNewDbgInst (DIBuilder &DIB, DbgDeclareInst *Orig, AllocaInst *NewAddr,
5093
+ DIExpression *NewAddrExpr, Instruction *BeforeInst,
5094
+ std::optional<DIExpression::FragmentInfo> NewFragment,
5095
+ int64_t BitExtractAdjustment) {
5096
+ if (NewFragment)
5097
+ NewAddrExpr = createOrReplaceFragment (NewAddrExpr, *NewFragment,
5098
+ BitExtractAdjustment);
5099
+ if (!NewAddrExpr)
5100
+ return ;
5101
+
5102
+ DIB.insertDeclare (NewAddr, Orig->getVariable (), NewAddrExpr,
4974
5103
Orig->getDebugLoc (), BeforeInst);
4975
5104
}
4976
- static void insertNewDbgInst (DIBuilder &DIB, DbgAssignIntrinsic *Orig,
4977
- AllocaInst *NewAddr, DIExpression *NewFragmentExpr,
4978
- Instruction *BeforeInst) {
5105
+
5106
+ // / Insert a new dbg.assign.
5107
+ // / \p Orig Original to copy debug loc, variable, value and value expression
5108
+ // / from.
5109
+ // / \p NewAddr Location's new base address.
5110
+ // / \p NewAddrExpr New expression to apply to address.
5111
+ // / \p BeforeInst Insert position.
5112
+ // / \p NewFragment New fragment (absolute, non-relative).
5113
+ // / \p BitExtractAdjustment Offset to apply to any extract_bits op.
5114
+ static void
5115
+ insertNewDbgInst (DIBuilder &DIB, DbgAssignIntrinsic *Orig, AllocaInst *NewAddr,
5116
+ DIExpression *NewAddrExpr, Instruction *BeforeInst,
5117
+ std::optional<DIExpression::FragmentInfo> NewFragment,
5118
+ int64_t BitExtractAdjustment) {
4979
5119
(void )BeforeInst;
5120
+
5121
+ // A dbg.assign puts fragment info in the value expression only. The address
5122
+ // expression has already been built: NewAddrExpr.
5123
+ DIExpression *NewFragmentExpr = Orig->getExpression ();
5124
+ if (NewFragment)
5125
+ NewFragmentExpr = createOrReplaceFragment (NewFragmentExpr, *NewFragment,
5126
+ BitExtractAdjustment);
5127
+ if (!NewFragmentExpr)
5128
+ return ;
5129
+
5130
+ // Apply a DIAssignID to the store if it doesn't already have it.
4980
5131
if (!NewAddr->hasMetadata (LLVMContext::MD_DIAssignID)) {
4981
5132
NewAddr->setMetadata (LLVMContext::MD_DIAssignID,
4982
5133
DIAssignID::getDistinct (NewAddr->getContext ()));
4983
5134
}
5135
+
4984
5136
Instruction *NewAssign =
4985
5137
DIB.insertDbgAssign (NewAddr, Orig->getValue (), Orig->getVariable (),
4986
- NewFragmentExpr, NewAddr,
4987
- Orig->getAddressExpression (), Orig-> getDebugLoc ())
5138
+ NewFragmentExpr, NewAddr, NewAddrExpr,
5139
+ Orig->getDebugLoc ())
4988
5140
.get <Instruction *>();
4989
5141
LLVM_DEBUG (dbgs () << " Created new assign intrinsic: " << *NewAssign << " \n " );
4990
5142
(void )NewAssign;
4991
5143
}
4992
- static void insertNewDbgInst (DIBuilder &DIB, DbgVariableRecord *Orig,
4993
- AllocaInst *NewAddr, DIExpression *NewFragmentExpr,
4994
- Instruction *BeforeInst) {
5144
+
5145
+ // / Insert a new DbgRecord.
5146
+ // / \p Orig Original to copy record type, debug loc and variable from, and
5147
+ // / additionally value and value expression for dbg_assign records.
5148
+ // / \p NewAddr Location's new base address.
5149
+ // / \p NewAddrExpr New expression to apply to address.
5150
+ // / \p BeforeInst Insert position.
5151
+ // / \p NewFragment New fragment (absolute, non-relative).
5152
+ // / \p BitExtractAdjustment Offset to apply to any extract_bits op.
5153
+ static void
5154
+ insertNewDbgInst (DIBuilder &DIB, DbgVariableRecord *Orig, AllocaInst *NewAddr,
5155
+ DIExpression *NewAddrExpr, Instruction *BeforeInst,
5156
+ std::optional<DIExpression::FragmentInfo> NewFragment,
5157
+ int64_t BitExtractAdjustment) {
4995
5158
(void )DIB;
5159
+
5160
+ // A dbg_assign puts fragment info in the value expression only. The address
5161
+ // expression has already been built: NewAddrExpr. A dbg_declare puts the
5162
+ // new fragment info into NewAddrExpr (as it only has one expression).
5163
+ DIExpression *NewFragmentExpr =
5164
+ Orig->isDbgAssign () ? Orig->getExpression () : NewAddrExpr;
5165
+ if (NewFragment)
5166
+ NewFragmentExpr = createOrReplaceFragment (NewFragmentExpr, *NewFragment,
5167
+ BitExtractAdjustment);
5168
+ if (!NewFragmentExpr)
5169
+ return ;
5170
+
4996
5171
if (Orig->isDbgDeclare ()) {
4997
5172
DbgVariableRecord *DVR = DbgVariableRecord::createDVRDeclare (
4998
5173
NewAddr, Orig->getVariable (), NewFragmentExpr, Orig->getDebugLoc ());
4999
5174
BeforeInst->getParent ()->insertDbgRecordBefore (DVR,
5000
5175
BeforeInst->getIterator ());
5001
5176
return ;
5002
5177
}
5178
+
5179
+ // Apply a DIAssignID to the store if it doesn't already have it.
5003
5180
if (!NewAddr->hasMetadata (LLVMContext::MD_DIAssignID)) {
5004
5181
NewAddr->setMetadata (LLVMContext::MD_DIAssignID,
5005
5182
DIAssignID::getDistinct (NewAddr->getContext ()));
5006
5183
}
5184
+
5007
5185
DbgVariableRecord *NewAssign = DbgVariableRecord::createLinkedDVRAssign (
5008
5186
NewAddr, Orig->getValue (), Orig->getVariable (), NewFragmentExpr, NewAddr,
5009
- Orig-> getAddressExpression () , Orig->getDebugLoc ());
5187
+ NewAddrExpr , Orig->getDebugLoc ());
5010
5188
LLVM_DEBUG (dbgs () << " Created new DVRAssign: " << *NewAssign << " \n " );
5011
5189
(void )NewAssign;
5012
5190
}
@@ -5019,7 +5197,7 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5019
5197
5020
5198
unsigned NumPartitions = 0 ;
5021
5199
bool Changed = false ;
5022
- const DataLayout &DL = AI.getDataLayout ();
5200
+ const DataLayout &DL = AI.getModule ()-> getDataLayout ();
5023
5201
5024
5202
// First try to pre-split loads and stores.
5025
5203
Changed |= presplitLoadsAndStores (AI, AS);
@@ -5110,57 +5288,79 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5110
5288
NumAllocaPartitions += NumPartitions;
5111
5289
MaxPartitionsPerAlloca.updateMax (NumPartitions);
5112
5290
5113
- // Migrate debug information from the old alloca to the new alloca(s)
5114
- // and the individual partitions.
5115
5291
auto MigrateOne = [&](auto *DbgVariable) {
5116
- auto *Expr = DbgVariable->getExpression ();
5117
- DIBuilder DIB (*AI.getModule (), /* AllowUnresolved*/ false );
5118
- uint64_t AllocaSize =
5119
- DL.getTypeSizeInBits (AI.getAllocatedType ()).getFixedValue ();
5120
- for (auto Fragment : Fragments) {
5121
- // Create a fragment expression describing the new partition or reuse AI's
5122
- // expression if there is only one partition.
5123
- auto *FragmentExpr = Expr;
5124
- if (Fragment.Size < AllocaSize || Expr->isFragment ()) {
5125
- // If this alloca is already a scalar replacement of a larger aggregate,
5126
- // Fragment.Offset describes the offset inside the scalar.
5127
- auto ExprFragment = Expr->getFragmentInfo ();
5128
- uint64_t Offset = ExprFragment ? ExprFragment->OffsetInBits : 0 ;
5129
- uint64_t Start = Offset + Fragment.Offset ;
5130
- uint64_t Size = Fragment.Size ;
5131
- if (ExprFragment) {
5132
- uint64_t AbsEnd =
5133
- ExprFragment->OffsetInBits + ExprFragment->SizeInBits ;
5134
- if (Start >= AbsEnd) {
5135
- // No need to describe a SROAed padding.
5136
- continue ;
5137
- }
5138
- Size = std::min (Size , AbsEnd - Start);
5139
- }
5140
- // The new, smaller fragment is stenciled out from the old fragment.
5141
- if (auto OrigFragment = FragmentExpr->getFragmentInfo ()) {
5142
- assert (Start >= OrigFragment->OffsetInBits &&
5143
- " new fragment is outside of original fragment" );
5144
- Start -= OrigFragment->OffsetInBits ;
5145
- }
5292
+ // Can't overlap with undef memory.
5293
+ if (isKillAddress (DbgVariable))
5294
+ return ;
5146
5295
5147
- // The alloca may be larger than the variable.
5148
- auto VarSize = DbgVariable->getVariable ()->getSizeInBits ();
5149
- if (VarSize) {
5150
- if (Size > *VarSize)
5151
- Size = *VarSize;
5152
- if (Size == 0 || Start + Size > *VarSize)
5153
- continue ;
5154
- }
5296
+ const Value *DbgPtr = getAddress (DbgVariable);
5297
+ DIExpression::FragmentInfo VarFrag =
5298
+ DbgVariable->getFragmentOrEntireVariable ();
5299
+ // Get the address expression constant offset if one exists and the ops
5300
+ // that come after it.
5301
+ int64_t CurrentExprOffsetInBytes = 0 ;
5302
+ SmallVector<uint64_t > PostOffsetOps;
5303
+ if (!getAddressExpression (DbgVariable)
5304
+ ->extractLeadingOffset (CurrentExprOffsetInBytes, PostOffsetOps))
5305
+ return ; // Couldn't interpret this DIExpression - drop the var.
5306
+
5307
+ // Offset defined by a DW_OP_LLVM_extract_bits_[sz]ext.
5308
+ int64_t ExtractOffsetInBits = 0 ;
5309
+ for (auto Op : getAddressExpression (DbgVariable)->expr_ops ()) {
5310
+ if (Op.getOp () == dwarf::DW_OP_LLVM_extract_bits_zext ||
5311
+ Op.getOp () == dwarf::DW_OP_LLVM_extract_bits_sext) {
5312
+ ExtractOffsetInBits = Op.getArg (0 );
5313
+ break ;
5314
+ }
5315
+ }
5155
5316
5156
- // Avoid creating a fragment expression that covers the entire variable.
5157
- if (!VarSize || *VarSize != Size ) {
5158
- if (auto E =
5159
- DIExpression::createFragmentExpression (Expr, Start, Size ))
5160
- FragmentExpr = *E;
5161
- else
5162
- continue ;
5163
- }
5317
+ DIBuilder DIB (*AI.getModule (), /* AllowUnresolved*/ false );
5318
+ for (auto Fragment : Fragments) {
5319
+ int64_t OffsetFromLocationInBits;
5320
+ std::optional<DIExpression::FragmentInfo> NewDbgFragment;
5321
+ // Find the variable fragment that the new alloca slice covers.
5322
+ // Drop debug info for this variable fragment if we can't compute an
5323
+ // intersect between it and the alloca slice.
5324
+ if (!DIExpression::calculateFragmentIntersect (
5325
+ DL, &AI, Fragment.Offset , Fragment.Size , DbgPtr,
5326
+ CurrentExprOffsetInBytes * 8 , ExtractOffsetInBits, VarFrag,
5327
+ NewDbgFragment, OffsetFromLocationInBits))
5328
+ continue ; // Do not migrate this fragment to this slice.
5329
+
5330
+ // Zero sized fragment indicates there's no intersect between the variable
5331
+ // fragment and the alloca slice. Skip this slice for this variable
5332
+ // fragment.
5333
+ if (NewDbgFragment && !NewDbgFragment->SizeInBits )
5334
+ continue ; // Do not migrate this fragment to this slice.
5335
+
5336
+ // No fragment indicates DbgVariable's variable or fragment exactly
5337
+ // overlaps the slice; copy its fragment (or nullopt if there isn't one).
5338
+ if (!NewDbgFragment)
5339
+ NewDbgFragment = DbgVariable->getFragment ();
5340
+
5341
+ // Reduce the new expression offset by the bit-extract offset since
5342
+ // we'll be keeping that.
5343
+ int64_t OffestFromNewAllocaInBits =
5344
+ OffsetFromLocationInBits - ExtractOffsetInBits;
5345
+ // We need to adjust an existing bit extract if the offset expression
5346
+ // can't eat the slack (i.e., if the new offset would be negative).
5347
+ int64_t BitExtractOffset =
5348
+ std::min<int64_t >(0 , OffestFromNewAllocaInBits);
5349
+ // The magnitude of a negative value indicates the number of bits into
5350
+ // the existing variable fragment that the memory region begins. The new
5351
+ // variable fragment already excludes those bits - the new DbgPtr offset
5352
+ // only needs to be applied if it's positive.
5353
+ OffestFromNewAllocaInBits =
5354
+ std::max (int64_t (0 ), OffestFromNewAllocaInBits);
5355
+
5356
+ // Rebuild the expression:
5357
+ // {Offset(OffestFromNewAllocaInBits), PostOffsetOps, NewDbgFragment}
5358
+ // Add NewDbgFragment later, because dbg.assigns don't want it in the
5359
+ // address expression but the value expression instead.
5360
+ DIExpression *NewExpr = DIExpression::get (AI.getContext (), PostOffsetOps);
5361
+ if (OffestFromNewAllocaInBits > 0 ) {
5362
+ int64_t OffsetInBytes = (OffestFromNewAllocaInBits + 7 ) / 8 ;
5363
+ NewExpr = DIExpression::prepend (NewExpr, /* flags=*/ 0 , OffsetInBytes);
5164
5364
}
5165
5365
5166
5366
// Remove any existing intrinsics on the new alloca describing
@@ -5177,7 +5377,8 @@ bool SROA::splitAlloca(AllocaInst &AI, AllocaSlices &AS) {
5177
5377
for_each (findDbgDeclares (Fragment.Alloca ), RemoveOne);
5178
5378
for_each (findDVRDeclares (Fragment.Alloca ), RemoveOne);
5179
5379
5180
- insertNewDbgInst (DIB, DbgVariable, Fragment.Alloca , FragmentExpr, &AI);
5380
+ insertNewDbgInst (DIB, DbgVariable, Fragment.Alloca , NewExpr, &AI,
5381
+ NewDbgFragment, BitExtractOffset);
5181
5382
}
5182
5383
};
5183
5384
0 commit comments