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